@bgord/bun 1.5.11 → 1.6.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.
Files changed (220) hide show
  1. package/dist/cache-file.service.d.ts +3 -3
  2. package/dist/cache-file.service.js +2 -2
  3. package/dist/cache-file.service.js.map +1 -1
  4. package/dist/cache-repository-node-cache.adapter.d.ts +5 -4
  5. package/dist/cache-repository-node-cache.adapter.d.ts.map +1 -1
  6. package/dist/cache-repository-node-cache.adapter.js +6 -6
  7. package/dist/cache-repository-node-cache.adapter.js.map +1 -1
  8. package/dist/cache-repository.port.d.ts +4 -4
  9. package/dist/cache-repository.port.d.ts.map +1 -1
  10. package/dist/cache-resolver-simple.adapter.d.ts +4 -3
  11. package/dist/cache-resolver-simple.adapter.d.ts.map +1 -1
  12. package/dist/cache-resolver-simple.adapter.js +5 -5
  13. package/dist/cache-resolver-simple.adapter.js.map +1 -1
  14. package/dist/cache-resolver.port.d.ts +3 -3
  15. package/dist/cache-resolver.port.d.ts.map +1 -1
  16. package/dist/cache-response.middleware.d.ts +2 -4
  17. package/dist/cache-response.middleware.d.ts.map +1 -1
  18. package/dist/cache-response.middleware.js +2 -3
  19. package/dist/cache-response.middleware.js.map +1 -1
  20. package/dist/cache-subject-resolver.vo.d.ts +22 -0
  21. package/dist/cache-subject-resolver.vo.d.ts.map +1 -0
  22. package/dist/cache-subject-resolver.vo.js +19 -0
  23. package/dist/cache-subject-resolver.vo.js.map +1 -0
  24. package/dist/cache-subject-segment-cookie.d.ts +8 -0
  25. package/dist/cache-subject-segment-cookie.d.ts.map +1 -0
  26. package/dist/cache-subject-segment-cookie.js +13 -0
  27. package/dist/cache-subject-segment-cookie.js.map +1 -0
  28. package/dist/cache-subject-segment-fixed.d.ts +7 -0
  29. package/dist/cache-subject-segment-fixed.d.ts.map +1 -0
  30. package/dist/cache-subject-segment-fixed.js +10 -0
  31. package/dist/cache-subject-segment-fixed.js.map +1 -0
  32. package/dist/cache-subject-segment-header.d.ts +8 -0
  33. package/dist/cache-subject-segment-header.d.ts.map +1 -0
  34. package/dist/cache-subject-segment-header.js +10 -0
  35. package/dist/cache-subject-segment-header.js.map +1 -0
  36. package/dist/cache-subject-segment-path.d.ts +6 -0
  37. package/dist/cache-subject-segment-path.d.ts.map +1 -0
  38. package/dist/cache-subject-segment-path.js +6 -0
  39. package/dist/cache-subject-segment-path.js.map +1 -0
  40. package/dist/cache-subject-segment-query.d.ts +6 -0
  41. package/dist/cache-subject-segment-query.d.ts.map +1 -0
  42. package/dist/cache-subject-segment-query.js +10 -0
  43. package/dist/cache-subject-segment-query.js.map +1 -0
  44. package/dist/cache-subject-segment-user.d.ts +6 -0
  45. package/dist/cache-subject-segment-user.d.ts.map +1 -0
  46. package/dist/cache-subject-segment-user.js +6 -0
  47. package/dist/cache-subject-segment-user.js.map +1 -0
  48. package/dist/cache-subject-segment.port.d.ts +6 -0
  49. package/dist/cache-subject-segment.port.d.ts.map +1 -0
  50. package/dist/cache-subject-segment.port.js +2 -0
  51. package/dist/cache-subject-segment.port.js.map +1 -0
  52. package/dist/checksum.service.d.ts +2 -2
  53. package/dist/checksum.service.js +2 -2
  54. package/dist/checksum.service.js.map +1 -1
  55. package/dist/client.vo.d.ts +3 -1
  56. package/dist/client.vo.d.ts.map +1 -1
  57. package/dist/client.vo.js +8 -1
  58. package/dist/client.vo.js.map +1 -1
  59. package/dist/environment-loader-process-safe.adapter.d.ts +2 -0
  60. package/dist/environment-loader-process-safe.adapter.d.ts.map +1 -1
  61. package/dist/environment-loader-process-safe.adapter.js +5 -1
  62. package/dist/environment-loader-process-safe.adapter.js.map +1 -1
  63. package/dist/hash-content-noop.adapter.d.ts +6 -0
  64. package/dist/hash-content-noop.adapter.d.ts.map +1 -0
  65. package/dist/hash-content-noop.adapter.js +7 -0
  66. package/dist/hash-content-noop.adapter.js.map +1 -0
  67. package/dist/hash-content-sha256-bun.adapter.d.ts +6 -0
  68. package/dist/hash-content-sha256-bun.adapter.d.ts.map +1 -0
  69. package/dist/{content-hash-sha256-bun.adapter.js → hash-content-sha256-bun.adapter.js} +4 -3
  70. package/dist/hash-content-sha256-bun.adapter.js.map +1 -0
  71. package/dist/hash-content.port.d.ts +5 -0
  72. package/dist/hash-content.port.d.ts.map +1 -0
  73. package/dist/hash-content.port.js +2 -0
  74. package/dist/hash-content.port.js.map +1 -0
  75. package/dist/hash-file-noop.adapter.d.ts +12 -0
  76. package/dist/hash-file-noop.adapter.d.ts.map +1 -0
  77. package/dist/{file-hash-noop.adapter.js → hash-file-noop.adapter.js} +4 -4
  78. package/dist/hash-file-noop.adapter.js.map +1 -0
  79. package/dist/hash-file-sha256-bun.adapter.d.ts +18 -0
  80. package/dist/hash-file-sha256-bun.adapter.d.ts.map +1 -0
  81. package/dist/{file-hash-sha256-bun.adapter.js → hash-file-sha256-bun.adapter.js} +7 -5
  82. package/dist/hash-file-sha256-bun.adapter.js.map +1 -0
  83. package/dist/hash-file.port.d.ts +12 -0
  84. package/dist/hash-file.port.d.ts.map +1 -0
  85. package/dist/hash-file.port.js +2 -0
  86. package/dist/hash-file.port.js.map +1 -0
  87. package/dist/hash-value.vo.d.ts +8 -0
  88. package/dist/hash-value.vo.d.ts.map +1 -0
  89. package/dist/hash-value.vo.js +9 -0
  90. package/dist/hash-value.vo.js.map +1 -0
  91. package/dist/hash.vo.d.ts +12 -0
  92. package/dist/hash.vo.d.ts.map +1 -0
  93. package/dist/hash.vo.js +26 -0
  94. package/dist/hash.vo.js.map +1 -0
  95. package/dist/http-logger.middleware.js +2 -2
  96. package/dist/http-logger.middleware.js.map +1 -1
  97. package/dist/index.d.ts +17 -15
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +17 -16
  100. package/dist/index.js.map +1 -1
  101. package/dist/remote-file-storage-disk.adapter.d.ts +2 -2
  102. package/dist/remote-file-storage-disk.adapter.d.ts.map +1 -1
  103. package/dist/remote-file-storage-disk.adapter.js +2 -2
  104. package/dist/remote-file-storage-noop.adapter.js +2 -2
  105. package/dist/remote-file-storage-noop.adapter.js.map +1 -1
  106. package/dist/remote-file-storage.port.d.ts +3 -3
  107. package/dist/shield-rate-limit.adapter.d.ts +2 -5
  108. package/dist/shield-rate-limit.adapter.d.ts.map +1 -1
  109. package/dist/shield-rate-limit.adapter.js +2 -4
  110. package/dist/shield-rate-limit.adapter.js.map +1 -1
  111. package/dist/tsconfig.tsbuildinfo +1 -1
  112. package/dist/visitor-id-client.adapter.d.ts +14 -0
  113. package/dist/visitor-id-client.adapter.d.ts.map +1 -0
  114. package/dist/visitor-id-client.adapter.js +14 -0
  115. package/dist/visitor-id-client.adapter.js.map +1 -0
  116. package/dist/visitor-id.port.d.ts +2 -2
  117. package/dist/visitor-id.port.d.ts.map +1 -1
  118. package/package.json +2 -2
  119. package/readme.md +17 -15
  120. package/src/cache-file.service.ts +7 -7
  121. package/src/cache-repository-node-cache.adapter.ts +8 -7
  122. package/src/cache-repository.port.ts +4 -5
  123. package/src/cache-resolver-simple.adapter.ts +7 -6
  124. package/src/cache-resolver.port.ts +3 -3
  125. package/src/cache-response.middleware.ts +4 -8
  126. package/src/cache-subject-resolver.vo.ts +30 -0
  127. package/src/cache-subject-segment-cookie.ts +12 -0
  128. package/src/cache-subject-segment-fixed.ts +9 -0
  129. package/src/cache-subject-segment-header.ts +10 -0
  130. package/src/cache-subject-segment-path.ts +8 -0
  131. package/src/cache-subject-segment-query.ts +13 -0
  132. package/src/cache-subject-segment-user.ts +8 -0
  133. package/src/cache-subject-segment.port.ts +7 -0
  134. package/src/checksum.service.ts +4 -4
  135. package/src/client.vo.ts +15 -1
  136. package/src/environment-loader-process-safe.adapter.ts +8 -2
  137. package/src/hash-content-noop.adapter.ts +8 -0
  138. package/src/{content-hash-sha256-bun.adapter.ts → hash-content-sha256-bun.adapter.ts} +4 -3
  139. package/src/hash-content.port.ts +5 -0
  140. package/src/{file-hash-noop.adapter.ts → hash-file-noop.adapter.ts} +4 -4
  141. package/src/{file-hash-sha256-bun.adapter.ts → hash-file-sha256-bun.adapter.ts} +8 -5
  142. package/src/{file-hash.port.ts → hash-file.port.ts} +5 -5
  143. package/src/hash-value.vo.ts +13 -0
  144. package/src/hash.vo.ts +29 -0
  145. package/src/http-logger.middleware.ts +2 -2
  146. package/src/index.ts +17 -16
  147. package/src/remote-file-storage-disk.adapter.ts +4 -4
  148. package/src/remote-file-storage-noop.adapter.ts +2 -2
  149. package/src/remote-file-storage.port.ts +3 -3
  150. package/src/shield-rate-limit.adapter.ts +4 -9
  151. package/src/visitor-id-client.adapter.ts +20 -0
  152. package/src/visitor-id.port.ts +2 -2
  153. package/dist/client-from-hono.adapter.d.ts +0 -6
  154. package/dist/client-from-hono.adapter.d.ts.map +0 -1
  155. package/dist/client-from-hono.adapter.js +0 -11
  156. package/dist/client-from-hono.adapter.js.map +0 -1
  157. package/dist/content-hash-noop.adapter.d.ts +0 -7
  158. package/dist/content-hash-noop.adapter.d.ts.map +0 -1
  159. package/dist/content-hash-noop.adapter.js +0 -6
  160. package/dist/content-hash-noop.adapter.js.map +0 -1
  161. package/dist/content-hash-sha256-bun.adapter.d.ts +0 -7
  162. package/dist/content-hash-sha256-bun.adapter.d.ts.map +0 -1
  163. package/dist/content-hash-sha256-bun.adapter.js.map +0 -1
  164. package/dist/content-hash.port.d.ts +0 -7
  165. package/dist/content-hash.port.d.ts.map +0 -1
  166. package/dist/content-hash.port.js +0 -2
  167. package/dist/content-hash.port.js.map +0 -1
  168. package/dist/file-etag.vo.d.ts +0 -8
  169. package/dist/file-etag.vo.d.ts.map +0 -1
  170. package/dist/file-etag.vo.js +0 -9
  171. package/dist/file-etag.vo.js.map +0 -1
  172. package/dist/file-hash-noop.adapter.d.ts +0 -11
  173. package/dist/file-hash-noop.adapter.d.ts.map +0 -1
  174. package/dist/file-hash-noop.adapter.js.map +0 -1
  175. package/dist/file-hash-sha256-bun.adapter.d.ts +0 -11
  176. package/dist/file-hash-sha256-bun.adapter.d.ts.map +0 -1
  177. package/dist/file-hash-sha256-bun.adapter.js.map +0 -1
  178. package/dist/file-hash.port.d.ts +0 -12
  179. package/dist/file-hash.port.d.ts.map +0 -1
  180. package/dist/file-hash.port.js +0 -2
  181. package/dist/file-hash.port.js.map +0 -1
  182. package/dist/markdown-generator-noop.adapter.d.ts +0 -5
  183. package/dist/markdown-generator-noop.adapter.d.ts.map +0 -1
  184. package/dist/markdown-generator-noop.adapter.js +0 -6
  185. package/dist/markdown-generator-noop.adapter.js.map +0 -1
  186. package/dist/markdown-generator.port.d.ts +0 -4
  187. package/dist/markdown-generator.port.d.ts.map +0 -1
  188. package/dist/markdown-generator.port.js +0 -3
  189. package/dist/markdown-generator.port.js.map +0 -1
  190. package/dist/secret-manager-noop.adapter.d.ts +0 -9
  191. package/dist/secret-manager-noop.adapter.d.ts.map +0 -1
  192. package/dist/secret-manager-noop.adapter.js +0 -10
  193. package/dist/secret-manager-noop.adapter.js.map +0 -1
  194. package/dist/secret-manager.port.d.ts +0 -5
  195. package/dist/secret-manager.port.d.ts.map +0 -1
  196. package/dist/secret-manager.port.js +0 -2
  197. package/dist/secret-manager.port.js.map +0 -1
  198. package/dist/visitor-id-hash-hono.adapter.d.ts +0 -8
  199. package/dist/visitor-id-hash-hono.adapter.d.ts.map +0 -1
  200. package/dist/visitor-id-hash-hono.adapter.js +0 -13
  201. package/dist/visitor-id-hash-hono.adapter.js.map +0 -1
  202. package/dist/visitor-id-hash.adapter.d.ts +0 -8
  203. package/dist/visitor-id-hash.adapter.d.ts.map +0 -1
  204. package/dist/visitor-id-hash.adapter.js +0 -18
  205. package/dist/visitor-id-hash.adapter.js.map +0 -1
  206. package/dist/visitor-id.vo.d.ts +0 -9
  207. package/dist/visitor-id.vo.d.ts.map +0 -1
  208. package/dist/visitor-id.vo.js +0 -12
  209. package/dist/visitor-id.vo.js.map +0 -1
  210. package/src/client-from-hono.adapter.ts +0 -16
  211. package/src/content-hash-noop.adapter.ts +0 -7
  212. package/src/content-hash.port.ts +0 -5
  213. package/src/file-etag.vo.ts +0 -13
  214. package/src/markdown-generator-noop.adapter.ts +0 -7
  215. package/src/markdown-generator.port.ts +0 -3
  216. package/src/secret-manager-noop.adapter.ts +0 -11
  217. package/src/secret-manager.port.ts +0 -5
  218. package/src/visitor-id-hash-hono.adapter.ts +0 -17
  219. package/src/visitor-id-hash.adapter.ts +0 -21
  220. package/src/visitor-id.vo.ts +0 -15
