@cauthyhq/node 0.0.0 → 1.1.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +8 -0
  4. package/README.md +184 -1
  5. package/dist/cauthy-Bn-i7cKD.d.mts +1058 -0
  6. package/dist/cauthy-Wy-YDGrM.d.ts +1058 -0
  7. package/dist/express.d.mts +25 -0
  8. package/dist/express.d.ts +25 -0
  9. package/dist/express.js +103 -0
  10. package/dist/express.js.map +1 -0
  11. package/dist/express.mjs +77 -0
  12. package/dist/express.mjs.map +1 -0
  13. package/dist/fastify.d.mts +38 -0
  14. package/dist/fastify.d.ts +38 -0
  15. package/dist/fastify.js +105 -0
  16. package/dist/fastify.js.map +1 -0
  17. package/dist/fastify.mjs +79 -0
  18. package/dist/fastify.mjs.map +1 -0
  19. package/dist/hono.d.mts +24 -0
  20. package/dist/hono.d.ts +24 -0
  21. package/dist/hono.js +51 -0
  22. package/dist/hono.js.map +1 -0
  23. package/dist/hono.mjs +25 -0
  24. package/dist/hono.mjs.map +1 -0
  25. package/dist/index.d.mts +138 -0
  26. package/dist/index.d.ts +138 -0
  27. package/dist/index.js +3485 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/index.mjs +3421 -0
  30. package/dist/index.mjs.map +1 -0
  31. package/dist/keys-D5k0omTb.d.mts +64 -0
  32. package/dist/keys-D5k0omTb.d.ts +64 -0
  33. package/dist/keys.d.mts +8 -0
  34. package/dist/keys.d.ts +8 -0
  35. package/dist/keys.js +157 -0
  36. package/dist/keys.js.map +1 -0
  37. package/dist/keys.mjs +129 -0
  38. package/dist/keys.mjs.map +1 -0
  39. package/dist/mcp.d.mts +151 -0
  40. package/dist/mcp.d.ts +151 -0
  41. package/dist/mcp.js +410 -0
  42. package/dist/mcp.js.map +1 -0
  43. package/dist/mcp.mjs +382 -0
  44. package/dist/mcp.mjs.map +1 -0
  45. package/dist/next.d.mts +24 -0
  46. package/dist/next.d.ts +24 -0
  47. package/dist/next.js +77 -0
  48. package/dist/next.js.map +1 -0
  49. package/dist/next.mjs +52 -0
  50. package/dist/next.mjs.map +1 -0
  51. package/dist/testing.d.mts +74 -0
  52. package/dist/testing.d.ts +74 -0
  53. package/dist/testing.js +270 -0
  54. package/dist/testing.js.map +1 -0
  55. package/dist/testing.mjs +243 -0
  56. package/dist/testing.mjs.map +1 -0
  57. package/dist/theme.d.mts +183 -0
  58. package/dist/theme.d.ts +183 -0
  59. package/dist/theme.js +531 -0
  60. package/dist/theme.js.map +1 -0
  61. package/dist/theme.mjs +496 -0
  62. package/dist/theme.mjs.map +1 -0
  63. package/package.json +190 -4
