@shware/http 1.1.13 → 1.2.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.
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/hono/authorizer.ts
21
21
  var authorizer_exports = {};
22
22
  __export(authorizer_exports, {
23
- Authorizer: () => Authorizer,
24
23
  authorizer: () => authorizer
25
24
  });
26
25
  module.exports = __toCommonJS(authorizer_exports);
@@ -29,51 +28,21 @@ var import_reg_exp_router = require("hono/router/reg-exp-router");
29
28
  var import_smart_router = require("hono/router/smart-router");
30
29
  var import_trie_router = require("hono/router/trie-router");
31
30
  var import_status = require("../error/status.cjs");
32
- var Authorizer = class _Authorizer {
33
- router = new import_smart_router.SmartRouter({
34
- routers: [new import_reg_exp_router.RegExpRouter(), new import_trie_router.TrieRouter()]
35
- });
36
- auth;
37
- constructor(auth) {
38
- this.auth = auth;
39
- }
40
- static create = (auth) => new _Authorizer(auth);
41
- match(path, methods) {
42
- if (methods) {
43
- for (const method of methods) {
44
- this.router.add(method, path, null);
45
- }
46
- } else {
47
- this.router.add(import_router.METHOD_NAME_ALL, path, null);
48
- }
49
- return this;
50
- }
51
- build = () => {
52
- return async (c, next) => {
53
- if (c.req.method === "OPTIONS") {
54
- await next();
55
- return;
56
- }
57
- const [matched] = this.router.match(c.req.method, c.req.path);
58
- if (matched.length === 0) {
59
- await next();
60
- return;
61
- }
62
- const authenticated = await this.auth.isAuthenticated(c.req.raw);
63
- if (!authenticated) throw import_status.Status.unauthorized().error();
64
- await next();
65
- };
66
- };
67
- };
68
31
  function authorizer({
69
32
  auth,
70
33
  errorMessage = "Unauthorized, please login to continue.",
71
34
  rules = []
72
35
  }) {
73
36
  const router = new import_smart_router.SmartRouter({ routers: [new import_reg_exp_router.RegExpRouter(), new import_trie_router.TrieRouter()] });
74
- for (const { path, methods = [import_router.METHOD_NAME_ALL] } of rules) {
75
- for (const method of methods) {
76
- router.add(method, path, null);
37
+ for (const rule of rules) {
38
+ if (typeof rule === "string") {
39
+ router.add(import_router.METHOD_NAME_ALL, rule, null);
40
+ } else if (rule.methods && rule.methods.length > 0) {
41
+ for (const method of rule.methods) {
42
+ router.add(method, rule.path, null);
43
+ }
44
+ } else {
45
+ router.add(import_router.METHOD_NAME_ALL, rule.path, null);
77
46
  }
78
47
  }
79
48
  return async (c, next) => {
@@ -93,7 +62,6 @@ function authorizer({
93
62
  }
94
63
  // Annotate the CommonJS export names for ESM import in node:
95
64
  0 && (module.exports = {
96
- Authorizer,
97
65
  authorizer
98
66
  });
99
67
  //# sourceMappingURL=authorizer.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hono/authorizer.ts"],"sourcesContent":["import { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ntype Auth = { isAuthenticated: (request: Request) => Promise<boolean> };\n\nexport class Authorizer {\n private readonly router = new SmartRouter<null>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n private readonly auth: Auth;\n\n private constructor(auth: Auth) {\n this.auth = auth;\n }\n\n static create = (auth: Auth) => new Authorizer(auth);\n\n match(path: string, methods?: [Methods, ...Methods[]]) {\n if (methods) {\n for (const method of methods) {\n this.router.add(method, path, null);\n }\n } else {\n this.router.add(METHOD_NAME_ALL, path, null);\n }\n return this;\n }\n\n build = (): MiddlewareHandler => {\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = this.router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await this.auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized().error();\n await next();\n };\n };\n}\n\nexport interface AuthorizerConfig {\n auth: Auth;\n errorMessage?: string;\n rules?: { path: string; methods?: [Methods, ...Methods[]] }[];\n}\n\nexport function authorizer({\n auth,\n errorMessage = 'Unauthorized, please login to continue.',\n rules = [],\n}: AuthorizerConfig): MiddlewareHandler {\n const router = new SmartRouter<null>({ routers: [new RegExpRouter(), new TrieRouter()] });\n\n for (const { path, methods = [METHOD_NAME_ALL] } of rules) {\n for (const method of methods) {\n router.add(method, path, null);\n }\n }\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized(errorMessage).error();\n await next();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAgC;AAChC,4BAA6B;AAC7B,0BAA4B;AAC5B,yBAA2B;AAC3B,oBAAuB;AAOhB,IAAM,aAAN,MAAM,YAAW;AAAA,EACL,SAAS,IAAI,gCAAkB;AAAA,IAC9C,SAAS,CAAC,IAAI,mCAAa,GAAG,IAAI,8BAAW,CAAC;AAAA,EAChD,CAAC;AAAA,EAEgB;AAAA,EAET,YAAY,MAAY;AAC9B,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,OAAO,SAAS,CAAC,SAAe,IAAI,YAAW,IAAI;AAAA,EAEnD,MAAM,MAAc,SAAmC;AACrD,QAAI,SAAS;AACX,iBAAW,UAAU,SAAS;AAC5B,aAAK,OAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,MACpC;AAAA,IACF,OAAO;AACL,WAAK,OAAO,IAAI,+BAAiB,MAAM,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,MAAyB;AAC/B,WAAO,OAAO,GAAG,SAAS;AACxB,UAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,CAAC,OAAO,IAAI,KAAK,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AAC5D,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,gBAAgB,MAAM,KAAK,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC/D,UAAI,CAAC,cAAe,OAAM,qBAAO,aAAa,EAAE,MAAM;AACtD,YAAM,KAAK;AAAA,IACb;AAAA,EACF;AACF;AAQO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,eAAe;AAAA,EACf,QAAQ,CAAC;AACX,GAAwC;AACtC,QAAM,SAAS,IAAI,gCAAkB,EAAE,SAAS,CAAC,IAAI,mCAAa,GAAG,IAAI,8BAAW,CAAC,EAAE,CAAC;AAExF,aAAW,EAAE,MAAM,UAAU,CAAC,6BAAe,EAAE,KAAK,OAAO;AACzD,eAAW,UAAU,SAAS;AAC5B,aAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,SAAO,OAAO,GAAG,SAAS;AACxB,QAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,CAAC,OAAO,IAAI,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AACvD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC1D,QAAI,CAAC,cAAe,OAAM,qBAAO,aAAa,YAAY,EAAE,MAAM;AAClE,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/hono/authorizer.ts"],"sourcesContent":["import { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ntype Auth = { isAuthenticated: (request: Request) => Promise<boolean> };\n\nexport type AuthRule = string | { path: string; methods?: [Methods, ...Methods[]] };\n\nexport interface AuthorizerConfig {\n auth: Auth;\n errorMessage?: string;\n rules?: AuthRule[];\n}\n\nexport function authorizer({\n auth,\n errorMessage = 'Unauthorized, please login to continue.',\n rules = [],\n}: AuthorizerConfig): MiddlewareHandler {\n const router = new SmartRouter<null>({ routers: [new RegExpRouter(), new TrieRouter()] });\n\n for (const rule of rules) {\n if (typeof rule === 'string') {\n router.add(METHOD_NAME_ALL, rule, null);\n } else if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, null);\n }\n } else {\n router.add(METHOD_NAME_ALL, rule.path, null);\n }\n }\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized(errorMessage).error();\n await next();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAgC;AAChC,4BAA6B;AAC7B,0BAA4B;AAC5B,yBAA2B;AAC3B,oBAAuB;AAehB,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,eAAe;AAAA,EACf,QAAQ,CAAC;AACX,GAAwC;AACtC,QAAM,SAAS,IAAI,gCAAkB,EAAE,SAAS,CAAC,IAAI,mCAAa,GAAG,IAAI,8BAAW,CAAC,EAAE,CAAC;AAExF,aAAW,QAAQ,OAAO;AACxB,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO,IAAI,+BAAiB,MAAM,IAAI;AAAA,IACxC,WAAW,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAClD,iBAAW,UAAU,KAAK,SAAS;AACjC,eAAO,IAAI,QAAQ,KAAK,MAAM,IAAI;AAAA,MACpC;AAAA,IACF,OAAO;AACL,aAAO,IAAI,+BAAiB,KAAK,MAAM,IAAI;AAAA,IAC7C;AAAA,EACF;AAEA,SAAO,OAAO,GAAG,SAAS;AACxB,QAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,CAAC,OAAO,IAAI,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AACvD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC1D,QAAI,CAAC,cAAe,OAAM,qBAAO,aAAa,YAAY,EAAE,MAAM;AAClE,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
@@ -4,22 +4,15 @@ type Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
4
  type Auth = {
5
5
  isAuthenticated: (request: Request) => Promise<boolean>;
6
6
  };
7
- declare class Authorizer {
8
- private readonly router;
9
- private readonly auth;
10
- private constructor();
11
- static create: (auth: Auth) => Authorizer;
12
- match(path: string, methods?: [Methods, ...Methods[]]): this;
13
- build: () => MiddlewareHandler;
14
- }
7
+ type AuthRule = string | {
8
+ path: string;
9
+ methods?: [Methods, ...Methods[]];
10
+ };
15
11
  interface AuthorizerConfig {
16
12
  auth: Auth;
17
13
  errorMessage?: string;
18
- rules?: {
19
- path: string;
20
- methods?: [Methods, ...Methods[]];
21
- }[];
14
+ rules?: AuthRule[];
22
15
  }
23
16
  declare function authorizer({ auth, errorMessage, rules, }: AuthorizerConfig): MiddlewareHandler;
24
17
 
25
- export { Authorizer, type AuthorizerConfig, authorizer };
18
+ export { type AuthRule, type AuthorizerConfig, authorizer };
@@ -4,22 +4,15 @@ type Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
4
  type Auth = {
5
5
  isAuthenticated: (request: Request) => Promise<boolean>;
6
6
  };
7
- declare class Authorizer {
8
- private readonly router;
9
- private readonly auth;
10
- private constructor();
11
- static create: (auth: Auth) => Authorizer;
12
- match(path: string, methods?: [Methods, ...Methods[]]): this;
13
- build: () => MiddlewareHandler;
14
- }
7
+ type AuthRule = string | {
8
+ path: string;
9
+ methods?: [Methods, ...Methods[]];
10
+ };
15
11
  interface AuthorizerConfig {
16
12
  auth: Auth;
17
13
  errorMessage?: string;
18
- rules?: {
19
- path: string;
20
- methods?: [Methods, ...Methods[]];
21
- }[];
14
+ rules?: AuthRule[];
22
15
  }
23
16
  declare function authorizer({ auth, errorMessage, rules, }: AuthorizerConfig): MiddlewareHandler;
24
17
 
25
- export { Authorizer, type AuthorizerConfig, authorizer };
18
+ export { type AuthRule, type AuthorizerConfig, authorizer };
@@ -4,51 +4,21 @@ import { RegExpRouter } from "hono/router/reg-exp-router";
4
4
  import { SmartRouter } from "hono/router/smart-router";
5
5
  import { TrieRouter } from "hono/router/trie-router";
6
6
  import { Status } from "../error/status.mjs";
7
- var Authorizer = class _Authorizer {
8
- router = new SmartRouter({
9
- routers: [new RegExpRouter(), new TrieRouter()]
10
- });
11
- auth;
12
- constructor(auth) {
13
- this.auth = auth;
14
- }
15
- static create = (auth) => new _Authorizer(auth);
16
- match(path, methods) {
17
- if (methods) {
18
- for (const method of methods) {
19
- this.router.add(method, path, null);
20
- }
21
- } else {
22
- this.router.add(METHOD_NAME_ALL, path, null);
23
- }
24
- return this;
25
- }
26
- build = () => {
27
- return async (c, next) => {
28
- if (c.req.method === "OPTIONS") {
29
- await next();
30
- return;
31
- }
32
- const [matched] = this.router.match(c.req.method, c.req.path);
33
- if (matched.length === 0) {
34
- await next();
35
- return;
36
- }
37
- const authenticated = await this.auth.isAuthenticated(c.req.raw);
38
- if (!authenticated) throw Status.unauthorized().error();
39
- await next();
40
- };
41
- };
42
- };
43
7
  function authorizer({
44
8
  auth,
45
9
  errorMessage = "Unauthorized, please login to continue.",
46
10
  rules = []
47
11
  }) {
48
12
  const router = new SmartRouter({ routers: [new RegExpRouter(), new TrieRouter()] });
49
- for (const { path, methods = [METHOD_NAME_ALL] } of rules) {
50
- for (const method of methods) {
51
- router.add(method, path, null);
13
+ for (const rule of rules) {
14
+ if (typeof rule === "string") {
15
+ router.add(METHOD_NAME_ALL, rule, null);
16
+ } else if (rule.methods && rule.methods.length > 0) {
17
+ for (const method of rule.methods) {
18
+ router.add(method, rule.path, null);
19
+ }
20
+ } else {
21
+ router.add(METHOD_NAME_ALL, rule.path, null);
52
22
  }
53
23
  }
54
24
  return async (c, next) => {
@@ -67,7 +37,6 @@ function authorizer({
67
37
  };
68
38
  }
69
39
  export {
70
- Authorizer,
71
40
  authorizer
72
41
  };
73
42
  //# sourceMappingURL=authorizer.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hono/authorizer.ts"],"sourcesContent":["import { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ntype Auth = { isAuthenticated: (request: Request) => Promise<boolean> };\n\nexport class Authorizer {\n private readonly router = new SmartRouter<null>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n private readonly auth: Auth;\n\n private constructor(auth: Auth) {\n this.auth = auth;\n }\n\n static create = (auth: Auth) => new Authorizer(auth);\n\n match(path: string, methods?: [Methods, ...Methods[]]) {\n if (methods) {\n for (const method of methods) {\n this.router.add(method, path, null);\n }\n } else {\n this.router.add(METHOD_NAME_ALL, path, null);\n }\n return this;\n }\n\n build = (): MiddlewareHandler => {\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = this.router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await this.auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized().error();\n await next();\n };\n };\n}\n\nexport interface AuthorizerConfig {\n auth: Auth;\n errorMessage?: string;\n rules?: { path: string; methods?: [Methods, ...Methods[]] }[];\n}\n\nexport function authorizer({\n auth,\n errorMessage = 'Unauthorized, please login to continue.',\n rules = [],\n}: AuthorizerConfig): MiddlewareHandler {\n const router = new SmartRouter<null>({ routers: [new RegExpRouter(), new TrieRouter()] });\n\n for (const { path, methods = [METHOD_NAME_ALL] } of rules) {\n for (const method of methods) {\n router.add(method, path, null);\n }\n }\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized(errorMessage).error();\n await next();\n };\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AAOhB,IAAM,aAAN,MAAM,YAAW;AAAA,EACL,SAAS,IAAI,YAAkB;AAAA,IAC9C,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC;AAAA,EAChD,CAAC;AAAA,EAEgB;AAAA,EAET,YAAY,MAAY;AAC9B,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,OAAO,SAAS,CAAC,SAAe,IAAI,YAAW,IAAI;AAAA,EAEnD,MAAM,MAAc,SAAmC;AACrD,QAAI,SAAS;AACX,iBAAW,UAAU,SAAS;AAC5B,aAAK,OAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,MACpC;AAAA,IACF,OAAO;AACL,WAAK,OAAO,IAAI,iBAAiB,MAAM,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,MAAyB;AAC/B,WAAO,OAAO,GAAG,SAAS;AACxB,UAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,CAAC,OAAO,IAAI,KAAK,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AAC5D,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,KAAK;AACX;AAAA,MACF;AAEA,YAAM,gBAAgB,MAAM,KAAK,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC/D,UAAI,CAAC,cAAe,OAAM,OAAO,aAAa,EAAE,MAAM;AACtD,YAAM,KAAK;AAAA,IACb;AAAA,EACF;AACF;AAQO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,eAAe;AAAA,EACf,QAAQ,CAAC;AACX,GAAwC;AACtC,QAAM,SAAS,IAAI,YAAkB,EAAE,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC;AAExF,aAAW,EAAE,MAAM,UAAU,CAAC,eAAe,EAAE,KAAK,OAAO;AACzD,eAAW,UAAU,SAAS;AAC5B,aAAO,IAAI,QAAQ,MAAM,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,SAAO,OAAO,GAAG,SAAS;AACxB,QAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,CAAC,OAAO,IAAI,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AACvD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC1D,QAAI,CAAC,cAAe,OAAM,OAAO,aAAa,YAAY,EAAE,MAAM;AAClE,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/hono/authorizer.ts"],"sourcesContent":["import { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ntype Auth = { isAuthenticated: (request: Request) => Promise<boolean> };\n\nexport type AuthRule = string | { path: string; methods?: [Methods, ...Methods[]] };\n\nexport interface AuthorizerConfig {\n auth: Auth;\n errorMessage?: string;\n rules?: AuthRule[];\n}\n\nexport function authorizer({\n auth,\n errorMessage = 'Unauthorized, please login to continue.',\n rules = [],\n}: AuthorizerConfig): MiddlewareHandler {\n const router = new SmartRouter<null>({ routers: [new RegExpRouter(), new TrieRouter()] });\n\n for (const rule of rules) {\n if (typeof rule === 'string') {\n router.add(METHOD_NAME_ALL, rule, null);\n } else if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, null);\n }\n } else {\n router.add(METHOD_NAME_ALL, rule.path, null);\n }\n }\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS') {\n await next();\n return;\n }\n\n const [matched] = router.match(c.req.method, c.req.path);\n if (matched.length === 0) {\n await next();\n return;\n }\n\n const authenticated = await auth.isAuthenticated(c.req.raw);\n if (!authenticated) throw Status.unauthorized(errorMessage).error();\n await next();\n };\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AAehB,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,eAAe;AAAA,EACf,QAAQ,CAAC;AACX,GAAwC;AACtC,QAAM,SAAS,IAAI,YAAkB,EAAE,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC;AAExF,aAAW,QAAQ,OAAO;AACxB,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO,IAAI,iBAAiB,MAAM,IAAI;AAAA,IACxC,WAAW,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAClD,iBAAW,UAAU,KAAK,SAAS;AACjC,eAAO,IAAI,QAAQ,KAAK,MAAM,IAAI;AAAA,MACpC;AAAA,IACF,OAAO;AACL,aAAO,IAAI,iBAAiB,KAAK,MAAM,IAAI;AAAA,IAC7C;AAAA,EACF;AAEA,SAAO,OAAO,GAAG,SAAS;AACxB,QAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,CAAC,OAAO,IAAI,OAAO,MAAM,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI;AACvD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,EAAE,IAAI,GAAG;AAC1D,QAAI,CAAC,cAAe,OAAM,OAAO,aAAa,YAAY,EAAE,MAAM;AAClE,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
@@ -48,7 +48,9 @@ function csrf(config = {}) {
48
48
  });
49
49
  if (config.ignores) {
50
50
  for (const rule of config.ignores) {
51
- if (rule.methods && rule.methods.length > 0) {
51
+ if (typeof rule === "string") {
52
+ router.add(import_router.METHOD_NAME_ALL, rule, true);
53
+ } else if (rule.methods && rule.methods.length > 0) {
52
54
  for (const method of rule.methods) {
53
55
  router.add(method, rule.path, true);
54
56
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hono/csrf.ts"],"sourcesContent":["import { timingSafeEqual } from 'crypto';\nimport { getCookie } from 'hono/cookie';\nimport { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n\nexport interface CSRFIgnoreRule {\n path: string;\n methods?: HTTPMethod[];\n}\n\nexport interface CSRFConfig {\n /**\n * Cookie name for CSRF token\n * @default 'XSRF-TOKEN'\n */\n cookieName?: string;\n\n /**\n * Header name for CSRF token\n * @default 'X-XSRF-TOKEN'\n */\n headerName?: string;\n\n /**\n * Ignore rules for specific paths and methods\n * @example\n * [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' }, // ignores all methods\n * ]\n */\n ignores?: CSRFIgnoreRule[];\n\n /**\n * Skip CSRF check for these methods\n * @default ['GET', 'HEAD', 'OPTIONS']\n */\n safeMethods?: HTTPMethod[];\n\n /**\n * Custom error message\n * @default 'CSRF token validation failed'\n */\n errorMessage?: string;\n}\n\n/** use timing safe compare to prevent timing attack */\nfunction safeCompare(a: string, b: string): boolean {\n if (typeof a !== 'string' || typeof b !== 'string') return false;\n if (a.length === 0 || b.length === 0) return false;\n\n const bufferA = Buffer.from(a, 'utf-8');\n const bufferB = Buffer.from(b, 'utf-8');\n if (bufferA.length !== bufferB.length) return false;\n return timingSafeEqual(bufferA, bufferB);\n}\n\n/**\n * Create CSRF protection middleware\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { csrf } from '@shware/http/hono';\n *\n * const app = new Hono();\n *\n * // basic usage\n * app.use(csrf());\n *\n * // with configuration\n * app.use(csrf({\n * cookieName: 'csrf-token',\n * headerName: 'X-CSRF-Token',\n * ignores: [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' },\n * ]\n * }));\n * ```\n */\nexport function csrf(config: CSRFConfig = {}): MiddlewareHandler {\n const cookieName = config.cookieName ?? 'XSRF-TOKEN';\n const headerName = config.headerName ?? 'X-XSRF-TOKEN';\n const safeMethods = new Set(config.safeMethods ?? ['GET', 'HEAD', 'OPTIONS']);\n const errorMessage = config.errorMessage ?? 'CSRF token validation failed';\n\n // initialize router for matching ignore rules\n const router = new SmartRouter<boolean>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n // register ignore rules\n if (config.ignores) {\n for (const rule of config.ignores) {\n if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, true);\n }\n } else {\n // if no methods are specified, ignore all methods\n router.add(METHOD_NAME_ALL, rule.path, true);\n }\n }\n }\n\n // check if the request should be ignored\n function shouldIgnore(method: string, path: string): boolean {\n if (safeMethods.has(method)) {\n return true;\n }\n const [matchedAll] = router.match(METHOD_NAME_ALL, path);\n if (matchedAll.length > 0) {\n return true;\n }\n const [matchedMethod] = router.match(method, path);\n return matchedMethod.length > 0;\n }\n\n // return middleware\n return async (c, next) => {\n const method = c.req.method;\n const path = c.req.path;\n\n if (shouldIgnore(method, path)) {\n await next();\n return;\n }\n\n const cookieToken = getCookie(c, cookieName);\n const headerToken = c.req.header(headerName);\n\n if (!cookieToken || !headerToken) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n if (!safeCompare(cookieToken, headerToken)) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n await next();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAgC;AAChC,oBAA0B;AAC1B,oBAAgC;AAChC,4BAA6B;AAC7B,0BAA4B;AAC5B,yBAA2B;AAC3B,oBAAuB;AA+CvB,SAAS,YAAY,GAAW,GAAoB;AAClD,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO;AAC3D,MAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EAAG,QAAO;AAE7C,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,MAAI,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9C,aAAO,+BAAgB,SAAS,OAAO;AACzC;AA0BO,SAAS,KAAK,SAAqB,CAAC,GAAsB;AAC/D,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,cAAc,IAAI,IAAI,OAAO,eAAe,CAAC,OAAO,QAAQ,SAAS,CAAC;AAC5E,QAAM,eAAe,OAAO,gBAAgB;AAG5C,QAAM,SAAS,IAAI,gCAAqB;AAAA,IACtC,SAAS,CAAC,IAAI,mCAAa,GAAG,IAAI,8BAAW,CAAC;AAAA,EAChD,CAAC;AAGD,MAAI,OAAO,SAAS;AAClB,eAAW,QAAQ,OAAO,SAAS;AACjC,UAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAC3C,mBAAW,UAAU,KAAK,SAAS;AACjC,iBAAO,IAAI,QAAQ,KAAK,MAAM,IAAI;AAAA,QACpC;AAAA,MACF,OAAO;AAEL,eAAO,IAAI,+BAAiB,KAAK,MAAM,IAAI;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAGA,WAAS,aAAa,QAAgB,MAAuB;AAC3D,QAAI,YAAY,IAAI,MAAM,GAAG;AAC3B,aAAO;AAAA,IACT;AACA,UAAM,CAAC,UAAU,IAAI,OAAO,MAAM,+BAAiB,IAAI;AACvD,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AACA,UAAM,CAAC,aAAa,IAAI,OAAO,MAAM,QAAQ,IAAI;AACjD,WAAO,cAAc,SAAS;AAAA,EAChC;AAGA,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,SAAS,EAAE,IAAI;AACrB,UAAM,OAAO,EAAE,IAAI;AAEnB,QAAI,aAAa,QAAQ,IAAI,GAAG;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,kBAAc,yBAAU,GAAG,UAAU;AAC3C,UAAM,cAAc,EAAE,IAAI,OAAO,UAAU;AAE3C,QAAI,CAAC,eAAe,CAAC,aAAa;AAChC,YAAM,qBAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,QAAI,CAAC,YAAY,aAAa,WAAW,GAAG;AAC1C,YAAM,qBAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/hono/csrf.ts"],"sourcesContent":["import { timingSafeEqual } from 'crypto';\nimport { getCookie } from 'hono/cookie';\nimport { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n\nexport type CSRFIgnoreRule = string | { path: string; methods?: [HTTPMethod, ...HTTPMethod[]] };\n\nexport interface CSRFConfig {\n /**\n * Cookie name for CSRF token\n * @default 'XSRF-TOKEN'\n */\n cookieName?: string;\n\n /**\n * Header name for CSRF token\n * @default 'X-XSRF-TOKEN'\n */\n headerName?: string;\n\n /**\n * Ignore rules for specific paths and methods\n * @example\n * [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' }, // ignores all methods\n * ]\n */\n ignores?: CSRFIgnoreRule[];\n\n /**\n * Skip CSRF check for these methods\n * @default ['GET', 'HEAD', 'OPTIONS']\n */\n safeMethods?: HTTPMethod[];\n\n /**\n * Custom error message\n * @default 'CSRF token validation failed'\n */\n errorMessage?: string;\n}\n\n/** use timing safe compare to prevent timing attack */\nfunction safeCompare(a: string, b: string): boolean {\n if (typeof a !== 'string' || typeof b !== 'string') return false;\n if (a.length === 0 || b.length === 0) return false;\n\n const bufferA = Buffer.from(a, 'utf-8');\n const bufferB = Buffer.from(b, 'utf-8');\n if (bufferA.length !== bufferB.length) return false;\n return timingSafeEqual(bufferA, bufferB);\n}\n\n/**\n * Create CSRF protection middleware\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { csrf } from '@shware/http/hono';\n *\n * const app = new Hono();\n *\n * // basic usage\n * app.use(csrf());\n *\n * // with configuration\n * app.use(csrf({\n * cookieName: 'csrf-token',\n * headerName: 'X-CSRF-Token',\n * ignores: [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' },\n * ]\n * }));\n * ```\n */\nexport function csrf(config: CSRFConfig = {}): MiddlewareHandler {\n const cookieName = config.cookieName ?? 'XSRF-TOKEN';\n const headerName = config.headerName ?? 'X-XSRF-TOKEN';\n const safeMethods = new Set(config.safeMethods ?? ['GET', 'HEAD', 'OPTIONS']);\n const errorMessage = config.errorMessage ?? 'CSRF token validation failed';\n\n // initialize router for matching ignore rules\n const router = new SmartRouter<boolean>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n // register ignore rules\n if (config.ignores) {\n for (const rule of config.ignores) {\n if (typeof rule === 'string') {\n router.add(METHOD_NAME_ALL, rule, true);\n } else if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, true);\n }\n } else {\n // if no methods are specified, ignore all methods\n router.add(METHOD_NAME_ALL, rule.path, true);\n }\n }\n }\n\n // check if the request should be ignored\n function shouldIgnore(method: string, path: string): boolean {\n if (safeMethods.has(method)) {\n return true;\n }\n const [matchedAll] = router.match(METHOD_NAME_ALL, path);\n if (matchedAll.length > 0) {\n return true;\n }\n const [matchedMethod] = router.match(method, path);\n return matchedMethod.length > 0;\n }\n\n // return middleware\n return async (c, next) => {\n const method = c.req.method;\n const path = c.req.path;\n\n if (shouldIgnore(method, path)) {\n await next();\n return;\n }\n\n const cookieToken = getCookie(c, cookieName);\n const headerToken = c.req.header(headerName);\n\n if (!cookieToken || !headerToken) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n if (!safeCompare(cookieToken, headerToken)) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n await next();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAgC;AAChC,oBAA0B;AAC1B,oBAAgC;AAChC,4BAA6B;AAC7B,0BAA4B;AAC5B,yBAA2B;AAC3B,oBAAuB;AA4CvB,SAAS,YAAY,GAAW,GAAoB;AAClD,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO;AAC3D,MAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EAAG,QAAO;AAE7C,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,MAAI,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9C,aAAO,+BAAgB,SAAS,OAAO;AACzC;AA0BO,SAAS,KAAK,SAAqB,CAAC,GAAsB;AAC/D,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,cAAc,IAAI,IAAI,OAAO,eAAe,CAAC,OAAO,QAAQ,SAAS,CAAC;AAC5E,QAAM,eAAe,OAAO,gBAAgB;AAG5C,QAAM,SAAS,IAAI,gCAAqB;AAAA,IACtC,SAAS,CAAC,IAAI,mCAAa,GAAG,IAAI,8BAAW,CAAC;AAAA,EAChD,CAAC;AAGD,MAAI,OAAO,SAAS;AAClB,eAAW,QAAQ,OAAO,SAAS;AACjC,UAAI,OAAO,SAAS,UAAU;AAC5B,eAAO,IAAI,+BAAiB,MAAM,IAAI;AAAA,MACxC,WAAW,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAClD,mBAAW,UAAU,KAAK,SAAS;AACjC,iBAAO,IAAI,QAAQ,KAAK,MAAM,IAAI;AAAA,QACpC;AAAA,MACF,OAAO;AAEL,eAAO,IAAI,+BAAiB,KAAK,MAAM,IAAI;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAGA,WAAS,aAAa,QAAgB,MAAuB;AAC3D,QAAI,YAAY,IAAI,MAAM,GAAG;AAC3B,aAAO;AAAA,IACT;AACA,UAAM,CAAC,UAAU,IAAI,OAAO,MAAM,+BAAiB,IAAI;AACvD,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AACA,UAAM,CAAC,aAAa,IAAI,OAAO,MAAM,QAAQ,IAAI;AACjD,WAAO,cAAc,SAAS;AAAA,EAChC;AAGA,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,SAAS,EAAE,IAAI;AACrB,UAAM,OAAO,EAAE,IAAI;AAEnB,QAAI,aAAa,QAAQ,IAAI,GAAG;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,kBAAc,yBAAU,GAAG,UAAU;AAC3C,UAAM,cAAc,EAAE,IAAI,OAAO,UAAU;AAE3C,QAAI,CAAC,eAAe,CAAC,aAAa;AAChC,YAAM,qBAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,QAAI,CAAC,YAAY,aAAa,WAAW,GAAG;AAC1C,YAAM,qBAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
@@ -1,10 +1,10 @@
1
1
  import { MiddlewareHandler } from 'hono';
2
2
 
3
3
  type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
4
- interface CSRFIgnoreRule {
4
+ type CSRFIgnoreRule = string | {
5
5
  path: string;
6
- methods?: HTTPMethod[];
7
- }
6
+ methods?: [HTTPMethod, ...HTTPMethod[]];
7
+ };
8
8
  interface CSRFConfig {
9
9
  /**
10
10
  * Cookie name for CSRF token
@@ -1,10 +1,10 @@
1
1
  import { MiddlewareHandler } from 'hono';
2
2
 
3
3
  type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
4
- interface CSRFIgnoreRule {
4
+ type CSRFIgnoreRule = string | {
5
5
  path: string;
6
- methods?: HTTPMethod[];
7
- }
6
+ methods?: [HTTPMethod, ...HTTPMethod[]];
7
+ };
8
8
  interface CSRFConfig {
9
9
  /**
10
10
  * Cookie name for CSRF token
@@ -24,7 +24,9 @@ function csrf(config = {}) {
24
24
  });
25
25
  if (config.ignores) {
26
26
  for (const rule of config.ignores) {
27
- if (rule.methods && rule.methods.length > 0) {
27
+ if (typeof rule === "string") {
28
+ router.add(METHOD_NAME_ALL, rule, true);
29
+ } else if (rule.methods && rule.methods.length > 0) {
28
30
  for (const method of rule.methods) {
29
31
  router.add(method, rule.path, true);
30
32
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hono/csrf.ts"],"sourcesContent":["import { timingSafeEqual } from 'crypto';\nimport { getCookie } from 'hono/cookie';\nimport { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n\nexport interface CSRFIgnoreRule {\n path: string;\n methods?: HTTPMethod[];\n}\n\nexport interface CSRFConfig {\n /**\n * Cookie name for CSRF token\n * @default 'XSRF-TOKEN'\n */\n cookieName?: string;\n\n /**\n * Header name for CSRF token\n * @default 'X-XSRF-TOKEN'\n */\n headerName?: string;\n\n /**\n * Ignore rules for specific paths and methods\n * @example\n * [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' }, // ignores all methods\n * ]\n */\n ignores?: CSRFIgnoreRule[];\n\n /**\n * Skip CSRF check for these methods\n * @default ['GET', 'HEAD', 'OPTIONS']\n */\n safeMethods?: HTTPMethod[];\n\n /**\n * Custom error message\n * @default 'CSRF token validation failed'\n */\n errorMessage?: string;\n}\n\n/** use timing safe compare to prevent timing attack */\nfunction safeCompare(a: string, b: string): boolean {\n if (typeof a !== 'string' || typeof b !== 'string') return false;\n if (a.length === 0 || b.length === 0) return false;\n\n const bufferA = Buffer.from(a, 'utf-8');\n const bufferB = Buffer.from(b, 'utf-8');\n if (bufferA.length !== bufferB.length) return false;\n return timingSafeEqual(bufferA, bufferB);\n}\n\n/**\n * Create CSRF protection middleware\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { csrf } from '@shware/http/hono';\n *\n * const app = new Hono();\n *\n * // basic usage\n * app.use(csrf());\n *\n * // with configuration\n * app.use(csrf({\n * cookieName: 'csrf-token',\n * headerName: 'X-CSRF-Token',\n * ignores: [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' },\n * ]\n * }));\n * ```\n */\nexport function csrf(config: CSRFConfig = {}): MiddlewareHandler {\n const cookieName = config.cookieName ?? 'XSRF-TOKEN';\n const headerName = config.headerName ?? 'X-XSRF-TOKEN';\n const safeMethods = new Set(config.safeMethods ?? ['GET', 'HEAD', 'OPTIONS']);\n const errorMessage = config.errorMessage ?? 'CSRF token validation failed';\n\n // initialize router for matching ignore rules\n const router = new SmartRouter<boolean>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n // register ignore rules\n if (config.ignores) {\n for (const rule of config.ignores) {\n if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, true);\n }\n } else {\n // if no methods are specified, ignore all methods\n router.add(METHOD_NAME_ALL, rule.path, true);\n }\n }\n }\n\n // check if the request should be ignored\n function shouldIgnore(method: string, path: string): boolean {\n if (safeMethods.has(method)) {\n return true;\n }\n const [matchedAll] = router.match(METHOD_NAME_ALL, path);\n if (matchedAll.length > 0) {\n return true;\n }\n const [matchedMethod] = router.match(method, path);\n return matchedMethod.length > 0;\n }\n\n // return middleware\n return async (c, next) => {\n const method = c.req.method;\n const path = c.req.path;\n\n if (shouldIgnore(method, path)) {\n await next();\n return;\n }\n\n const cookieToken = getCookie(c, cookieName);\n const headerToken = c.req.header(headerName);\n\n if (!cookieToken || !headerToken) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n if (!safeCompare(cookieToken, headerToken)) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n await next();\n };\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AA+CvB,SAAS,YAAY,GAAW,GAAoB;AAClD,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO;AAC3D,MAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EAAG,QAAO;AAE7C,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,MAAI,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9C,SAAO,gBAAgB,SAAS,OAAO;AACzC;AA0BO,SAAS,KAAK,SAAqB,CAAC,GAAsB;AAC/D,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,cAAc,IAAI,IAAI,OAAO,eAAe,CAAC,OAAO,QAAQ,SAAS,CAAC;AAC5E,QAAM,eAAe,OAAO,gBAAgB;AAG5C,QAAM,SAAS,IAAI,YAAqB;AAAA,IACtC,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC;AAAA,EAChD,CAAC;AAGD,MAAI,OAAO,SAAS;AAClB,eAAW,QAAQ,OAAO,SAAS;AACjC,UAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAC3C,mBAAW,UAAU,KAAK,SAAS;AACjC,iBAAO,IAAI,QAAQ,KAAK,MAAM,IAAI;AAAA,QACpC;AAAA,MACF,OAAO;AAEL,eAAO,IAAI,iBAAiB,KAAK,MAAM,IAAI;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAGA,WAAS,aAAa,QAAgB,MAAuB;AAC3D,QAAI,YAAY,IAAI,MAAM,GAAG;AAC3B,aAAO;AAAA,IACT;AACA,UAAM,CAAC,UAAU,IAAI,OAAO,MAAM,iBAAiB,IAAI;AACvD,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AACA,UAAM,CAAC,aAAa,IAAI,OAAO,MAAM,QAAQ,IAAI;AACjD,WAAO,cAAc,SAAS;AAAA,EAChC;AAGA,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,SAAS,EAAE,IAAI;AACrB,UAAM,OAAO,EAAE,IAAI;AAEnB,QAAI,aAAa,QAAQ,IAAI,GAAG;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,cAAc,UAAU,GAAG,UAAU;AAC3C,UAAM,cAAc,EAAE,IAAI,OAAO,UAAU;AAE3C,QAAI,CAAC,eAAe,CAAC,aAAa;AAChC,YAAM,OAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,QAAI,CAAC,YAAY,aAAa,WAAW,GAAG;AAC1C,YAAM,OAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/hono/csrf.ts"],"sourcesContent":["import { timingSafeEqual } from 'crypto';\nimport { getCookie } from 'hono/cookie';\nimport { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\nimport type { MiddlewareHandler } from 'hono';\n\ntype HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n\nexport type CSRFIgnoreRule = string | { path: string; methods?: [HTTPMethod, ...HTTPMethod[]] };\n\nexport interface CSRFConfig {\n /**\n * Cookie name for CSRF token\n * @default 'XSRF-TOKEN'\n */\n cookieName?: string;\n\n /**\n * Header name for CSRF token\n * @default 'X-XSRF-TOKEN'\n */\n headerName?: string;\n\n /**\n * Ignore rules for specific paths and methods\n * @example\n * [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' }, // ignores all methods\n * ]\n */\n ignores?: CSRFIgnoreRule[];\n\n /**\n * Skip CSRF check for these methods\n * @default ['GET', 'HEAD', 'OPTIONS']\n */\n safeMethods?: HTTPMethod[];\n\n /**\n * Custom error message\n * @default 'CSRF token validation failed'\n */\n errorMessage?: string;\n}\n\n/** use timing safe compare to prevent timing attack */\nfunction safeCompare(a: string, b: string): boolean {\n if (typeof a !== 'string' || typeof b !== 'string') return false;\n if (a.length === 0 || b.length === 0) return false;\n\n const bufferA = Buffer.from(a, 'utf-8');\n const bufferB = Buffer.from(b, 'utf-8');\n if (bufferA.length !== bufferB.length) return false;\n return timingSafeEqual(bufferA, bufferB);\n}\n\n/**\n * Create CSRF protection middleware\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { csrf } from '@shware/http/hono';\n *\n * const app = new Hono();\n *\n * // basic usage\n * app.use(csrf());\n *\n * // with configuration\n * app.use(csrf({\n * cookieName: 'csrf-token',\n * headerName: 'X-CSRF-Token',\n * ignores: [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' },\n * ]\n * }));\n * ```\n */\nexport function csrf(config: CSRFConfig = {}): MiddlewareHandler {\n const cookieName = config.cookieName ?? 'XSRF-TOKEN';\n const headerName = config.headerName ?? 'X-XSRF-TOKEN';\n const safeMethods = new Set(config.safeMethods ?? ['GET', 'HEAD', 'OPTIONS']);\n const errorMessage = config.errorMessage ?? 'CSRF token validation failed';\n\n // initialize router for matching ignore rules\n const router = new SmartRouter<boolean>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n // register ignore rules\n if (config.ignores) {\n for (const rule of config.ignores) {\n if (typeof rule === 'string') {\n router.add(METHOD_NAME_ALL, rule, true);\n } else if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, true);\n }\n } else {\n // if no methods are specified, ignore all methods\n router.add(METHOD_NAME_ALL, rule.path, true);\n }\n }\n }\n\n // check if the request should be ignored\n function shouldIgnore(method: string, path: string): boolean {\n if (safeMethods.has(method)) {\n return true;\n }\n const [matchedAll] = router.match(METHOD_NAME_ALL, path);\n if (matchedAll.length > 0) {\n return true;\n }\n const [matchedMethod] = router.match(method, path);\n return matchedMethod.length > 0;\n }\n\n // return middleware\n return async (c, next) => {\n const method = c.req.method;\n const path = c.req.path;\n\n if (shouldIgnore(method, path)) {\n await next();\n return;\n }\n\n const cookieToken = getCookie(c, cookieName);\n const headerToken = c.req.header(headerName);\n\n if (!cookieToken || !headerToken) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n if (!safeCompare(cookieToken, headerToken)) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n await next();\n };\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AA4CvB,SAAS,YAAY,GAAW,GAAoB;AAClD,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO;AAC3D,MAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EAAG,QAAO;AAE7C,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,QAAM,UAAU,OAAO,KAAK,GAAG,OAAO;AACtC,MAAI,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9C,SAAO,gBAAgB,SAAS,OAAO;AACzC;AA0BO,SAAS,KAAK,SAAqB,CAAC,GAAsB;AAC/D,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,cAAc,IAAI,IAAI,OAAO,eAAe,CAAC,OAAO,QAAQ,SAAS,CAAC;AAC5E,QAAM,eAAe,OAAO,gBAAgB;AAG5C,QAAM,SAAS,IAAI,YAAqB;AAAA,IACtC,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC;AAAA,EAChD,CAAC;AAGD,MAAI,OAAO,SAAS;AAClB,eAAW,QAAQ,OAAO,SAAS;AACjC,UAAI,OAAO,SAAS,UAAU;AAC5B,eAAO,IAAI,iBAAiB,MAAM,IAAI;AAAA,MACxC,WAAW,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAClD,mBAAW,UAAU,KAAK,SAAS;AACjC,iBAAO,IAAI,QAAQ,KAAK,MAAM,IAAI;AAAA,QACpC;AAAA,MACF,OAAO;AAEL,eAAO,IAAI,iBAAiB,KAAK,MAAM,IAAI;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAGA,WAAS,aAAa,QAAgB,MAAuB;AAC3D,QAAI,YAAY,IAAI,MAAM,GAAG;AAC3B,aAAO;AAAA,IACT;AACA,UAAM,CAAC,UAAU,IAAI,OAAO,MAAM,iBAAiB,IAAI;AACvD,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AACA,UAAM,CAAC,aAAa,IAAI,OAAO,MAAM,QAAQ,IAAI;AACjD,WAAO,cAAc,SAAS;AAAA,EAChC;AAGA,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,SAAS,EAAE,IAAI;AACrB,UAAM,OAAO,EAAE,IAAI;AAEnB,QAAI,aAAa,QAAQ,IAAI,GAAG;AAC9B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,cAAc,UAAU,GAAG,UAAU;AAC3C,UAAM,cAAc,EAAE,IAAI,OAAO,UAAU;AAE3C,QAAI,CAAC,eAAe,CAAC,aAAa;AAChC,YAAM,OAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,QAAI,CAAC,YAAY,aAAa,WAAW,GAAG;AAC1C,YAAM,OAAO,iBAAiB,YAAY,EAAE,MAAM;AAAA,IACpD;AAEA,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/hono/index.ts
21
21
  var hono_exports = {};
22
22
  __export(hono_exports, {
23
- Authorizer: () => import_authorizer.Authorizer,
24
23
  authorizer: () => import_authorizer.authorizer,
25
24
  bigintId: () => import_validator.bigintId,
26
25
  csrf: () => import_csrf.csrf,
@@ -36,7 +35,6 @@ var import_authorizer = require("./authorizer.cjs");
36
35
  var import_csrf = require("./csrf.cjs");
37
36
  // Annotate the CommonJS export names for ESM import in node:
38
37
  0 && (module.exports = {
39
- Authorizer,
40
38
  authorizer,
41
39
  bigintId,
42
40
  csrf,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export { zValidator, bigintId } from './validator';\nexport { errorHandler } from './handler';\nexport { geolocation } from './geolocation';\nexport { Authorizer, authorizer, type AuthorizerConfig } from './authorizer';\nexport { csrf, type CSRFConfig, type CSRFIgnoreRule } from './csrf';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAqC;AACrC,qBAA6B;AAC7B,yBAA4B;AAC5B,wBAA8D;AAC9D,kBAA2D;","names":[]}
1
+ {"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export { zValidator, bigintId } from './validator';\nexport { errorHandler } from './handler';\nexport { geolocation } from './geolocation';\nexport { authorizer, type AuthorizerConfig } from './authorizer';\nexport { csrf, type CSRFConfig, type CSRFIgnoreRule } from './csrf';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAqC;AACrC,qBAA6B;AAC7B,yBAA4B;AAC5B,wBAAkD;AAClD,kBAA2D;","names":[]}
@@ -1,7 +1,7 @@
1
1
  export { bigintId, zValidator } from './validator.cjs';
2
2
  export { errorHandler } from './handler.cjs';
3
3
  export { geolocation } from './geolocation.cjs';
4
- export { Authorizer, AuthorizerConfig, authorizer } from './authorizer.cjs';
4
+ export { AuthorizerConfig, authorizer } from './authorizer.cjs';
5
5
  export { CSRFConfig, CSRFIgnoreRule, csrf } from './csrf.cjs';
6
6
  import 'zod/mini';
7
7
  import 'hono';
@@ -1,7 +1,7 @@
1
1
  export { bigintId, zValidator } from './validator.js';
2
2
  export { errorHandler } from './handler.js';
3
3
  export { geolocation } from './geolocation.js';
4
- export { Authorizer, AuthorizerConfig, authorizer } from './authorizer.js';
4
+ export { AuthorizerConfig, authorizer } from './authorizer.js';
5
5
  export { CSRFConfig, CSRFIgnoreRule, csrf } from './csrf.js';
6
6
  import 'zod/mini';
7
7
  import 'hono';
@@ -2,10 +2,9 @@
2
2
  import { zValidator, bigintId } from "./validator.mjs";
3
3
  import { errorHandler } from "./handler.mjs";
4
4
  import { geolocation } from "./geolocation.mjs";
5
- import { Authorizer, authorizer } from "./authorizer.mjs";
5
+ import { authorizer } from "./authorizer.mjs";
6
6
  import { csrf } from "./csrf.mjs";
7
7
  export {
8
- Authorizer,
9
8
  authorizer,
10
9
  bigintId,
11
10
  csrf,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export { zValidator, bigintId } from './validator';\nexport { errorHandler } from './handler';\nexport { geolocation } from './geolocation';\nexport { Authorizer, authorizer, type AuthorizerConfig } from './authorizer';\nexport { csrf, type CSRFConfig, type CSRFIgnoreRule } from './csrf';\n"],"mappings":";AAAA,SAAS,YAAY,gBAAgB;AACrC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,YAAY,kBAAyC;AAC9D,SAAS,YAAkD;","names":[]}
1
+ {"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export { zValidator, bigintId } from './validator';\nexport { errorHandler } from './handler';\nexport { geolocation } from './geolocation';\nexport { authorizer, type AuthorizerConfig } from './authorizer';\nexport { csrf, type CSRFConfig, type CSRFIgnoreRule } from './csrf';\n"],"mappings":";AAAA,SAAS,YAAY,gBAAgB;AACrC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,kBAAyC;AAClD,SAAS,YAAkD;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shware/http",
3
- "version": "1.1.13",
3
+ "version": "1.2.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "repository": {
@@ -44,8 +44,8 @@
44
44
  "jest": "^30.1.3",
45
45
  "ts-jest": "^29.4.1",
46
46
  "typescript": "^5.9.2",
47
- "@repo/eslint-config": "0.0.4",
48
- "@repo/typescript-config": "0.0.0"
47
+ "@repo/typescript-config": "0.0.0",
48
+ "@repo/eslint-config": "0.0.4"
49
49
  },
50
50
  "dependencies": {
51
51
  "zod": "^4.1.8"