@@ -0,0 +1,14 @@
1
+ import type { Client } from "./client.vo";
2
+ import type { HashContentPort } from "./hash-content.port";
3
+ import type { VisitorIdPort } from "./visitor-id.port";
4
+ type Dependencies = {
5
+ HashContent: HashContentPort;
6
+ };
7
+ export declare class VisitorIdClientAdapter implements VisitorIdPort {
8
+ private readonly client;
9
+ private readonly deps;
10
+ constructor(client: Client, deps: Dependencies);
11
+ get(): Promise<import("./hash.vo").Hash>;
12
+ }
13
+ export {};
14
+ //# sourceMappingURL=visitor-id-client.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visitor-id-client.adapter.d.ts","sourceRoot":"","sources":["../src/visitor-id-client.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,KAAK,YAAY,GAAG;IAAE,WAAW,EAAE,eAAe,CAAA;CAAE,CAAC;AAErD,qBAAa,sBAAuB,YAAW,aAAa;IAExD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY;IAG/B,GAAG;CAOV"}
@@ -0,0 +1,14 @@
1
+ export class VisitorIdClientAdapter {
2
+ client;
3
+ deps;
4
+ constructor(client, deps) {
5
+ this.client = client;
6
+ this.deps = deps;
7
+ }
8
+ async get() {
9
+ const { ip, ua } = this.client.toJSON();
10
+ const value = `${ip}|${ua}`;
11
+ return this.deps.HashContent.hash(value);
12
+ }
13
+ }
14
+ //# sourceMappingURL=visitor-id-client.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visitor-id-client.adapter.js","sourceRoot":"","sources":["../src/visitor-id-client.adapter.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,sBAAsB;IAEd;IACA;IAFnB,YACmB,MAAc,EACd,IAAkB;QADlB,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAc;IAClC,CAAC;IAEJ,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAExC,MAAM,KAAK,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;QAE5B,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;CACF"}
@@ -1,5 +1,5 @@
1
- import type { VisitorIdType } from "./visitor-id.vo";
1
+ import type { Hash } from "./hash.vo";
2
2
  export interface VisitorIdPort {
3
- get(): Promise<VisitorIdType>;
3
+ get(): Promise<Hash>;
4
4
  }