@@ -0,0 +1,25 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { S as Session, C as Cauthy } from './cauthy-Bn-i7cKD.mjs';
3
+ import './keys-D5k0omTb.mjs';
4
+ import 'jose';
5
+ import './theme.mjs';
6
+
7
+ declare global {
8
+ namespace Express {
9
+ interface Request {
10
+ /** Who is signed in, or null. Asked once per request. */
11
+ cauthy(): Promise<Session | null>;
12
+ }
13
+ }
14
+ }
15
+ type Next = (error?: unknown) => void;
16
+ /**
17
+ * Serves the routes under the handler's `basePath` (and, by contract, the
18
+ * application's published key), and gives every other
19
+ * request `req.cauthy()`. Mount it once, before the routes that use it.
20
+ */
21
+ declare function cauthyExpress(auth: Cauthy): (req: IncomingMessage, res: ServerResponse, next: Next) => void;
22
+ /** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyExpress` mounted before it. */
23
+ declare function requireSession(req: IncomingMessage, res: ServerResponse, next: Next): void;
24
+
25
+ export { cauthyExpress, requireSession };
@@ -0,0 +1,25 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { S as Session, C as Cauthy } from './cauthy-Wy-YDGrM.js';
3
+ import './keys-D5k0omTb.js';
4
+ import 'jose';
5
+ import './theme.js';
6
+
7
+ declare global {
8
+ namespace Express {
9
+ interface Request {
10
+ /** Who is signed in, or null. Asked once per request. */
11
+ cauthy(): Promise<Session | null>;
12
+ }
13
+ }
14
+ }
15
+ type Next = (error?: unknown) => void;
16
+ /**
17
+ * Serves the routes under the handler's `basePath` (and, by contract, the
18
+ * application's published key), and gives every other
19
+ * request `req.cauthy()`. Mount it once, before the routes that use it.
20
+ */
21
+ declare function cauthyExpress(auth: Cauthy): (req: IncomingMessage, res: ServerResponse, next: Next) => void;
22
+ /** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyExpress` mounted before it. */
23
+ declare function requireSession(req: IncomingMessage, res: ServerResponse, next: Next): void;
24
+
25
+ export { cauthyExpress, requireSession };
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/express.ts
21
+ var express_exports = {};
22
+ __export(express_exports, {
23
+ cauthyExpress: () => cauthyExpress,
24
+ requireSession: () => requireSession
25
+ });
26
+ module.exports = __toCommonJS(express_exports);
27
+ function originOf(req) {
28
+ const secure = req.socket?.encrypted === true;
29
+ return `${req.protocol ?? (secure ? "https" : "http")}://${req.headers.host ?? "localhost"}`;
30
+ }
31
+ async function bodyOf(req) {
32
+ if (req.method === "GET" || req.method === "HEAD") return void 0;
33
+ if (req.body !== void 0 && req.body !== null) {
34
+ if (typeof req.body === "string") return req.body;
35
+ if (req.body instanceof Uint8Array) return new Uint8Array(req.body);
36
+ return JSON.stringify(req.body);
37
+ }
38
+ const chunks = [];
39
+ for await (const chunk of req) chunks.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
40
+ return chunks.length === 0 ? void 0 : new Blob(chunks);
41
+ }
42
+ async function toWebRequest(req, withBody) {
43
+ const headers = new Headers();
44
+ for (const [k, v] of Object.entries(req.headers)) {
45
+ if (Array.isArray(v)) for (const one of v) headers.append(k, one);
46
+ else if (v !== void 0) headers.set(k, v);
47
+ }
48
+ if (typeof req.ip === "string" && req.ip !== "") headers.set("x-forwarded-for", req.ip);
49
+ return new Request(new URL(req.originalUrl ?? req.url ?? "/", originOf(req)), {
50
+ method: req.method,
51
+ headers,
52
+ body: withBody ? await bodyOf(req) : void 0
53
+ });
54
+ }
55
+ function addCookies(res, cookies) {
56
+ if (cookies.length === 0 || res.headersSent) return;
57
+ const had = res.getHeader("set-cookie");
58
+ res.setHeader("set-cookie", [...Array.isArray(had) ? had : typeof had === "string" ? [had] : [], ...cookies]);
59
+ }
60
+ function cauthyExpress(auth) {
61
+ const base = auth.options.basePath;
62
+ const key = auth.pact?.contract.jwksPath;
63
+ return function cauthy(req, res, next) {
64
+ const request = req;
65
+ const path = (request.originalUrl ?? request.url ?? "/").split("?")[0];
66
+ if (path === base || path.startsWith(`${base}/`) || path === key) {
67
+ void (async () => {
68
+ const answer = await auth.handler(await toWebRequest(request, true));
69
+ res.statusCode = answer.status;
70
+ answer.headers.forEach((value, name) => {
71
+ if (name !== "set-cookie") res.setHeader(name, value);
72
+ });
73
+ addCookies(res, answer.headers.getSetCookie());
74
+ res.end(answer.body === null ? void 0 : Buffer.from(await answer.arrayBuffer()));
75
+ })().catch(next);
76
+ return;
77
+ }
78
+ let asked;
79
+ request.cauthy = () => asked ??= (async () => {
80
+ const resolved = await auth.resolve(await toWebRequest(request, false));
81
+ addCookies(res, resolved.cookies);
82
+ return resolved.session;
83
+ })();
84
+ next();
85
+ };
86
+ }
87
+ function requireSession(req, res, next) {
88
+ const ask = req.cauthy;
89
+ if (!ask) return next(new Error("@cauthyhq/node: mount cauthyExpress(auth) before requireSession"));
90
+ ask().then((session) => {
91
+ if (session !== null) return next();
92
+ res.statusCode = 401;
93
+ res.setHeader("content-type", "application/json; charset=utf-8");
94
+ res.setHeader("x-cauthy-session", "none");
95
+ res.end(JSON.stringify({ error: "unauthenticated" }));
96
+ }, next);
97
+ }
98
+ // Annotate the CommonJS export names for ESM import in node:
99
+ 0 && (module.exports = {
100
+ cauthyExpress,
101
+ requireSession
102
+ });
103
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/express.ts"],"sourcesContent":["// Express (and anything else that speaks Node's http): the routes, and who is\n// signed in on every request.\n//\n// app.use(cauthyExpress(auth))\n//\n// app.get('/api/me', async (req, res) => {\n// const session = await req.cauthy()\n// if (!session) return res.status(401).json({ error: 'unauthenticated' })\n// res.json(session.user)\n// })\n//\n// app.get('/api/books', requireSession, (req, res) => { … })\n//\n// A session that needs renewing is renewed on the spot, and its new cookie\n// leaves with whatever the route answers.\n\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n }\n}\n\n/** A request as Node gives it, with what Express adds when it is Express. */\ntype NodeRequest = IncomingMessage & { originalUrl?: string; protocol?: string; ip?: string; body?: unknown; cauthy?: () => Promise<Session | null> }\ntype Next = (error?: unknown) => void\n\nfunction originOf(req: NodeRequest): string {\n const secure = (req.socket as { encrypted?: boolean } | undefined)?.encrypted === true\n return `${req.protocol ?? (secure ? 'https' : 'http')}://${req.headers.host ?? 'localhost'}`\n}\n\nasync function bodyOf(req: NodeRequest): Promise<BodyInit | undefined> {\n if (req.method === 'GET' || req.method === 'HEAD') return undefined\n // A body parser was here first (express.json()): what it read is the body.\n if (req.body !== undefined && req.body !== null) {\n if (typeof req.body === 'string') return req.body\n if (req.body instanceof Uint8Array) return new Uint8Array(req.body)\n return JSON.stringify(req.body)\n }\n const chunks: Uint8Array[] = []\n for await (const chunk of req) chunks.push(typeof chunk === 'string' ? new TextEncoder().encode(chunk) : (chunk as Uint8Array))\n return chunks.length === 0 ? undefined : new Blob(chunks as BlobPart[])\n}\n\nasync function toWebRequest(req: NodeRequest, withBody: boolean): Promise<Request> {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // Express knows who is calling (it applies `trust proxy`): that address is\n // the one passed on to Cauthy, whatever the header claimed.\n if (typeof req.ip === 'string' && req.ip !== '') headers.set('x-forwarded-for', req.ip)\n return new Request(new URL(req.originalUrl ?? req.url ?? '/', originOf(req)), {\n method: req.method,\n headers,\n body: withBody ? await bodyOf(req) : undefined,\n })\n}\n\nfunction addCookies(res: ServerResponse, cookies: string[]): void {\n if (cookies.length === 0 || res.headersSent) return\n const had = res.getHeader('set-cookie')\n res.setHeader('set-cookie', [...(Array.isArray(had) ? had : typeof had === 'string' ? [had] : []), ...cookies])\n}\n\n/**\n * Serves the routes under the handler's `basePath` (and, by contract, the\n * application's published key), and gives every other\n * request `req.cauthy()`. Mount it once, before the routes that use it.\n */\nexport function cauthyExpress(auth: Cauthy) {\n const base = auth.options.basePath\n // By contract the application also publishes its key, outside basePath.\n const key = auth.pact?.contract.jwksPath\n return function cauthy(req: IncomingMessage, res: ServerResponse, next: Next): void {\n const request = req as NodeRequest\n const path = (request.originalUrl ?? request.url ?? '/').split('?')[0]\n\n if (path === base || path.startsWith(`${base}/`) || path === key) {\n void (async () => {\n const answer = await auth.handler(await toWebRequest(request, true))\n res.statusCode = answer.status\n answer.headers.forEach((value, name) => {\n if (name !== 'set-cookie') res.setHeader(name, value)\n })\n addCookies(res, answer.headers.getSetCookie())\n res.end(answer.body === null ? undefined : Buffer.from(await answer.arrayBuffer()))\n })().catch(next)\n return\n }\n\n let asked: Promise<Session | null> | undefined\n request.cauthy = () =>\n (asked ??= (async () => {\n const resolved = await auth.resolve(await toWebRequest(request, false))\n addCookies(res, resolved.cookies)\n return resolved.session\n })())\n next()\n }\n}\n\n/** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyExpress` mounted before it. */\nexport function requireSession(req: IncomingMessage, res: ServerResponse, next: Next): void {\n const ask = (req as NodeRequest).cauthy\n if (!ask) return next(new Error('@cauthyhq/node: mount cauthyExpress(auth) before requireSession'))\n ask().then((session) => {\n if (session !== null) return next()\n res.statusCode = 401\n res.setHeader('content-type', 'application/json; charset=utf-8')\n res.setHeader('x-cauthy-session', 'none')\n res.end(JSON.stringify({ error: 'unauthenticated' }))\n }, next)\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,77 @@
1
+ // src/express.ts
2
+ function originOf(req) {
3
+ const secure = req.socket?.encrypted === true;
4
+ return `${req.protocol ?? (secure ? "https" : "http")}://${req.headers.host ?? "localhost"}`;
5
+ }
6
+ async function bodyOf(req) {
7
+ if (req.method === "GET" || req.method === "HEAD") return void 0;
8
+ if (req.body !== void 0 && req.body !== null) {
9
+ if (typeof req.body === "string") return req.body;
10
+ if (req.body instanceof Uint8Array) return new Uint8Array(req.body);
11
+ return JSON.stringify(req.body);
12
+ }
13
+ const chunks = [];
14
+ for await (const chunk of req) chunks.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
15
+ return chunks.length === 0 ? void 0 : new Blob(chunks);
16
+ }
17
+ async function toWebRequest(req, withBody) {
18
+ const headers = new Headers();
19
+ for (const [k, v] of Object.entries(req.headers)) {
20
+ if (Array.isArray(v)) for (const one of v) headers.append(k, one);
21
+ else if (v !== void 0) headers.set(k, v);
22
+ }
23
+ if (typeof req.ip === "string" && req.ip !== "") headers.set("x-forwarded-for", req.ip);
24
+ return new Request(new URL(req.originalUrl ?? req.url ?? "/", originOf(req)), {
25
+ method: req.method,
26
+ headers,
27
+ body: withBody ? await bodyOf(req) : void 0
28
+ });
29
+ }
30
+ function addCookies(res, cookies) {
31
+ if (cookies.length === 0 || res.headersSent) return;
32
+ const had = res.getHeader("set-cookie");
33
+ res.setHeader("set-cookie", [...Array.isArray(had) ? had : typeof had === "string" ? [had] : [], ...cookies]);
34
+ }
35
+ function cauthyExpress(auth) {
36
+ const base = auth.options.basePath;
37
+ const key = auth.pact?.contract.jwksPath;
38
+ return function cauthy(req, res, next) {
39
+ const request = req;
40
+ const path = (request.originalUrl ?? request.url ?? "/").split("?")[0];
41
+ if (path === base || path.startsWith(`${base}/`) || path === key) {
42
+ void (async () => {
43
+ const answer = await auth.handler(await toWebRequest(request, true));
44
+ res.statusCode = answer.status;
45
+ answer.headers.forEach((value, name) => {
46
+ if (name !== "set-cookie") res.setHeader(name, value);
47
+ });
48
+ addCookies(res, answer.headers.getSetCookie());
49
+ res.end(answer.body === null ? void 0 : Buffer.from(await answer.arrayBuffer()));
50
+ })().catch(next);
51
+ return;
52
+ }
53
+ let asked;
54
+ request.cauthy = () => asked ??= (async () => {
55
+ const resolved = await auth.resolve(await toWebRequest(request, false));
56
+ addCookies(res, resolved.cookies);
57
+ return resolved.session;
58
+ })();
59
+ next();
60
+ };
61
+ }
62
+ function requireSession(req, res, next) {
63
+ const ask = req.cauthy;
64
+ if (!ask) return next(new Error("@cauthyhq/node: mount cauthyExpress(auth) before requireSession"));
65
+ ask().then((session) => {
66
+ if (session !== null) return next();
67
+ res.statusCode = 401;
68
+ res.setHeader("content-type", "application/json; charset=utf-8");
69
+ res.setHeader("x-cauthy-session", "none");
70
+ res.end(JSON.stringify({ error: "unauthenticated" }));
71
+ }, next);
72
+ }
73
+ export {
74
+ cauthyExpress,
75
+ requireSession
76
+ };
77
+ //# sourceMappingURL=express.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/express.ts"],"sourcesContent":["// Express (and anything else that speaks Node's http): the routes, and who is\n// signed in on every request.\n//\n// app.use(cauthyExpress(auth))\n//\n// app.get('/api/me', async (req, res) => {\n// const session = await req.cauthy()\n// if (!session) return res.status(401).json({ error: 'unauthenticated' })\n// res.json(session.user)\n// })\n//\n// app.get('/api/books', requireSession, (req, res) => { … })\n//\n// A session that needs renewing is renewed on the spot, and its new cookie\n// leaves with whatever the route answers.\n\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n }\n}\n\n/** A request as Node gives it, with what Express adds when it is Express. */\ntype NodeRequest = IncomingMessage & { originalUrl?: string; protocol?: string; ip?: string; body?: unknown; cauthy?: () => Promise<Session | null> }\ntype Next = (error?: unknown) => void\n\nfunction originOf(req: NodeRequest): string {\n const secure = (req.socket as { encrypted?: boolean } | undefined)?.encrypted === true\n return `${req.protocol ?? (secure ? 'https' : 'http')}://${req.headers.host ?? 'localhost'}`\n}\n\nasync function bodyOf(req: NodeRequest): Promise<BodyInit | undefined> {\n if (req.method === 'GET' || req.method === 'HEAD') return undefined\n // A body parser was here first (express.json()): what it read is the body.\n if (req.body !== undefined && req.body !== null) {\n if (typeof req.body === 'string') return req.body\n if (req.body instanceof Uint8Array) return new Uint8Array(req.body)\n return JSON.stringify(req.body)\n }\n const chunks: Uint8Array[] = []\n for await (const chunk of req) chunks.push(typeof chunk === 'string' ? new TextEncoder().encode(chunk) : (chunk as Uint8Array))\n return chunks.length === 0 ? undefined : new Blob(chunks as BlobPart[])\n}\n\nasync function toWebRequest(req: NodeRequest, withBody: boolean): Promise<Request> {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // Express knows who is calling (it applies `trust proxy`): that address is\n // the one passed on to Cauthy, whatever the header claimed.\n if (typeof req.ip === 'string' && req.ip !== '') headers.set('x-forwarded-for', req.ip)\n return new Request(new URL(req.originalUrl ?? req.url ?? '/', originOf(req)), {\n method: req.method,\n headers,\n body: withBody ? await bodyOf(req) : undefined,\n })\n}\n\nfunction addCookies(res: ServerResponse, cookies: string[]): void {\n if (cookies.length === 0 || res.headersSent) return\n const had = res.getHeader('set-cookie')\n res.setHeader('set-cookie', [...(Array.isArray(had) ? had : typeof had === 'string' ? [had] : []), ...cookies])\n}\n\n/**\n * Serves the routes under the handler's `basePath` (and, by contract, the\n * application's published key), and gives every other\n * request `req.cauthy()`. Mount it once, before the routes that use it.\n */\nexport function cauthyExpress(auth: Cauthy) {\n const base = auth.options.basePath\n // By contract the application also publishes its key, outside basePath.\n const key = auth.pact?.contract.jwksPath\n return function cauthy(req: IncomingMessage, res: ServerResponse, next: Next): void {\n const request = req as NodeRequest\n const path = (request.originalUrl ?? request.url ?? '/').split('?')[0]\n\n if (path === base || path.startsWith(`${base}/`) || path === key) {\n void (async () => {\n const answer = await auth.handler(await toWebRequest(request, true))\n res.statusCode = answer.status\n answer.headers.forEach((value, name) => {\n if (name !== 'set-cookie') res.setHeader(name, value)\n })\n addCookies(res, answer.headers.getSetCookie())\n res.end(answer.body === null ? undefined : Buffer.from(await answer.arrayBuffer()))\n })().catch(next)\n return\n }\n\n let asked: Promise<Session | null> | undefined\n request.cauthy = () =>\n (asked ??= (async () => {\n const resolved = await auth.resolve(await toWebRequest(request, false))\n addCookies(res, resolved.cookies)\n return resolved.session\n })())\n next()\n }\n}\n\n/** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyExpress` mounted before it. */\nexport function requireSession(req: IncomingMessage, res: ServerResponse, next: Next): void {\n const ask = (req as NodeRequest).cauthy\n if (!ask) return next(new Error('@cauthyhq/node: mount cauthyExpress(auth) before requireSession'))\n ask().then((session) => {\n if (session !== null) return next()\n res.statusCode = 401\n res.setHeader('content-type', 'application/json; charset=utf-8')\n res.setHeader('x-cauthy-session', 'none')\n res.end(JSON.stringify({ error: 'unauthenticated' }))\n }, next)\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,38 @@
1
+ import { FastifyReply, FastifyPluginAsync, FastifyInstance } from 'fastify';
2
+ import { S as Session, C as Cauthy } from './cauthy-Bn-i7cKD.mjs';
3
+ import './keys-D5k0omTb.mjs';
4
+ import 'jose';
5
+ import './theme.mjs';
6
+
7
+ declare module 'fastify' {
8
+ interface FastifyRequest {
9
+ /** Who is signed in, or null. Asked once per request. */
10
+ cauthy(): Promise<Session | null>;
11
+ }
12
+ interface FastifyInstance {
13
+ /** A preHandler that answers 401 unless somebody is signed in. */
14
+ requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>;
15
+ }
16
+ }
17
+ interface CauthyFastifyOptions {
18
+ auth: Cauthy;
19
+ /**
20
+ * Check, when Fastify is ready, that this plugin is what answers under
21
+ * basePath (`checkFastifyMount`), and fail startup when another route
22
+ * does. Default: true.
23
+ */
24
+ checkMount?: boolean;
25
+ }
26
+ declare const plugin: FastifyPluginAsync<CauthyFastifyOptions>;
27
+ /**
28
+ * Checks that the plugin is what answers under basePath, in process, once
29
+ * Fastify is ready (the plugin already does it by itself at `onReady`; this
30
+ * is for tests and for `checkMount: false`):
31
+ *
32
+ * await app.ready()
33
+ * await checkFastifyMount(app, auth)
34
+ */
35
+ declare function checkFastifyMount(app: FastifyInstance, auth: Cauthy): Promise<void>;
36
+ declare const cauthyFastify: FastifyPluginAsync<CauthyFastifyOptions>;
37
+
38
+ export { type CauthyFastifyOptions, cauthyFastify, checkFastifyMount, plugin as default };
@@ -0,0 +1,38 @@
1
+ import { FastifyReply, FastifyPluginAsync, FastifyInstance } from 'fastify';
2
+ import { S as Session, C as Cauthy } from './cauthy-Wy-YDGrM.js';
3
+ import './keys-D5k0omTb.js';
4
+ import 'jose';
5
+ import './theme.js';
6
+
7
+ declare module 'fastify' {
8
+ interface FastifyRequest {
9
+ /** Who is signed in, or null. Asked once per request. */
10
+ cauthy(): Promise<Session | null>;
11
+ }
12
+ interface FastifyInstance {
13
+ /** A preHandler that answers 401 unless somebody is signed in. */
14
+ requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>;
15
+ }
16
+ }
17
+ interface CauthyFastifyOptions {
18
+ auth: Cauthy;
19
+ /**
20
+ * Check, when Fastify is ready, that this plugin is what answers under
21
+ * basePath (`checkFastifyMount`), and fail startup when another route
22
+ * does. Default: true.
23
+ */
24
+ checkMount?: boolean;
25
+ }
26
+ declare const plugin: FastifyPluginAsync<CauthyFastifyOptions>;
27
+ /**
28
+ * Checks that the plugin is what answers under basePath, in process, once
29
+ * Fastify is ready (the plugin already does it by itself at `onReady`; this
30
+ * is for tests and for `checkMount: false`):
31
+ *
32
+ * await app.ready()
33
+ * await checkFastifyMount(app, auth)
34
+ */
35
+ declare function checkFastifyMount(app: FastifyInstance, auth: Cauthy): Promise<void>;
36
+ declare const cauthyFastify: FastifyPluginAsync<CauthyFastifyOptions>;
37
+
38
+ export { type CauthyFastifyOptions, cauthyFastify, checkFastifyMount, plugin as default };
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/fastify.ts
21
+ var fastify_exports = {};
22
+ __export(fastify_exports, {
23
+ cauthyFastify: () => cauthyFastify,
24
+ checkFastifyMount: () => checkFastifyMount,
25
+ default: () => fastify_default
26
+ });
27
+ module.exports = __toCommonJS(fastify_exports);
28
+ var import_node_http = require("http");
29
+ function originOf(req) {
30
+ return `${req.protocol}://${req.headers.host ?? "localhost"}`;
31
+ }
32
+ function toWebRequest(req) {
33
+ const headers = new Headers();
34
+ for (const [k, v] of Object.entries(req.headers)) {
35
+ if (Array.isArray(v)) for (const one of v) headers.append(k, one);
36
+ else if (v !== void 0) headers.set(k, v);
37
+ }
38
+ headers.set("x-forwarded-for", req.ip);
39
+ const body = req.method === "GET" || req.method === "HEAD" || req.body === void 0 || req.body === null ? void 0 : typeof req.body === "string" ? req.body : JSON.stringify(req.body);
40
+ return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body });
41
+ }
42
+ var kSession = /* @__PURE__ */ Symbol("cauthy.session");
43
+ var kReply = /* @__PURE__ */ Symbol("cauthy.reply");
44
+ var plugin = async (app, { auth, checkMount = true }) => {
45
+ const base = auth.options.basePath;
46
+ app.decorateRequest("cauthy", async function() {
47
+ const self = this;
48
+ self[kSession] ??= (async () => {
49
+ const resolved = await auth.resolve(toWebRequest(this));
50
+ const reply = this[kReply];
51
+ if (resolved.cookies.length > 0 && reply) reply.header("set-cookie", resolved.cookies);
52
+ return resolved.session;
53
+ })();
54
+ return self[kSession];
55
+ });
56
+ app.addHook("onRequest", async (req, reply) => {
57
+ ;
58
+ req[kReply] = reply;
59
+ });
60
+ app.decorate("requireSession", async function(request, reply) {
61
+ if (await request.cauthy() === null) {
62
+ await reply.code(401).header("x-cauthy-session", "none").send({ error: "unauthenticated" });
63
+ }
64
+ });
65
+ const serve = async (req, reply) => {
66
+ const res = await auth.handler(toWebRequest(req));
67
+ reply.code(res.status);
68
+ res.headers.forEach((value, name) => {
69
+ if (name !== "set-cookie") reply.header(name, value);
70
+ });
71
+ const cookies = res.headers.getSetCookie();
72
+ if (cookies.length > 0) reply.header("set-cookie", cookies);
73
+ return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()));
74
+ };
75
+ app.route({ method: ["GET", "POST"], url: `${base}/*`, handler: serve });
76
+ const key = auth.pact?.contract.jwksPath;
77
+ if (key) app.route({ method: ["GET", "HEAD", "POST"], url: key, handler: serve });
78
+ if (checkMount && process.env.NODE_ENV !== "test") app.addHook("onReady", () => probe(app, auth));
79
+ };
80
+ async function probe(app, auth) {
81
+ const server = (0, import_node_http.createServer)((req, res) => app.routing(req, res));
82
+ await new Promise((resolve, reject) => {
83
+ server.once("error", reject);
84
+ server.listen(0, "127.0.0.1", resolve);
85
+ });
86
+ try {
87
+ await auth.checkMount(`http://127.0.0.1:${server.address().port}`);
88
+ } finally {
89
+ server.closeAllConnections();
90
+ await new Promise((resolve) => server.close(() => resolve()));
91
+ }
92
+ }
93
+ function checkFastifyMount(app, auth) {
94
+ return probe(app, auth);
95
+ }
96
+ plugin[/* @__PURE__ */ Symbol.for("skip-override")] = true;
97
+ plugin[/* @__PURE__ */ Symbol.for("fastify.display-name")] = "@cauthyhq/node";
98
+ var cauthyFastify = plugin;
99
+ var fastify_default = plugin;
100
+ // Annotate the CommonJS export names for ESM import in node:
101
+ 0 && (module.exports = {
102
+ cauthyFastify,
103
+ checkFastifyMount
104
+ });
105
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fastify.ts"],"sourcesContent":["// Fastify: the routes, and who is signed in on every request.\n//\n// await app.register(cauthyFastify, { auth })\n//\n// app.get('/api/me', async (req, reply) => {\n// const session = await req.cauthy()\n// if (!session) return reply.code(401).send({ error: 'unauthenticated' })\n// return session.user\n// })\n//\n// app.get('/api/books', { preHandler: app.requireSession }, async (req) => { … })\n//\n// Here a session that needs renewing is renewed on the spot: Fastify has the\n// reply in hand, so the new cookie always goes back.\n\nimport { createServer } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n interface FastifyInstance {\n /** A preHandler that answers 401 unless somebody is signed in. */\n requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>\n }\n}\n\nexport interface CauthyFastifyOptions {\n auth: Cauthy\n /**\n * Check, when Fastify is ready, that this plugin is what answers under\n * basePath (`checkFastifyMount`), and fail startup when another route\n * does. Default: true.\n */\n checkMount?: boolean\n}\n\nfunction originOf(req: FastifyRequest): string {\n return `${req.protocol}://${req.headers.host ?? 'localhost'}`\n}\n\nfunction toWebRequest(req: FastifyRequest): Request {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // Fastify knows who is calling (it applies `trustProxy`): that address is\n // the one passed on to Cauthy, whatever the header claimed.\n headers.set('x-forwarded-for', req.ip)\n // What Fastify parsed is the body: the application's own sign-in screens post JSON.\n const body = req.method === 'GET' || req.method === 'HEAD' || req.body === undefined || req.body === null\n ? undefined\n : typeof req.body === 'string' ? req.body : JSON.stringify(req.body)\n return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body })\n}\n\nconst kSession = Symbol('cauthy.session')\nconst kReply = Symbol('cauthy.reply')\n\nconst plugin: FastifyPluginAsync<CauthyFastifyOptions> = async (app: FastifyInstance, { auth, checkMount = true }) => {\n const base = auth.options.basePath\n\n app.decorateRequest('cauthy', async function (this: FastifyRequest): Promise<Session | null> {\n const self = this as FastifyRequest & { [kSession]?: Promise<Session | null> }\n self[kSession] ??= (async () => {\n const resolved = await auth.resolve(toWebRequest(this))\n // Set through the raw response so the cookie leaves whatever the route\n // answers with, even an error.\n const reply = (this as FastifyRequest & { [kReply]?: FastifyReply })[kReply]\n if (resolved.cookies.length > 0 && reply) reply.header('set-cookie', resolved.cookies)\n return resolved.session\n })()\n return self[kSession]\n })\n\n app.addHook('onRequest', async (req, reply) => {\n ;(req as FastifyRequest & { [kReply]?: FastifyReply })[kReply] = reply\n })\n\n app.decorate('requireSession', async function (request: FastifyRequest, reply: FastifyReply): Promise<void> {\n if ((await request.cauthy()) === null) {\n await reply.code(401).header('x-cauthy-session', 'none').send({ error: 'unauthenticated' })\n }\n })\n\n const serve = async (req: FastifyRequest, reply: FastifyReply) => {\n const res = await auth.handler(toWebRequest(req))\n reply.code(res.status)\n res.headers.forEach((value, name) => {\n if (name !== 'set-cookie') reply.header(name, value)\n })\n const cookies = res.headers.getSetCookie()\n if (cookies.length > 0) reply.header('set-cookie', cookies)\n return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()))\n }\n app.route({ method: ['GET', 'POST'], url: `${base}/*`, handler: serve })\n // By contract the application also publishes its key, outside basePath.\n const key = auth.pact?.contract.jwksPath\n if (key) app.route({ method: ['GET', 'HEAD', 'POST'], url: key, handler: serve })\n // Tests build many apps with routes of their own, and mount nothing for real.\n if (checkMount && process.env.NODE_ENV !== 'test') app.addHook('onReady', () => probe(app, auth))\n}\n\n/**\n * Sends the probes of checkMount through Fastify's own router, over a private\n * loopback socket that only lives for the check. Not `app.inject`: inside\n * `onReady` it would wait for the very ready it runs in.\n */\nasync function probe(app: FastifyInstance, auth: Cauthy): Promise<void> {\n const server = createServer((req, res) => app.routing(req, res))\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(0, '127.0.0.1', resolve)\n })\n try {\n await auth.checkMount(`http://127.0.0.1:${(server.address() as AddressInfo).port}`)\n } finally {\n server.closeAllConnections()\n await new Promise<void>((resolve) => server.close(() => resolve()))\n }\n}\n\n/**\n * Checks that the plugin is what answers under basePath, in process, once\n * Fastify is ready (the plugin already does it by itself at `onReady`; this\n * is for tests and for `checkMount: false`):\n *\n * await app.ready()\n * await checkFastifyMount(app, auth)\n */\nexport function checkFastifyMount(app: FastifyInstance, auth: Cauthy): Promise<void> {\n return probe(app, auth)\n}\n\n\n// Outside encapsulation: `req.cauthy()` and `requireSession` are for the whole\n// application, not only for routes registered beside this plugin.\n;(plugin as unknown as Record<symbol, boolean>)[Symbol.for('skip-override')] = true\n;(plugin as unknown as Record<symbol, unknown>)[Symbol.for('fastify.display-name')] = '@cauthyhq/node'\n\nexport const cauthyFastify = plugin\nexport default plugin\n"],"mappings":"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","names":[]}
@@ -0,0 +1,79 @@
1
+ // src/fastify.ts
2
+ import { createServer } from "http";
3
+ function originOf(req) {
4
+ return `${req.protocol}://${req.headers.host ?? "localhost"}`;
5
+ }
6
+ function toWebRequest(req) {
7
+ const headers = new Headers();
8
+ for (const [k, v] of Object.entries(req.headers)) {
9
+ if (Array.isArray(v)) for (const one of v) headers.append(k, one);
10
+ else if (v !== void 0) headers.set(k, v);
11
+ }
12
+ headers.set("x-forwarded-for", req.ip);
13
+ const body = req.method === "GET" || req.method === "HEAD" || req.body === void 0 || req.body === null ? void 0 : typeof req.body === "string" ? req.body : JSON.stringify(req.body);
14
+ return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body });
15
+ }
16
+ var kSession = /* @__PURE__ */ Symbol("cauthy.session");
17
+ var kReply = /* @__PURE__ */ Symbol("cauthy.reply");
18
+ var plugin = async (app, { auth, checkMount = true }) => {
19
+ const base = auth.options.basePath;
20
+ app.decorateRequest("cauthy", async function() {
21
+ const self = this;
22
+ self[kSession] ??= (async () => {
23
+ const resolved = await auth.resolve(toWebRequest(this));
24
+ const reply = this[kReply];
25
+ if (resolved.cookies.length > 0 && reply) reply.header("set-cookie", resolved.cookies);
26
+ return resolved.session;
27
+ })();
28
+ return self[kSession];
29
+ });
30
+ app.addHook("onRequest", async (req, reply) => {
31
+ ;
32
+ req[kReply] = reply;
33
+ });
34
+ app.decorate("requireSession", async function(request, reply) {
35
+ if (await request.cauthy() === null) {
36
+ await reply.code(401).header("x-cauthy-session", "none").send({ error: "unauthenticated" });
37
+ }
38
+ });
39
+ const serve = async (req, reply) => {
40
+ const res = await auth.handler(toWebRequest(req));
41
+ reply.code(res.status);
42
+ res.headers.forEach((value, name) => {
43
+ if (name !== "set-cookie") reply.header(name, value);
44
+ });
45
+ const cookies = res.headers.getSetCookie();
46
+ if (cookies.length > 0) reply.header("set-cookie", cookies);
47
+ return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()));
48
+ };
49
+ app.route({ method: ["GET", "POST"], url: `${base}/*`, handler: serve });
50
+ const key = auth.pact?.contract.jwksPath;
51
+ if (key) app.route({ method: ["GET", "HEAD", "POST"], url: key, handler: serve });
52
+ if (checkMount && process.env.NODE_ENV !== "test") app.addHook("onReady", () => probe(app, auth));
53
+ };
54
+ async function probe(app, auth) {
55
+ const server = createServer((req, res) => app.routing(req, res));
56
+ await new Promise((resolve, reject) => {
57
+ server.once("error", reject);
58
+ server.listen(0, "127.0.0.1", resolve);
59
+ });
60
+ try {
61
+ await auth.checkMount(`http://127.0.0.1:${server.address().port}`);
62
+ } finally {
63
+ server.closeAllConnections();
64
+ await new Promise((resolve) => server.close(() => resolve()));
65
+ }
66
+ }
67
+ function checkFastifyMount(app, auth) {
68
+ return probe(app, auth);
69
+ }
70
+ plugin[/* @__PURE__ */ Symbol.for("skip-override")] = true;
71
+ plugin[/* @__PURE__ */ Symbol.for("fastify.display-name")] = "@cauthyhq/node";
72
+ var cauthyFastify = plugin;
73
+ var fastify_default = plugin;
74
+ export {
75
+ cauthyFastify,
76
+ checkFastifyMount,
77
+ fastify_default as default
78
+ };
79
+ //# sourceMappingURL=fastify.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fastify.ts"],"sourcesContent":["// Fastify: the routes, and who is signed in on every request.\n//\n// await app.register(cauthyFastify, { auth })\n//\n// app.get('/api/me', async (req, reply) => {\n// const session = await req.cauthy()\n// if (!session) return reply.code(401).send({ error: 'unauthenticated' })\n// return session.user\n// })\n//\n// app.get('/api/books', { preHandler: app.requireSession }, async (req) => { … })\n//\n// Here a session that needs renewing is renewed on the spot: Fastify has the\n// reply in hand, so the new cookie always goes back.\n\nimport { createServer } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n interface FastifyInstance {\n /** A preHandler that answers 401 unless somebody is signed in. */\n requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>\n }\n}\n\nexport interface CauthyFastifyOptions {\n auth: Cauthy\n /**\n * Check, when Fastify is ready, that this plugin is what answers under\n * basePath (`checkFastifyMount`), and fail startup when another route\n * does. Default: true.\n */\n checkMount?: boolean\n}\n\nfunction originOf(req: FastifyRequest): string {\n return `${req.protocol}://${req.headers.host ?? 'localhost'}`\n}\n\nfunction toWebRequest(req: FastifyRequest): Request {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // Fastify knows who is calling (it applies `trustProxy`): that address is\n // the one passed on to Cauthy, whatever the header claimed.\n headers.set('x-forwarded-for', req.ip)\n // What Fastify parsed is the body: the application's own sign-in screens post JSON.\n const body = req.method === 'GET' || req.method === 'HEAD' || req.body === undefined || req.body === null\n ? undefined\n : typeof req.body === 'string' ? req.body : JSON.stringify(req.body)\n return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body })\n}\n\nconst kSession = Symbol('cauthy.session')\nconst kReply = Symbol('cauthy.reply')\n\nconst plugin: FastifyPluginAsync<CauthyFastifyOptions> = async (app: FastifyInstance, { auth, checkMount = true }) => {\n const base = auth.options.basePath\n\n app.decorateRequest('cauthy', async function (this: FastifyRequest): Promise<Session | null> {\n const self = this as FastifyRequest & { [kSession]?: Promise<Session | null> }\n self[kSession] ??= (async () => {\n const resolved = await auth.resolve(toWebRequest(this))\n // Set through the raw response so the cookie leaves whatever the route\n // answers with, even an error.\n const reply = (this as FastifyRequest & { [kReply]?: FastifyReply })[kReply]\n if (resolved.cookies.length > 0 && reply) reply.header('set-cookie', resolved.cookies)\n return resolved.session\n })()\n return self[kSession]\n })\n\n app.addHook('onRequest', async (req, reply) => {\n ;(req as FastifyRequest & { [kReply]?: FastifyReply })[kReply] = reply\n })\n\n app.decorate('requireSession', async function (request: FastifyRequest, reply: FastifyReply): Promise<void> {\n if ((await request.cauthy()) === null) {\n await reply.code(401).header('x-cauthy-session', 'none').send({ error: 'unauthenticated' })\n }\n })\n\n const serve = async (req: FastifyRequest, reply: FastifyReply) => {\n const res = await auth.handler(toWebRequest(req))\n reply.code(res.status)\n res.headers.forEach((value, name) => {\n if (name !== 'set-cookie') reply.header(name, value)\n })\n const cookies = res.headers.getSetCookie()\n if (cookies.length > 0) reply.header('set-cookie', cookies)\n return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()))\n }\n app.route({ method: ['GET', 'POST'], url: `${base}/*`, handler: serve })\n // By contract the application also publishes its key, outside basePath.\n const key = auth.pact?.contract.jwksPath\n if (key) app.route({ method: ['GET', 'HEAD', 'POST'], url: key, handler: serve })\n // Tests build many apps with routes of their own, and mount nothing for real.\n if (checkMount && process.env.NODE_ENV !== 'test') app.addHook('onReady', () => probe(app, auth))\n}\n\n/**\n * Sends the probes of checkMount through Fastify's own router, over a private\n * loopback socket that only lives for the check. Not `app.inject`: inside\n * `onReady` it would wait for the very ready it runs in.\n */\nasync function probe(app: FastifyInstance, auth: Cauthy): Promise<void> {\n const server = createServer((req, res) => app.routing(req, res))\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(0, '127.0.0.1', resolve)\n })\n try {\n await auth.checkMount(`http://127.0.0.1:${(server.address() as AddressInfo).port}`)\n } finally {\n server.closeAllConnections()\n await new Promise<void>((resolve) => server.close(() => resolve()))\n }\n}\n\n/**\n * Checks that the plugin is what answers under basePath, in process, once\n * Fastify is ready (the plugin already does it by itself at `onReady`; this\n * is for tests and for `checkMount: false`):\n *\n * await app.ready()\n * await checkFastifyMount(app, auth)\n */\nexport function checkFastifyMount(app: FastifyInstance, auth: Cauthy): Promise<void> {\n return probe(app, auth)\n}\n\n\n// Outside encapsulation: `req.cauthy()` and `requireSession` are for the whole\n// application, not only for routes registered beside this plugin.\n;(plugin as unknown as Record<symbol, boolean>)[Symbol.for('skip-override')] = true\n;(plugin as unknown as Record<symbol, unknown>)[Symbol.for('fastify.display-name')] = '@cauthyhq/node'\n\nexport const cauthyFastify = plugin\nexport default plugin\n"],"mappings":"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","names":[]}
@@ -0,0 +1,24 @@
1
+ import { MiddlewareHandler } from 'hono';
2
+ import { S as Session, C as Cauthy } from './cauthy-Bn-i7cKD.mjs';
3
+ import './keys-D5k0omTb.mjs';
4
+ import 'jose';
5
+ import './theme.mjs';
6
+
7
+ /** What the middleware keeps on the context: `new Hono<{ Variables: CauthyVariables }>()`. */
8
+ interface CauthyVariables {
9
+ /** Who is signed in, or null. */
10
+ session: Session | null;
11
+ }
12
+ type Env = {
13
+ Variables: CauthyVariables;
14
+ };
15
+ /**
16
+ * Serves the routes under the handler's `basePath` (and, by contract, the
17
+ * application's published key), and sets `session` for
18
+ * every other request. Mount it once, before the routes that use it.
19
+ */
20
+ declare function cauthyHono(auth: Cauthy): MiddlewareHandler<Env>;
21
+ /** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyHono` mounted before it. */
22
+ declare const requireSession: MiddlewareHandler<Env>;
23
+
24
+ export { type CauthyVariables, cauthyHono, requireSession };
package/dist/hono.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { MiddlewareHandler } from 'hono';
2
+ import { S as Session, C as Cauthy } from './cauthy-Wy-YDGrM.js';
3
+ import './keys-D5k0omTb.js';
4
+ import 'jose';
5
+ import './theme.js';
6
+
7
+ /** What the middleware keeps on the context: `new Hono<{ Variables: CauthyVariables }>()`. */
8
+ interface CauthyVariables {
9
+ /** Who is signed in, or null. */
10
+ session: Session | null;
11
+ }
12
+ type Env = {
13
+ Variables: CauthyVariables;
14
+ };
15
+ /**
16
+ * Serves the routes under the handler's `basePath` (and, by contract, the
17
+ * application's published key), and sets `session` for
18
+ * every other request. Mount it once, before the routes that use it.
19
+ */
20
+ declare function cauthyHono(auth: Cauthy): MiddlewareHandler<Env>;
21
+ /** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyHono` mounted before it. */
22
+ declare const requireSession: MiddlewareHandler<Env>;
23
+
24
+ export { type CauthyVariables, cauthyHono, requireSession };