weifuwu 0.32.0 → 0.32.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.
package/README.md CHANGED
@@ -370,22 +370,27 @@ app.post('/api/chat', async (req, ctx) => {
370
370
 
371
371
  ### Auth
372
372
 
373
+ JWT extraction priority: `cookie` → `Authorization: Bearer` → `?access_token=`. All callbacks receive `ctx` so `ctx.sql` is directly available.
374
+
373
375
  ```ts
374
376
  import { auth } from 'weifuwu'
375
377
 
376
- // JWT
378
+ // JWT — cookie, header, or ?access_token=
377
379
  app.use(auth({ jwt: { secret: process.env.JWT_SECRET } }))
378
380
 
379
- // Session cookie
381
+ // Session cookie — loadUser gets ctx
380
382
  app.use(auth({
381
383
  session: {
382
384
  secret: '...',
383
- loadUser: async (data) => db.findUser(data.userId),
385
+ loadUser: async (data, ctx) => ctx.sql`SELECT * FROM users WHERE id = ${data.userId}`,
384
386
  },
385
387
  }))
386
388
 
387
- // API key
388
- app.use(auth({ apiKey: { validate: async (key) => db.findByApiKey(key) } }))
389
+ // API key — header or ?api_key=
390
+ app.use(auth({ apiKey: {
391
+ query: 'api_key',
392
+ validate: async (key, ctx) => ctx.sql`SELECT * FROM users WHERE api_key = ${key}`,
393
+ } }))
389
394
 
390
395
  // ctx.user is now available
391
396
  app.get('/me', (req, ctx) => {
package/dist/index.js CHANGED
@@ -926,7 +926,7 @@ function auth(opts) {
926
926
  return async (req, ctx, next) => {
927
927
  if (opts.jwt) {
928
928
  const cookie = opts.jwt.cookie ?? "token";
929
- const token = parseCookie(req.headers.get("cookie"), cookie) ?? req.headers.get("authorization")?.replace(/^Bearer\s+/i, "");
929
+ const token = parseCookie(req.headers.get("cookie"), cookie) ?? req.headers.get("authorization")?.replace(/^Bearer\s+/i, "") ?? ctx.query.access_token;
930
930
  if (token) {
931
931
  try {
932
932
  const [headerB64, payloadB64, sigB64] = token.split(".");
@@ -957,7 +957,7 @@ function auth(opts) {
957
957
  const expectedBuf = Buffer.from(expectedSig, "base64url");
958
958
  if (sigBuf.length === expectedBuf.length && timingSafeEqual(sigBuf, expectedBuf)) {
959
959
  const data = JSON.parse(base64urlDecode(dataB64));
960
- const user = await opts.session.loadUser(data);
960
+ const user = await opts.session.loadUser(data, ctx);
961
961
  if (user) ctx.user = user;
962
962
  }
963
963
  } catch {
@@ -967,10 +967,14 @@ function auth(opts) {
967
967
  if (opts.apiKey && !ctx.user) {
968
968
  const header = opts.apiKey.header ?? "authorization";
969
969
  const prefix = opts.apiKey.prefix ?? "Bearer ";
970
- const raw = req.headers.get(header);
970
+ let raw = req.headers.get(header);
971
+ if (!raw && opts.apiKey.query) {
972
+ raw = ctx.query[opts.apiKey.query];
973
+ if (raw) raw = prefix + raw;
974
+ }
971
975
  if (raw?.startsWith(prefix)) {
972
976
  const key = raw.slice(prefix.length);
973
- const user = await opts.apiKey.validate(key);
977
+ const user = await opts.apiKey.validate(key, ctx);
974
978
  if (user) ctx.user = user;
975
979
  }
976
980
  }
@@ -1,4 +1,4 @@
1
- import type { Middleware, User } from '../types.ts';
1
+ import type { Middleware, User, Context } from '../types.ts';
2
2
  export interface AuthOptions {
3
3
  /**
4
4
  * JWT authentication.
@@ -23,8 +23,8 @@ export interface AuthOptions {
23
23
  secret: string;
24
24
  /** Cookie name (default: 'session'). */
25
25
  cookie?: string;
26
- /** Load user from session data. */
27
- loadUser: (data: Record<string, unknown>) => Promise<User | null> | User | null;
26
+ /** Load user from session data. `ctx` has `ctx.sql`, `ctx.redis`, etc. */
27
+ loadUser: (data: Record<string, unknown>, ctx: Context) => Promise<User | null> | User | null;
28
28
  };
29
29
  /**
30
30
  * API key authentication via header.
@@ -37,8 +37,10 @@ export interface AuthOptions {
37
37
  header?: string;
38
38
  /** Prefix to strip (default: 'Bearer '). */
39
39
  prefix?: string;
40
- /** Validate an API key → User or null. */
41
- validate: (key: string) => Promise<User | null> | User | null;
40
+ /** Query parameter name (e.g. 'api_key'). */
41
+ query?: string;
42
+ /** Validate an API key → User or null. `ctx` has `ctx.sql`, `ctx.redis`, etc. */
43
+ validate: (key: string, ctx: Context) => Promise<User | null> | User | null;
42
44
  };
43
45
  }
44
46
  /**
@@ -57,12 +59,12 @@ export interface AuthOptions {
57
59
  * app.use(auth({
58
60
  * session: {
59
61
  * secret: '...',
60
- * loadUser: async (data) => db.findUser(data.userId),
62
+ * loadUser: async (data, ctx) => ctx.sql`SELECT * FROM users WHERE id = ${data.userId}`,
61
63
  * },
62
64
  * }))
63
65
  *
64
66
  * // API key
65
- * app.use(auth({ apiKey: { validate: async (key) => db.findByApiKey(key) } }))
67
+ * app.use(auth({ apiKey: { validate: async (key, ctx) => ctx.sql`...` } }))
66
68
  * ```
67
69
  */
68
70
  export declare function auth(opts: AuthOptions): Middleware;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "weifuwu",
3
3
  "type": "module",
4
- "version": "0.32.0",
4
+ "version": "0.32.1",
5
5
  "description": "Web-standard HTTP microframework for Node.js — (req, ctx) => Response",
6
6
  "exports": {
7
7
  ".": {