5
5
  //# sourceMappingURL=visitor-id.port.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visitor-id.port.d.ts","sourceRoot":"","sources":["../src/visitor-id.port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;CAC/B"}
1
+ {"version":3,"file":"visitor-id.port.d.ts","sourceRoot":"","sources":["../src/visitor-id.port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,WAAW,aAAa;IAC5B,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgord/bun",
3
- "version": "1.5.11",
3
+ "version": "1.6.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": "Bartosz Gordon",
@@ -23,7 +23,7 @@
23
23
  "@biomejs/biome": "2.3.10",
24
24
  "@commitlint/cli": "20.2.0",
25
25
  "@commitlint/config-conventional": "20.2.0",
26
- "@types/bun": "1.3.4",
26
+ "@types/bun": "1.3.5",
27
27
  "@types/lodash": "4.17.21",
28
28
  "@types/nodemailer": "7.0.4",
29
29
  "@types/yazl": "3.3.0",
package/readme.md CHANGED
@@ -42,11 +42,18 @@ src/
42
42
  ├── cache-resolver-simple.adapter.ts
43
43
  ├── cache-resolver.port.ts
44
44
  ├── cache-response.middleware.ts
45
+ ├── cache-subject-resolver.vo.ts
46
+ ├── cache-subject-segment-cookie.ts
47
+ ├── cache-subject-segment-fixed.ts
48
+ ├── cache-subject-segment-header.ts
49
+ ├── cache-subject-segment-path.ts
50
+ ├── cache-subject-segment-query.ts
51
+ ├── cache-subject-segment-user.ts
52
+ ├── cache-subject-segment.port.ts
45
53
  ├── certificate-inspector-noop.adapter.ts
46
54
  ├── certificate-inspector-tls.adapter.ts
47
55
  ├── certificate-inspector.port.ts
48
56
  ├── checksum.service.ts
49
- ├── client-from-hono.adapter.ts
50
57
  ├── client.vo.ts
51
58
  ├── clock-fixed.adapter.ts
52
59
  ├── clock-system.adapter.ts
@@ -54,9 +61,6 @@ src/
54
61
  ├── command-envelope.ts
55
62
  ├── command-logger.service.ts
56
63
  ├── command.types.ts
57
- ├── content-hash-noop.adapter.ts
58
- ├── content-hash-sha256-bun.adapter.ts
59
- ├── content-hash.port.ts
60
64
  ├── context.middleware.ts
61
65
  ├── correlation-id.vo.ts
62
66
  ├── correlation-storage.service.ts
@@ -97,10 +101,6 @@ src/
97
101
  ├── file-cleaner.port.ts
98
102
  ├── file-draft-zip.service.ts
99
103
  ├── file-draft.service.ts
100
- ├── file-etag.vo.ts
101
- ├── file-hash-noop.adapter.ts
102
- ├── file-hash-sha256-bun.adapter.ts
103
- ├── file-hash.port.ts
104
104
  ├── file-renamer-fs-forgiving.adapter.ts
105
105
  ├── file-renamer-fs.adapter.ts
106
106
  ├── file-renamer-noop.adapter.ts
@@ -111,6 +111,14 @@ src/
111
111
  ├── gzip-noop.adapter.ts
112
112
  ├── gzip-stream.adapter.ts
113
113
  ├── gzip.port.ts
114
+ ├── hash-content-noop.adapter.ts
115
+ ├── hash-content-sha256-bun.adapter.ts
116
+ ├── hash-content.port.ts
117
+ ├── hash-file-noop.adapter.ts
118
+ ├── hash-file-sha256-bun.adapter.ts
119
+ ├── hash-file.port.ts
120
+ ├── hash-value.vo.ts
121
+ ├── hash.vo.ts
114
122
  ├── hcaptcha-secret-key.vo.ts
115
123
  ├── hcaptcha-site-key.vo.ts
116
124
  ├── healthcheck.service.ts
@@ -162,8 +170,6 @@ src/
162
170
  ├── mailer-smtp.adapter.ts
163
171
  ├── mailer.port.ts
164
172
  ├── mailer.vo.ts
165
- ├── markdown-generator-noop.adapter.ts
166
- ├── markdown-generator.port.ts
167
173
  ├── memory-consumption.service.ts
168
174
  ├── modules
169
175
  │   ├── history
@@ -243,8 +249,6 @@ src/
243
249
  ├── remote-file-storage-noop.adapter.ts
244
250
  ├── remote-file-storage.port.ts
245
251
  ├── safe-parse-body.service.ts
246
- ├── secret-manager-noop.adapter.ts
247
- ├── secret-manager.port.ts
248
252
  ├── secret.vo.ts
249
253
  ├── setup.service.ts
250
254
  ├── shield-api-key.adapter.ts
@@ -272,10 +276,8 @@ src/
272
276
  ├── translations.service.ts
273
277
  ├── uptime.service.ts
274
278
  ├── uuid.vo.ts
275
- ├── visitor-id-hash-hono.adapter.ts
276
- ├── visitor-id-hash.adapter.ts
279
+ ├── visitor-id-client.adapter.ts
277
280
  ├── visitor-id.port.ts
278
- ├── visitor-id.vo.ts
279
281
  └── weak-etag-extractor.middleware.ts
280
282
  ```
281
283
 
@@ -1,19 +1,19 @@
1
- import type { FileHashResult } from "./file-hash.port";
1
+ import type { HashFileResult } from "./hash-file.port";
2
2
 
3
3
  type CacheFileOverridesType = Record<string, string>;
4
4
 
5
5
  interface CacheFileHandler {
6
- notModified(options: FileHashResult, overrides?: CacheFileOverridesType): Response;
6
+ notModified(options: HashFileResult, overrides?: CacheFileOverridesType): Response;
7
7
 
8
- fresh(options: FileHashResult, overrides?: CacheFileOverridesType): Headers;
8
+ fresh(options: HashFileResult, overrides?: CacheFileOverridesType): Headers;
9
9
  }
10
10
 
11
11
  export const CacheFileMustRevalidate: CacheFileHandler = {
12
- notModified(options: FileHashResult, overrides: CacheFileOverridesType = {}) {
12
+ notModified(options: HashFileResult, overrides: CacheFileOverridesType = {}) {
13
13
  return new Response(null, {
14
14
  status: 304,
15
15
  headers: new Headers({
16
- ETag: options.etag,
16
+ ETag: options.etag.get(),
17
17
  "Cache-Control": "private, max-age=0, must-revalidate",
18
18
  "Last-Modified": new Date(options.lastModified.ms).toUTCString(),
19
19
  Vary: "Authorization, Cookie",
@@ -22,11 +22,11 @@ export const CacheFileMustRevalidate: CacheFileHandler = {
22
22
  });
23
23
  },
24
24
 
25
- fresh(options: FileHashResult, overrides: CacheFileOverridesType = {}) {
25
+ fresh(options: HashFileResult, overrides: CacheFileOverridesType = {}) {
26
26
  return new Headers({
27
27
  "Content-Type": options.mime.toString(),
28
28
  "Cache-Control": "private, max-age=0, must-revalidate",
29
- ETag: options.etag,
29
+ ETag: options.etag.get(),
30
30
  "Content-Length": options.size.toBytes().toString(),
31
31
  "Last-Modified": new Date(options.lastModified.ms).toUTCString(),
32
32
  "Accept-Ranges": "bytes",
@@ -1,6 +1,7 @@
1
1
  import type * as tools from "@bgord/tools";
2
2
  import NodeCache from "node-cache";
3
- import type { CacheRepositoryKeyType, CacheRepositoryPort } from "./cache-repository.port";
3
+ import type { CacheRepositoryPort } from "./cache-repository.port";
4
+ import type { Hash } from "./hash.vo";
4
5
 
5
6
  export class CacheRepositoryNodeCacheAdapter implements CacheRepositoryPort {
6
7
  private readonly store: NodeCache;
@@ -15,16 +16,16 @@ export class CacheRepositoryNodeCacheAdapter implements CacheRepositoryPort {
15
16
  });
16
17
  }
17
18
 
18
- async get<T>(key: CacheRepositoryKeyType): Promise<T | null> {
19
- return this.store.get(key) ?? null;
19
+ async get<T>(subject: Hash): Promise<T | null> {
20
+ return this.store.get(subject.get()) ?? null;
20
21
  }
21
22
 
22
- async set<T>(key: CacheRepositoryKeyType, value: T) {
23
- this.store.set(key, value);
23
+ async set<T>(subject: Hash, value: T) {
24
+ this.store.set(subject.get(), value);
24
25
  }
25
26
 
26
- async delete(key: CacheRepositoryKeyType) {
27
- this.store.del(key);
27
+ async delete(subject: Hash) {
28
+ this.store.del(subject.get());
28
29
  }
29
30
 
30
31
  async flush() {
@@ -1,11 +1,10 @@
1
1
  import type * as tools from "@bgord/tools";
2
-
3
- export type CacheRepositoryKeyType = string;
2
+ import type { Hash } from "./hash.vo";
4
3
 
5
4
  export interface CacheRepositoryPort {
6
- get<T>(key: CacheRepositoryKeyType): Promise<T | null>;
7
- set<T>(key: CacheRepositoryKeyType, value: T): Promise<void>;
8
- delete(key: CacheRepositoryKeyType): Promise<void>;
5
+ get<T>(subject: Hash): Promise<T | null>;
6
+ set<T>(subject: Hash, value: T): Promise<void>;
7
+ delete(subject: Hash): Promise<void>;
9
8
  flush(): Promise<void>;
10
9
  get ttl(): tools.Duration;
11
10
  }
@@ -1,27 +1,28 @@
1
- import type { CacheRepositoryKeyType, CacheRepositoryPort } from "./cache-repository.port";
1
+ import type { CacheRepositoryPort } from "./cache-repository.port";
2
2
  import { type CacheResolverPort, CacheSourceEnum } from "./cache-resolver.port";
3
+ import type { Hash } from "./hash.vo";
3
4
 
4
5
  type Dependencies = { CacheRepository: CacheRepositoryPort };
5
6
 
6
7
  export class CacheResolverSimpleAdapter implements CacheResolverPort {
7
8
  constructor(private readonly deps: Dependencies) {}
8
9
 
9
- async resolve<T>(key: CacheRepositoryKeyType, producer: () => Promise<T>): Promise<T> {
10
- const result = await this.resolveWithContext(key, producer);
10
+ async resolve<T>(subject: Hash, producer: () => Promise<T>): Promise<T> {
11
+ const result = await this.resolveWithContext(subject, producer);
11
12
 
12
13
  return result.value;
13
14
  }
14
15
 
15
16
  async resolveWithContext<T>(
16
- key: CacheRepositoryKeyType,
17
+ subject: Hash,
17
18
  producer: () => Promise<T>,
18
19
  ): Promise<{ value: T; source: CacheSourceEnum }> {
19
- const cached = await this.deps.CacheRepository.get<T>(key);
20
+ const cached = await this.deps.CacheRepository.get<T>(subject);
20
21
 
21
22
  if (cached !== null) return { value: cached, source: CacheSourceEnum.hit };
22
23
 
23
24
  const value = await producer();
24
- await this.deps.CacheRepository.set(key, value);
25
+ await this.deps.CacheRepository.set(subject, value);
25
26
 
26
27
  return { value, source: CacheSourceEnum.miss };
27
28
  }
@@ -1,5 +1,5 @@
1
1
  import type * as tools from "@bgord/tools";
2
- import type { CacheRepositoryKeyType } from "./cache-repository.port";
2
+ import type { Hash } from "./hash.vo";
3
3
 
4
4
  export enum CacheSourceEnum {
5
5
  hit = "hit",
@@ -7,10 +7,10 @@ export enum CacheSourceEnum {
7
7
  }
8
8
 
9
9
  export interface CacheResolverPort {
10
- resolve<T>(key: CacheRepositoryKeyType, producer: () => Promise<T>): Promise<T>;
10
+ resolve<T>(subject: Hash, producer: () => Promise<T>): Promise<T>;
11
11
 
12
12
  resolveWithContext<T>(
13
- key: CacheRepositoryKeyType,
13
+ subject: Hash,
14
14
  producer: () => Promise<T>,
15
15
  ): Promise<{ value: T; source: CacheSourceEnum }>;
16
16
 
@@ -1,15 +1,11 @@
1
- import type { Context } from "hono";
2
1
  import { createMiddleware } from "hono/factory";
3
2
  import type { ContentfulStatusCode } from "hono/utils/http-status";
4
3
  import type { CacheResolverPort } from "./cache-resolver.port";
5
-
6
- type SubjectResolver = (c: Context) => string;
4
+ import type { CacheSubjectResolver } from "./cache-subject-resolver.vo";
7
5
 
8
6
  type Dependencies = { CacheResolver: CacheResolverPort };
9
7
 
10
- type CacheResponseOptions = { enabled: boolean; subject: SubjectResolver };
11
-
12
- export const CacheResponseSubjectUrl: SubjectResolver = (c: Context) => `cache_response_${c.req.url}`;
8
+ type CacheResponseOptions = { enabled: boolean; resolver: CacheSubjectResolver };
13
9
 
14
10
  type CachedResponse = {
15
11
  body: string;
@@ -28,9 +24,9 @@ export class CacheResponse {
28
24
  handle = createMiddleware(async (c, next) => {
29
25
  if (!this.config.enabled) return next();
30
26
 
31
- const subject = this.config.subject(c);
27
+ const subject = await this.config.resolver.resolve(c);
32
28
 
33
- const result = await this.deps.CacheResolver.resolveWithContext<CachedResponse>(subject, async () => {
29
+ const result = await this.deps.CacheResolver.resolveWithContext<CachedResponse>(subject.hex, async () => {
34
30
  await next();
35
31
 
36
32
  const response = c.res.clone();
@@ -0,0 +1,30 @@
1
+ import type { Context } from "hono";
2
+ import type { CacheSubjectSegmentPort, CacheSubjectSegmentType } from "./cache-subject-segment.port";
3
+ import type { Hash } from "./hash.vo";
4
+ import type { HashContentPort } from "./hash-content.port";
5
+
6
+ type Dependencies = { HashContent: HashContentPort };
7
+
8
+ export const CacheSubjectResolverError = { NoSegments: "cache.subject.no.segments" };
9
+
10
+ export class CacheSubjectResolver {
11
+ private readonly SEPARATOR = "|";
12
+
13
+ constructor(
14
+ private readonly segments: CacheSubjectSegmentPort[],
15
+ private readonly deps: Dependencies,
16
+ ) {
17
+ if (this.segments.length === 0) throw new Error(CacheSubjectResolverError.NoSegments);
18
+ }
19
+
20
+ async resolve(context?: Context): Promise<{ hex: Hash; raw: CacheSubjectSegmentType[] }> {
21
+ const segments = this.segments.map((segment) =>
22
+ segment.create(context).replaceAll(this.SEPARATOR, encodeURIComponent(this.SEPARATOR)),
23
+ );
24
+ const subject = segments.join(this.SEPARATOR);
25
+
26
+ const hex = await this.deps.HashContent.hash(subject);
27
+
28
+ return { hex, raw: segments };
29
+ }
30
+ }
@@ -0,0 +1,12 @@
1
+ import type { Context } from "hono";
2
+ import { getCookie } from "hono/cookie";
3
+ import type { CacheSubjectSegmentPort } from "./cache-subject-segment.port";
4
+
5
+ export class CacheSubjectSegmentCookie implements CacheSubjectSegmentPort {
6
+ constructor(private readonly name: string) {}
7
+
8
+ create(context?: Context) {
9
+ if (!context) return "";
10
+ return getCookie(context, this.name) ?? "";
11
+ }
12
+ }
@@ -0,0 +1,9 @@
1
+ import type { CacheSubjectSegmentPort } from "./cache-subject-segment.port";
2
+
3
+ export class CacheSubjectSegmentFixed implements CacheSubjectSegmentPort {
4
+ constructor(private readonly value: string) {}
5
+
6
+ create() {
7
+ return this.value;
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ import type { Context } from "hono";
2
+ import type { CacheSubjectSegmentPort } from "./cache-subject-segment.port";
3
+
4
+ export class CacheSubjectSegmentHeader implements CacheSubjectSegmentPort {
5
+ constructor(private readonly name: string) {}
6
+
7
+ create(context?: Context) {
8
+ return context?.req.header(this.name) ?? "";
9
+ }
10
+ }
@@ -0,0 +1,8 @@
1
+ import type { Context } from "hono";
2
+ import type { CacheSubjectSegmentPort } from "./cache-subject-segment.port";
3
+
4
+ export class CacheSubjectSegmentPath implements CacheSubjectSegmentPort {
5
+ create(context?: Context) {
6
+ return context?.req.path ?? "";
7
+ }
8
+ }
@@ -0,0 +1,13 @@
1
+ import type { Context } from "hono";
2
+ import type { CacheSubjectSegmentPort } from "./cache-subject-segment.port";
3
+
4
+ export class CacheSubjectSegmentQuery implements CacheSubjectSegmentPort {
5
+ create(context?: Context) {
6
+ const query = context?.req.query() ?? {};
7
+
8
+ const keys = Object.keys(query).toSorted();
9
+
10
+ if (keys.length === 0) return "";
11
+ return keys.map((key) => `${key}=${query[key]}`).join("&");
12
+ }
13
+ }
@@ -0,0 +1,8 @@
1
+ import type { Context } from "hono";
2
+ import type { CacheSubjectSegmentPort } from "./cache-subject-segment.port";
3
+
4
+ export class CacheSubjectSegmentUser implements CacheSubjectSegmentPort {
5
+ create(context?: Context) {
6
+ return context?.get("user")?.id ?? "anon";
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ import type { Context } from "hono";
2
+
3
+ export type CacheSubjectSegmentType = string;
4
+
5
+ export interface CacheSubjectSegmentPort {
6
+ create(context?: Context): CacheSubjectSegmentType;
7
+ }
@@ -1,4 +1,4 @@
1
- import type { FileHashResult } from "./file-hash.port";
1
+ import type { HashFileResult } from "./hash-file.port";
2
2
 
3
3
  export enum ChecksumStrategy {
4
4
  etag = "etag",
@@ -6,13 +6,13 @@ export enum ChecksumStrategy {
6
6
  }
7
7
 
8
8
  export class Checksum {
9
- static compare(first: FileHashResult, second: FileHashResult, strategy: ChecksumStrategy): boolean {
9
+ static compare(first: HashFileResult, second: HashFileResult, strategy: ChecksumStrategy): boolean {
10
10
  switch (strategy) {
11
11
  case ChecksumStrategy.etag:
12
- return first.etag === second.etag;
12
+ return first.etag.matches(second.etag);
13
13
  case ChecksumStrategy.complex:
14
14
  return (
15
- first.etag === second.etag &&
15
+ first.etag.matches(second.etag) &&
16
16
  first.size === second.size &&
17
17
  first.lastModified &&
18
18
  second.lastModified &&
package/src/client.vo.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import type { Context } from "hono";
2
+ import { getConnInfo } from "hono/bun";
3
+
1
4
  export type ClientIpType = string;
2
5
  export type ClientUaType = string;
3
6
  export type ClientType = { ip: ClientIpType; ua: ClientUaType };
@@ -5,10 +8,21 @@ export type ClientType = { ip: ClientIpType; ua: ClientUaType };
5
8
  export class Client {
6
9
  private constructor(private readonly value: ClientType) {}
7
10
 
8
- static from(ip: ClientIpType | null | undefined, ua: ClientUaType | null | undefined): Client {
11
+ static fromParts(ip: ClientIpType | null | undefined, ua: ClientUaType | null | undefined): Client {
9
12
  return new Client({ ip: ip ?? "anon", ua: ua ?? "anon" });
10
13
  }
11
14
 
15
+ static fromHonoContext(context: Context): Client {
16
+ const info = getConnInfo(context);
17
+
18
+ const ip =
19
+ context.req.header("x-real-ip") || context.req.header("x-forwarded-for") || info?.remote?.address;
20
+
21
+ const ua = context.req.header("user-agent");
22
+
23
+ return Client.fromParts(ip, ua);
24
+ }
25
+
12
26
  toJSON(): ClientType {
13
27
  return this.value;
14
28
  }
@@ -1,9 +1,12 @@
1
1
  import type { z } from "zod/v4";
2
2
  import type { NodeEnvironmentEnum } from "../src/node-env.vo";
3
3
  import type { CacheResolverPort } from "./cache-resolver.port";
4
+ import { CacheSubjectResolver } from "./cache-subject-resolver.vo";
5
+ import { CacheSubjectSegmentFixed } from "./cache-subject-segment-fixed";
4
6
  import type { EnvironmentLoaderPort } from "./environment-loader.port";
7
+ import type { HashContentPort } from "./hash-content.port";
5
8
 
6
- type Dependencies = { CacheResolver: CacheResolverPort };
9
+ type Dependencies = { CacheResolver: CacheResolverPort; HashContent: HashContentPort };
7
10
 
8
11
  export class EnvironmentLoaderProcessSafeAdapter<Schema extends z.ZodObject<any>>
9
12
  implements EnvironmentLoaderPort<Schema>
@@ -15,7 +18,10 @@ export class EnvironmentLoaderProcessSafeAdapter<Schema extends z.ZodObject<any>
15
18
  ) {}
16
19
 
17
20
  async load() {
18
- const result = await this.deps.CacheResolver.resolve("env", async () =>
21
+ const resolver = new CacheSubjectResolver([new CacheSubjectSegmentFixed("env")], this.deps);
22
+ const subject = await resolver.resolve();
23
+
24
+ const result = await this.deps.CacheResolver.resolve(subject.hex, async () =>
19
25
  this.config.Schema.parse(this.env),
20
26
  );
21
27
 
@@ -0,0 +1,8 @@
1
+ import { Hash } from "./hash.vo";
2
+ import type { HashContentPort } from "./hash-content.port";
3
+
4
+ export class HashContentNoopAdapter implements HashContentPort {
5
+ async hash(_content: string) {
6
+ return Hash.fromString("0000000000000000000000000000000000000000000000000000000000000000");
7
+ }
8
+ }
@@ -1,10 +1,11 @@
1
- import type { ContentHashPort } from "./content-hash.port";
1
+ import { Hash } from "./hash.vo";
2
+ import type { HashContentPort } from "./hash-content.port";
2
3
 
3
- export class ContentHashSha256BunAdapter implements ContentHashPort {
4
+ export class HashContentSha256BunAdapter implements HashContentPort {
4
5
  async hash(content: string) {
5
6
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(content));
6
7
  const etag = Buffer.from(digest).toString("hex");
7
8
 
8
- return { etag };
9
+ return Hash.fromString(etag);
9
10
  }
10
11
  }
@@ -0,0 +1,5 @@
1
+ import type { Hash } from "./hash.vo";
2
+
3
+ export interface HashContentPort {
4
+ hash(content: string): Promise<Hash>;
5
+ }
@@ -1,11 +1,11 @@
1
1
  import * as tools from "@bgord/tools";
2
- import { FileEtag } from "./file-etag.vo";
3
- import type { FileHashPort } from "./file-hash.port";
2
+ import { Hash } from "./hash.vo";
3
+ import type { HashFilePort } from "./hash-file.port";
4
4
 
5
- export class FileHashNoopAdapter implements FileHashPort {
5
+ export class HashFileNoopAdapter implements HashFilePort {
6
6
  async hash(_path: tools.FilePathAbsolute | tools.FilePathRelative) {
7
7
  return {
8
- etag: FileEtag.parse("0000000000000000000000000000000000000000000000000000000000000000"),
8
+ etag: Hash.fromString("0000000000000000000000000000000000000000000000000000000000000000"),
9
9
  size: tools.Size.fromBytes(10),
10
10
  lastModified: tools.Timestamp.fromNumber(1000),
11
11
  mime: tools.MIMES.text,
@@ -1,17 +1,20 @@
1
1
  import * as tools from "@bgord/tools";
2
- import { FileEtag } from "./file-etag.vo";
3
- import type { FileHashPort } from "./file-hash.port";
2
+ import type { HashContentPort } from "./hash-content.port";
3
+ import type { HashFilePort } from "./hash-file.port";
4
+
5
+ type Dependencies = { HashContent: HashContentPort };
6
+
7
+ export class HashFileSha256BunAdapter implements HashFilePort {
8
+ constructor(private readonly deps: Dependencies) {}
4
9
 
5
- export class FileHashSha256BunAdapter implements FileHashPort {
6
10
  async hash(path: tools.FilePathAbsolute | tools.FilePathRelative) {
7
11
  const file = Bun.file(path.get());
8
12
  const extension = path.getFilename().getExtension();
9
13
 
10
14
  const arrayBuffer = await file.arrayBuffer();
11
- const digest = await crypto.subtle.digest("SHA-256", arrayBuffer);
12
15
 
13
16
  return {
14
- etag: FileEtag.parse(Buffer.from(digest).toString("hex")),
17
+ etag: await this.deps.HashContent.hash(await file.text()),
15
18
  size: tools.Size.fromBytes(arrayBuffer.byteLength),
16
19
  lastModified: tools.Timestamp.fromNumber(file.lastModified),
17
20
  mime: tools.Mime.fromExtension(extension),
@@ -1,13 +1,13 @@
1
1
  import type * as tools from "@bgord/tools";
2
- import type { FileEtagType } from "./file-etag.vo";
2
+ import type { Hash } from "./hash.vo";
3
3
 
4
- export type FileHashResult = {
5
- etag: FileEtagType;
4
+ export type HashFileResult = {
5
+ etag: Hash;
6
6
  size: tools.Size;
7
7
  lastModified: tools.Timestamp;
8
8
  mime: tools.Mime;
9
9
  };
10
10
 
11
- export interface FileHashPort {
12
- hash(path: tools.FilePathAbsolute | tools.FilePathRelative): Promise<FileHashResult>;
11
+ export interface HashFilePort {
12
+ hash(path: tools.FilePathAbsolute | tools.FilePathRelative): Promise<HashFileResult>;
13
13
  }
@@ -0,0 +1,13 @@
1
+ import { z } from "zod/v4";
2
+
3
+ export const HashValueError = { Type: "hash.value.type", InvalidHex: "hash.value.invalid.hex" } as const;
4
+
5
+ // 64 hex chars allowed
6
+ const CHARS_WHITELIST = /^[a-fA-F0-9]{64}$/;
7
+
8
+ export const HashValue = z
9
+ .string(HashValueError.Type)
10
+ .regex(CHARS_WHITELIST, HashValueError.InvalidHex)
11
+ .brand("HashValue");
12
+
13
+ export type HashValueType = z.infer<typeof HashValue>;