@bgord/bun 1.16.0 → 1.16.2

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 (292) hide show
  1. package/dist/antivirus-clamav.adapter.js +1 -1
  2. package/dist/antivirus-clamav.adapter.js.map +1 -1
  3. package/dist/antivirus-with-logger.adapter.d.ts +17 -0
  4. package/dist/antivirus-with-logger.adapter.d.ts.map +1 -0
  5. package/dist/antivirus-with-logger.adapter.js +35 -0
  6. package/dist/antivirus-with-logger.adapter.js.map +1 -0
  7. package/dist/antivirus-with-semaphore.adapter.d.ts +14 -0
  8. package/dist/antivirus-with-semaphore.adapter.d.ts.map +1 -0
  9. package/dist/antivirus-with-semaphore.adapter.js +10 -0
  10. package/dist/antivirus-with-semaphore.adapter.js.map +1 -0
  11. package/dist/csv-stringifier-noop.adapter.d.ts +5 -0
  12. package/dist/csv-stringifier-noop.adapter.d.ts.map +1 -0
  13. package/dist/csv-stringifier-noop.adapter.js +6 -0
  14. package/dist/csv-stringifier-noop.adapter.js.map +1 -0
  15. package/dist/environment-loader-encrypted.adapter.d.ts.map +1 -1
  16. package/dist/environment-loader-encrypted.adapter.js +0 -1
  17. package/dist/environment-loader-encrypted.adapter.js.map +1 -1
  18. package/dist/environment-loader-noop.adapter.d.ts.map +1 -1
  19. package/dist/environment-loader-noop.adapter.js +0 -1
  20. package/dist/environment-loader-noop.adapter.js.map +1 -1
  21. package/dist/environment-loader-process-safe.adapter.d.ts.map +1 -1
  22. package/dist/environment-loader-process-safe.adapter.js +0 -1
  23. package/dist/environment-loader-process-safe.adapter.js.map +1 -1
  24. package/dist/environment-loader-process.adapter.d.ts.map +1 -1
  25. package/dist/environment-loader-process.adapter.js +0 -1
  26. package/dist/environment-loader-process.adapter.js.map +1 -1
  27. package/dist/event-envelope.d.ts +0 -7
  28. package/dist/event-envelope.d.ts.map +1 -1
  29. package/dist/event-envelope.js +2 -2
  30. package/dist/event-envelope.js.map +1 -1
  31. package/dist/event-loop-lag.service.js +1 -1
  32. package/dist/event-loop-lag.service.js.map +1 -1
  33. package/dist/event-loop-utilization.service.d.ts.map +1 -1
  34. package/dist/event-loop-utilization.service.js +0 -2
  35. package/dist/event-loop-utilization.service.js.map +1 -1
  36. package/dist/event-serializer-collecting.adapter.d.ts +5 -4
  37. package/dist/event-serializer-collecting.adapter.d.ts.map +1 -1
  38. package/dist/event-serializer-collecting.adapter.js.map +1 -1
  39. package/dist/event-serializer-json.adapter.d.ts +3 -2
  40. package/dist/event-serializer-json.adapter.d.ts.map +1 -1
  41. package/dist/event-serializer-json.adapter.js.map +1 -1
  42. package/dist/event-serializer.port.d.ts +3 -2
  43. package/dist/event-serializer.port.d.ts.map +1 -1
  44. package/dist/event-store-with-logger.adapter.d.ts.map +1 -1
  45. package/dist/event-store-with-logger.adapter.js +0 -1
  46. package/dist/event-store-with-logger.adapter.js.map +1 -1
  47. package/dist/event-store.adapter.d.ts +2 -0
  48. package/dist/event-store.adapter.d.ts.map +1 -1
  49. package/dist/event-store.adapter.js +1 -0
  50. package/dist/event-store.adapter.js.map +1 -1
  51. package/dist/event-upcaster-chain.adapter.d.ts +11 -0
  52. package/dist/event-upcaster-chain.adapter.d.ts.map +1 -0
  53. package/dist/event-upcaster-chain.adapter.js +31 -0
  54. package/dist/event-upcaster-chain.adapter.js.map +1 -0
  55. package/dist/event-upcaster-noop.adapter.d.ts +6 -0
  56. package/dist/event-upcaster-noop.adapter.d.ts.map +1 -0
  57. package/dist/event-upcaster-noop.adapter.js +6 -0
  58. package/dist/event-upcaster-noop.adapter.js.map +1 -0
  59. package/dist/event-upcaster-step.vo.d.ts +11 -0
  60. package/dist/event-upcaster-step.vo.d.ts.map +1 -0
  61. package/dist/event-upcaster-step.vo.js +10 -0
  62. package/dist/event-upcaster-step.vo.js.map +1 -0
  63. package/dist/event-upcaster.port.d.ts +5 -0
  64. package/dist/event-upcaster.port.d.ts.map +1 -0
  65. package/dist/event-upcaster.port.js +2 -0
  66. package/dist/event-upcaster.port.js.map +1 -0
  67. package/dist/event-validator-registry.adapter.d.ts.map +1 -1
  68. package/dist/event-validator-registry.adapter.js +0 -1
  69. package/dist/event-validator-registry.adapter.js.map +1 -1
  70. package/dist/event.types.d.ts +1 -1
  71. package/dist/event.types.d.ts.map +1 -1
  72. package/dist/file-copier.adapter.d.ts.map +1 -1
  73. package/dist/file-copier.adapter.js +0 -2
  74. package/dist/file-copier.adapter.js.map +1 -1
  75. package/dist/file-writer-forgiving.adapter.d.ts +6 -0
  76. package/dist/file-writer-forgiving.adapter.d.ts.map +1 -0
  77. package/dist/file-writer-forgiving.adapter.js +10 -0
  78. package/dist/file-writer-forgiving.adapter.js.map +1 -0
  79. package/dist/graceful-shutdown.service.d.ts.map +1 -1
  80. package/dist/graceful-shutdown.service.js +1 -3
  81. package/dist/graceful-shutdown.service.js.map +1 -1
  82. package/dist/image-alpha-with-semaphore.adapter.d.ts +14 -0
  83. package/dist/image-alpha-with-semaphore.adapter.d.ts.map +1 -0
  84. package/dist/image-alpha-with-semaphore.adapter.js +10 -0
  85. package/dist/image-alpha-with-semaphore.adapter.js.map +1 -0
  86. package/dist/image-blur-with-semaphore.adapter.d.ts +14 -0
  87. package/dist/image-blur-with-semaphore.adapter.d.ts.map +1 -0
  88. package/dist/image-blur-with-semaphore.adapter.js +10 -0
  89. package/dist/image-blur-with-semaphore.adapter.js.map +1 -0
  90. package/dist/image-compressor-with-semaphore.adapter.d.ts +14 -0
  91. package/dist/image-compressor-with-semaphore.adapter.d.ts.map +1 -0
  92. package/dist/image-compressor-with-semaphore.adapter.js +10 -0
  93. package/dist/image-compressor-with-semaphore.adapter.js.map +1 -0
  94. package/dist/image-exif-clear-with-semaphore.adapter.d.ts +14 -0
  95. package/dist/image-exif-clear-with-semaphore.adapter.d.ts.map +1 -0
  96. package/dist/image-exif-clear-with-semaphore.adapter.js +10 -0
  97. package/dist/image-exif-clear-with-semaphore.adapter.js.map +1 -0
  98. package/dist/image-formatter-with-semaphore.adapter.d.ts +14 -0
  99. package/dist/image-formatter-with-semaphore.adapter.d.ts.map +1 -0
  100. package/dist/image-formatter-with-semaphore.adapter.js +10 -0
  101. package/dist/image-formatter-with-semaphore.adapter.js.map +1 -0
  102. package/dist/image-grayscale-with-semaphore.adapter.d.ts +14 -0
  103. package/dist/image-grayscale-with-semaphore.adapter.d.ts.map +1 -0
  104. package/dist/image-grayscale-with-semaphore.adapter.js +10 -0
  105. package/dist/image-grayscale-with-semaphore.adapter.js.map +1 -0
  106. package/dist/image-info-with-semaphore.adapter.d.ts +14 -0
  107. package/dist/image-info-with-semaphore.adapter.d.ts.map +1 -0
  108. package/dist/image-info-with-semaphore.adapter.js +10 -0
  109. package/dist/image-info-with-semaphore.adapter.js.map +1 -0
  110. package/dist/image-processor-with-semaphore.adapter.d.ts +14 -0
  111. package/dist/image-processor-with-semaphore.adapter.d.ts.map +1 -0
  112. package/dist/image-processor-with-semaphore.adapter.js +10 -0
  113. package/dist/image-processor-with-semaphore.adapter.js.map +1 -0
  114. package/dist/image-resizer-with-semaphore.adapter.d.ts +14 -0
  115. package/dist/image-resizer-with-semaphore.adapter.d.ts.map +1 -0
  116. package/dist/image-resizer-with-semaphore.adapter.js +10 -0
  117. package/dist/image-resizer-with-semaphore.adapter.js.map +1 -0
  118. package/dist/index.d.ts +19 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +19 -1
  121. package/dist/index.js.map +1 -1
  122. package/dist/language-detector-header.strategy.d.ts.map +1 -1
  123. package/dist/language-detector-header.strategy.js +0 -2
  124. package/dist/language-detector-header.strategy.js.map +1 -1
  125. package/dist/logger.port.d.ts +1 -2
  126. package/dist/logger.port.d.ts.map +1 -1
  127. package/dist/logger.port.js.map +1 -1
  128. package/dist/modules/preferences/command-handlers/handleSetUserLanguageCommand.d.ts.map +1 -1
  129. package/dist/modules/preferences/command-handlers/handleSetUserLanguageCommand.js +4 -8
  130. package/dist/modules/preferences/command-handlers/handleSetUserLanguageCommand.js.map +1 -1
  131. package/dist/modules/system/services/passage-of-time-hourly.service.d.ts.map +1 -1
  132. package/dist/modules/system/services/passage-of-time-hourly.service.js +5 -9
  133. package/dist/modules/system/services/passage-of-time-hourly.service.js.map +1 -1
  134. package/dist/modules/system/services/passage-of-time-minute.service.d.ts.map +1 -1
  135. package/dist/modules/system/services/passage-of-time-minute.service.js +5 -9
  136. package/dist/modules/system/services/passage-of-time-minute.service.js.map +1 -1
  137. package/dist/prerequisite-verifier-dns.adapter.js +1 -1
  138. package/dist/prerequisite-verifier-dns.adapter.js.map +1 -1
  139. package/dist/prerequisite-verifier-with-retry.adapter.d.ts.map +1 -1
  140. package/dist/prerequisite-verifier-with-retry.adapter.js +0 -2
  141. package/dist/prerequisite-verifier-with-retry.adapter.js.map +1 -1
  142. package/dist/prerequisite-verifier.port.d.ts +2 -2
  143. package/dist/prerequisite-verifier.port.d.ts.map +1 -1
  144. package/dist/prerequisite-verifier.port.js +2 -2
  145. package/dist/prerequisite-verifier.port.js.map +1 -1
  146. package/dist/randomness-crypto.strategy.js +1 -1
  147. package/dist/randomness-crypto.strategy.js.map +1 -1
  148. package/dist/redactor-error-cause-depth-limit.strategy.d.ts.map +1 -1
  149. package/dist/redactor-error-cause-depth-limit.strategy.js +2 -6
  150. package/dist/redactor-error-cause-depth-limit.strategy.js.map +1 -1
  151. package/dist/redactor-error-stack-hide.strategy.d.ts.map +1 -1
  152. package/dist/redactor-error-stack-hide.strategy.js +3 -6
  153. package/dist/redactor-error-stack-hide.strategy.js.map +1 -1
  154. package/dist/redactor-mask.strategy.js +2 -2
  155. package/dist/redactor-mask.strategy.js.map +1 -1
  156. package/dist/redactor-metadata-compact-array.strategy.d.ts.map +1 -1
  157. package/dist/redactor-metadata-compact-array.strategy.js +2 -4
  158. package/dist/redactor-metadata-compact-array.strategy.js.map +1 -1
  159. package/dist/redactor-metadata-compact-object.strategy.d.ts.map +1 -1
  160. package/dist/redactor-metadata-compact-object.strategy.js +3 -5
  161. package/dist/redactor-metadata-compact-object.strategy.js.map +1 -1
  162. package/dist/remote-file-storage-noop.adapter.d.ts +4 -7
  163. package/dist/remote-file-storage-noop.adapter.d.ts.map +1 -1
  164. package/dist/remote-file-storage-noop.adapter.js +4 -26
  165. package/dist/remote-file-storage-noop.adapter.js.map +1 -1
  166. package/dist/remote-file-storage-with-logger.adapter.d.ts +21 -0
  167. package/dist/remote-file-storage-with-logger.adapter.d.ts.map +1 -0
  168. package/dist/remote-file-storage-with-logger.adapter.js +111 -0
  169. package/dist/remote-file-storage-with-logger.adapter.js.map +1 -0
  170. package/dist/retry.service.d.ts +0 -3
  171. package/dist/retry.service.d.ts.map +1 -1
  172. package/dist/retry.service.js +0 -3
  173. package/dist/retry.service.js.map +1 -1
  174. package/dist/security-countermeasure-ban.strategy.d.ts.map +1 -1
  175. package/dist/security-countermeasure-ban.strategy.js +5 -8
  176. package/dist/security-countermeasure-ban.strategy.js.map +1 -1
  177. package/dist/semaphore.service.d.ts +10 -0
  178. package/dist/semaphore.service.d.ts.map +1 -0
  179. package/dist/semaphore.service.js +19 -0
  180. package/dist/semaphore.service.js.map +1 -0
  181. package/dist/setup-hono.service.d.ts.map +1 -1
  182. package/dist/setup-hono.service.js +1 -12
  183. package/dist/setup-hono.service.js.map +1 -1
  184. package/dist/sse-registry.adapter.js +1 -1
  185. package/dist/sse-registry.adapter.js.map +1 -1
  186. package/dist/static-files-hono.service.d.ts.map +1 -1
  187. package/dist/static-files-hono.service.js +0 -2
  188. package/dist/static-files-hono.service.js.map +1 -1
  189. package/dist/translations-hono.handler.d.ts +1 -1
  190. package/dist/translations-hono.handler.d.ts.map +1 -1
  191. package/dist/translations-hono.handler.js.map +1 -1
  192. package/dist/woodchopper-diagnostics-collecting.strategy.js +2 -2
  193. package/dist/woodchopper-diagnostics-collecting.strategy.js.map +1 -1
  194. package/dist/woodchopper-diagnostics-console-error.strategy.js +2 -2
  195. package/dist/woodchopper-diagnostics-console-error.strategy.js.map +1 -1
  196. package/dist/woodchopper-dispatcher-async.strategy.d.ts.map +1 -1
  197. package/dist/woodchopper-dispatcher-async.strategy.js +0 -2
  198. package/dist/woodchopper-dispatcher-async.strategy.js.map +1 -1
  199. package/dist/woodchopper-sampling-correlation-id.strategy.js +1 -1
  200. package/dist/woodchopper-sampling-correlation-id.strategy.js.map +1 -1
  201. package/dist/woodchopper-sink-stderr.strategy.js +1 -1
  202. package/dist/woodchopper-sink-stderr.strategy.js.map +1 -1
  203. package/dist/woodchopper-sink-stdout-human.strategy.js +1 -1
  204. package/dist/woodchopper-sink-stdout-human.strategy.js.map +1 -1
  205. package/dist/woodchopper-sink-stdout.strategy.js +1 -1
  206. package/dist/woodchopper-sink-stdout.strategy.js.map +1 -1
  207. package/dist/woodchopper.d.ts.map +1 -1
  208. package/dist/woodchopper.js +1 -2
  209. package/dist/woodchopper.js.map +1 -1
  210. package/package.json +7 -6
  211. package/readme.md +19 -3
  212. package/src/antivirus-clamav.adapter.ts +1 -1
  213. package/src/antivirus-with-logger.adapter.ts +44 -0
  214. package/src/antivirus-with-semaphore.adapter.ts +13 -0
  215. package/src/csv-stringifier-noop.adapter.ts +7 -0
  216. package/src/environment-loader-encrypted.adapter.ts +0 -1
  217. package/src/environment-loader-noop.adapter.ts +0 -1
  218. package/src/environment-loader-process-safe.adapter.ts +0 -1
  219. package/src/environment-loader-process.adapter.ts +0 -1
  220. package/src/event-envelope.ts +2 -2
  221. package/src/event-loop-lag.service.ts +1 -1
  222. package/src/event-loop-utilization.service.ts +0 -2
  223. package/src/event-serializer-collecting.adapter.ts +5 -4
  224. package/src/event-serializer-json.adapter.ts +3 -2
  225. package/src/event-serializer.port.ts +4 -2
  226. package/src/event-store-with-logger.adapter.ts +0 -1
  227. package/src/event-store.adapter.ts +3 -0
  228. package/src/event-upcaster-chain.adapter.ts +49 -0
  229. package/src/event-upcaster-noop.adapter.ts +8 -0
  230. package/src/event-upcaster-step.vo.ts +21 -0
  231. package/src/event-upcaster.port.ts +5 -0
  232. package/src/event-validator-registry.adapter.ts +0 -1
  233. package/src/event.types.ts +1 -1
  234. package/src/file-copier.adapter.ts +0 -2
  235. package/src/file-writer-forgiving.adapter.ts +14 -0
  236. package/src/graceful-shutdown.service.ts +0 -2
  237. package/src/image-alpha-with-semaphore.adapter.ts +13 -0
  238. package/src/image-blur-with-semaphore.adapter.ts +13 -0
  239. package/src/image-compressor-with-semaphore.adapter.ts +13 -0
  240. package/src/image-exif-clear-with-semaphore.adapter.ts +13 -0
  241. package/src/image-formatter-with-semaphore.adapter.ts +13 -0
  242. package/src/image-grayscale-with-semaphore.adapter.ts +13 -0
  243. package/src/image-info-with-semaphore.adapter.ts +13 -0
  244. package/src/image-processor-with-semaphore.adapter.ts +13 -0
  245. package/src/image-resizer-with-semaphore.adapter.ts +13 -0
  246. package/src/index.ts +19 -1
  247. package/src/language-detector-header.strategy.ts +0 -2
  248. package/src/logger.port.ts +1 -2
  249. package/src/modules/preferences/command-handlers/handleSetUserLanguageCommand.ts +9 -9
  250. package/src/modules/system/services/passage-of-time-hourly.service.ts +5 -14
  251. package/src/modules/system/services/passage-of-time-minute.service.ts +5 -14
  252. package/src/prerequisite-verifier-dns.adapter.ts +1 -1
  253. package/src/prerequisite-verifier-with-retry.adapter.ts +0 -2
  254. package/src/prerequisite-verifier.port.ts +3 -3
  255. package/src/randomness-crypto.strategy.ts +1 -1
  256. package/src/redactor-error-cause-depth-limit.strategy.ts +3 -7
  257. package/src/redactor-error-stack-hide.strategy.ts +4 -7
  258. package/src/redactor-mask.strategy.ts +2 -2
  259. package/src/redactor-metadata-compact-array.strategy.ts +2 -4
  260. package/src/redactor-metadata-compact-object.strategy.ts +3 -5
  261. package/src/remote-file-storage-noop.adapter.ts +5 -32
  262. package/src/remote-file-storage-with-logger.adapter.ts +140 -0
  263. package/src/retry.service.ts +0 -4
  264. package/src/security-countermeasure-ban.strategy.ts +4 -9
  265. package/src/semaphore.service.ts +26 -0
  266. package/src/setup-hono.service.ts +1 -12
  267. package/src/sse-registry.adapter.ts +1 -1
  268. package/src/static-files-hono.service.ts +0 -2
  269. package/src/translations-hono.handler.ts +1 -1
  270. package/src/woodchopper-diagnostics-collecting.strategy.ts +2 -2
  271. package/src/woodchopper-diagnostics-console-error.strategy.ts +2 -2
  272. package/src/woodchopper-dispatcher-async.strategy.ts +0 -2
  273. package/src/woodchopper-sampling-correlation-id.strategy.ts +1 -1
  274. package/src/woodchopper-sink-stderr.strategy.ts +1 -1
  275. package/src/woodchopper-sink-stdout-human.strategy.ts +1 -1
  276. package/src/woodchopper-sink-stdout.strategy.ts +1 -1
  277. package/src/woodchopper.ts +1 -2
  278. package/dist/deep-clone-with.d.ts +0 -4
  279. package/dist/deep-clone-with.d.ts.map +0 -1
  280. package/dist/deep-clone-with.js +0 -22
  281. package/dist/deep-clone-with.js.map +0 -1
  282. package/dist/error-normalizer.service.d.ts +0 -12
  283. package/dist/error-normalizer.service.d.ts.map +0 -1
  284. package/dist/error-normalizer.service.js +0 -24
  285. package/dist/error-normalizer.service.js.map +0 -1
  286. package/dist/is-plain-object.d.ts +0 -2
  287. package/dist/is-plain-object.d.ts.map +0 -1
  288. package/dist/is-plain-object.js +0 -7
  289. package/dist/is-plain-object.js.map +0 -1
  290. package/src/deep-clone-with.ts +0 -31
  291. package/src/error-normalizer.service.ts +0 -32
  292. package/src/is-plain-object.ts +0 -7
@@ -0,0 +1,140 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { ClockPort } from "./clock.port";
3
+ import type { LoggerPort } from "./logger.port";
4
+ import type {
5
+ RemoteFileStoragePort,
6
+ RemoteHeadResult,
7
+ RemotePutFromPathInput,
8
+ RemotePutFromPathResult,
9
+ } from "./remote-file-storage.port";
10
+ import { Stopwatch } from "./stopwatch.service";
11
+
12
+ type Dependencies = { inner: RemoteFileStoragePort; Logger: LoggerPort; Clock: ClockPort };
13
+
14
+ export class RemoteFileStorageWithLoggerAdapter implements RemoteFileStoragePort {
15
+ private readonly base = { component: "infra", operation: "remote_file_storage" };
16
+
17
+ constructor(private readonly deps: Dependencies) {}
18
+
19
+ async putFromPath(input: RemotePutFromPathInput): Promise<RemotePutFromPathResult> {
20
+ const duration = new Stopwatch(this.deps);
21
+
22
+ try {
23
+ this.deps.Logger.info({
24
+ message: "Remote file storage put attempt",
25
+ metadata: { key: input.key },
26
+ ...this.base,
27
+ });
28
+
29
+ const result = await this.deps.inner.putFromPath(input);
30
+
31
+ this.deps.Logger.info({
32
+ message: "Remote file storage put success",
33
+ metadata: { key: input.key, size: result.size, duration: duration.stop() },
34
+ ...this.base,
35
+ });
36
+
37
+ return result;
38
+ } catch (error) {
39
+ this.deps.Logger.error({
40
+ message: "Remote file storage put error",
41
+ error,
42
+ metadata: duration.stop(),
43
+ ...this.base,
44
+ });
45
+
46
+ throw error;
47
+ }
48
+ }
49
+
50
+ async head(key: tools.ObjectKeyType): Promise<RemoteHeadResult> {
51
+ const duration = new Stopwatch(this.deps);
52
+
53
+ try {
54
+ this.deps.Logger.info({ message: "Remote file storage head attempt", metadata: { key }, ...this.base });
55
+
56
+ const result = await this.deps.inner.head(key);
57
+
58
+ this.deps.Logger.info({
59
+ message: "Remote file storage head success",
60
+ metadata: { key, exists: result.exists, duration: duration.stop() },
61
+ ...this.base,
62
+ });
63
+
64
+ return result;
65
+ } catch (error) {
66
+ this.deps.Logger.error({
67
+ message: "Remote file storage head error",
68
+ error,
69
+ metadata: duration.stop(),
70
+ ...this.base,
71
+ });
72
+
73
+ throw error;
74
+ }
75
+ }
76
+
77
+ async getStream(key: tools.ObjectKeyType): Promise<ReadableStream | null> {
78
+ const duration = new Stopwatch(this.deps);
79
+
80
+ try {
81
+ this.deps.Logger.info({
82
+ message: "Remote file storage get stream attempt",
83
+ metadata: { key },
84
+ ...this.base,
85
+ });
86
+
87
+ const result = await this.deps.inner.getStream(key);
88
+
89
+ this.deps.Logger.info({
90
+ message: "Remote file storage get stream success",
91
+ metadata: { key, duration: duration.stop() },
92
+ ...this.base,
93
+ });
94
+
95
+ return result;
96
+ } catch (error) {
97
+ this.deps.Logger.error({
98
+ message: "Remote file storage get stream error",
99
+ error,
100
+ metadata: duration.stop(),
101
+ ...this.base,
102
+ });
103
+
104
+ throw error;
105
+ }
106
+ }
107
+
108
+ async delete(key: tools.ObjectKeyType): Promise<void> {
109
+ const duration = new Stopwatch(this.deps);
110
+
111
+ try {
112
+ this.deps.Logger.info({
113
+ message: "Remote file storage delete attempt",
114
+ metadata: { key },
115
+ ...this.base,
116
+ });
117
+
118
+ await this.deps.inner.delete(key);
119
+
120
+ this.deps.Logger.info({
121
+ message: "Remote file storage delete success",
122
+ metadata: { key, duration: duration.stop() },
123
+ ...this.base,
124
+ });
125
+ } catch (error) {
126
+ this.deps.Logger.error({
127
+ message: "Remote file storage delete error",
128
+ error,
129
+ metadata: duration.stop(),
130
+ ...this.base,
131
+ });
132
+
133
+ throw error;
134
+ }
135
+ }
136
+
137
+ get root(): tools.DirectoryPathAbsoluteType {
138
+ return this.deps.inner.root;
139
+ }
140
+ }
@@ -2,8 +2,6 @@ import * as tools from "@bgord/tools";
2
2
  import type { RetryBackoffStrategy } from "./retry-backoff.strategy";
3
3
  import type { SleeperPort } from "./sleeper.port";
4
4
 
5
- export const RetryError = { InvalidMax: "retry.invalid.max" };
6
-
7
5
  type Dependencies = { Sleeper: SleeperPort };
8
6
 
9
7
  export type RetryConfig = {
@@ -16,8 +14,6 @@ export class Retry {
16
14
  constructor(private readonly deps: Dependencies) {}
17
15
 
18
16
  async run<T>(action: () => Promise<T>, config: RetryConfig): Promise<T> {
19
- if (config.max < 1) throw new Error(RetryError.InvalidMax);
20
-
21
17
  let lastError: unknown;
22
18
 
23
19
  for (let attempt = 1; attempt <= config.max; attempt++) {
@@ -1,12 +1,11 @@
1
1
  import * as v from "valibot";
2
2
  import type { ClockPort } from "./clock.port";
3
3
  import { CorrelationStorage } from "./correlation-storage.service";
4
- import { createEventEnvelope } from "./event-envelope";
4
+ import { event } from "./event-envelope";
5
5
  import type { EventStorePort } from "./event-store.port";
6
6
  import type { IdProviderPort } from "./id-provider.port";
7
7
  import type { LoggerPort } from "./logger.port";
8
8
  import {
9
- SECURITY_VIOLATION_DETECTED_EVENT,
10
9
  SecurityViolationDetectedEvent,
11
10
  type SecurityViolationDetectedEventType,
12
11
  } from "./modules/system/events/SECURITY_VIOLATION_DETECTED_EVENT";
@@ -51,13 +50,9 @@ export class SecurityCountermeasureBanStrategy implements SecurityCountermeasure
51
50
  metadata: context,
52
51
  });
53
52
 
54
- const event = v.parse(SecurityViolationDetectedEvent, {
55
- ...createEventEnvelope("security", this.deps),
56
- name: SECURITY_VIOLATION_DETECTED_EVENT,
57
- payload: { action: action.kind, ...context },
58
- } satisfies SecurityViolationDetectedEventType);
59
-
60
- await this.deps.EventStore.save([event]);
53
+ await this.deps.EventStore.save([
54
+ event(SecurityViolationDetectedEvent, "security", { action: action.kind, ...context }, this.deps),
55
+ ]);
61
56
 
62
57
  return action;
63
58
  }
@@ -0,0 +1,26 @@
1
+ import type * as tools from "@bgord/tools";
2
+
3
+ export type SemaphoreConfig = { limit: tools.IntegerPositiveType };
4
+
5
+ export class Semaphore {
6
+ private readonly slots: Array<Promise<void>>;
7
+
8
+ constructor(config: SemaphoreConfig) {
9
+ this.slots = Array.from({ length: config.limit }, () => Promise.resolve());
10
+ }
11
+
12
+ async run<T>(action: () => Promise<T>): Promise<T> {
13
+ const slot = this.slots.shift()!;
14
+ const { promise, resolve } = Promise.withResolvers<void>();
15
+
16
+ this.slots.push(promise);
17
+
18
+ await slot;
19
+
20
+ try {
21
+ return await action();
22
+ } finally {
23
+ resolve();
24
+ }
25
+ }
26
+ }
@@ -69,18 +69,7 @@ export class SetupHono {
69
69
  xFrameOptions: false,
70
70
  }),
71
71
  cors({
72
- // Stryker disable all
73
- origin: (origin, c) => {
74
- // server-to-server, curl, same-origin navigation
75
- if (!origin) return undefined;
76
-
77
- // same-origin fetch
78
- if (origin === new URL(c.req.url).origin) return origin;
79
-
80
- // deny cross-origin
81
- return null;
82
- },
83
- // Stryker restore all
72
+ origin: (origin, c) => (origin === new URL(c.req.url).origin ? origin : null),
84
73
  credentials: false,
85
74
  maxAge: tools.Duration.Minutes(10).seconds,
86
75
  ...config.cors,
@@ -8,7 +8,7 @@ export class SseRegistryAdapter<Messages extends Message> implements SseRegistry
8
8
  register(identity: HashValueType, connection: SseSenderType<Messages>): void {
9
9
  if (!this.senders.has(identity)) this.senders.set(identity, new Set());
10
10
 
11
- this.senders.get(identity)!.add(connection);
11
+ this.senders.get(identity)?.add(connection);
12
12
  }
13
13
 
14
14
  unregister(identity: HashValueType, connection: SseSenderType<Messages>): void {
@@ -72,9 +72,7 @@ export class StaticFilesHono {
72
72
 
73
73
  const contentType = context.res.headers.get("Content-Type");
74
74
 
75
- // Stryker disable all
76
75
  if (contentType?.startsWith("text/html")) staticDocumentHeaders(context, noop);
77
- // Stryker restore all
78
76
  else staticAssetHeaders(context, noop);
79
77
  },
80
78
  etag(),
@@ -19,7 +19,7 @@ export class TranslationsHonoHandler<T extends tools.LanguageType> implements Ha
19
19
  }
20
20
 
21
21
  handle() {
22
- return factory.createHandlers<{}, any, { Variables: LanguageDetectorVariables }>(async (c) => {
22
+ return factory.createHandlers<any, any, { Variables: LanguageDetectorVariables }>(async (c) => {
23
23
  const language = c.get("language");
24
24
  const result = await this.handler.execute(language);
25
25
 
@@ -1,4 +1,4 @@
1
- import { ErrorNormalizer } from "./error-normalizer.service";
1
+ import * as tools from "@bgord/tools";
2
2
  import type {
3
3
  WoodchopperDiagnosticsStrategy,
4
4
  WoodchopperDiagnosticType,
@@ -8,6 +8,6 @@ export class WoodchopperDiagnosticsCollecting implements WoodchopperDiagnosticsS
8
8
  readonly entries: Array<WoodchopperDiagnosticType> = [];
9
9
 
10
10
  handle(diagnostic: WoodchopperDiagnosticType): void {
11
- this.entries.push({ ...diagnostic, error: ErrorNormalizer.normalize(diagnostic.error) });
11
+ this.entries.push({ ...diagnostic, error: tools.ErrorNormalizer.normalize(diagnostic.error) });
12
12
  }
13
13
  }
@@ -1,4 +1,4 @@
1
- import { ErrorNormalizer } from "./error-normalizer.service";
1
+ import * as tools from "@bgord/tools";
2
2
  import type { RedactorStrategy } from "./redactor.strategy";
3
3
  import type {
4
4
  WoodchopperDiagnosticsStrategy,
@@ -9,7 +9,7 @@ export class WoodchopperDiagnosticsConsoleError implements WoodchopperDiagnostic
9
9
  constructor(private readonly redactor?: RedactorStrategy) {}
10
10
 
11
11
  handle(diagnostic: WoodchopperDiagnosticType): void {
12
- const output = { ...diagnostic, error: ErrorNormalizer.normalize(diagnostic.error) };
12
+ const output = { ...diagnostic, error: tools.ErrorNormalizer.normalize(diagnostic.error) };
13
13
 
14
14
  // biome-ignore lint: lint/suspicious/noConsole
15
15
  console.error(this.redactor ? this.redactor.redact(output) : output);
@@ -73,9 +73,7 @@ export class WoodchopperDispatcherAsync implements WoodchopperDispatcher {
73
73
  try {
74
74
  this.sink.write(entry as LoggerEntry);
75
75
  } catch (error) {
76
- // Stryker disable all
77
76
  this.onError?.(error);
78
- // Stryker restore all
79
77
  }
80
78
  }
81
79
  }
@@ -9,8 +9,8 @@ export class WoodchoperSamplingCorrelationId implements WoodchopperSamplingStrat
9
9
  constructor(private readonly config: Config) {}
10
10
 
11
11
  decide(entry: LoggerEntry): boolean {
12
- // Stryker disable all
13
12
  if (!entry.correlationId) return false;
13
+ // Stryker disable all
14
14
  return fnv1a32(entry.correlationId) % this.config.everyNth === 0;
15
15
  // Stryker restore all
16
16
  }
@@ -3,6 +3,6 @@ import type { WoodchopperSinkStrategy } from "./woodchopper-sink.strategy";
3
3
 
4
4
  export class WoodchopperSinkStderr implements WoodchopperSinkStrategy {
5
5
  write(entry: LoggerEntry): void {
6
- process.stderr.write(JSON.stringify(entry) + "\n");
6
+ process.stderr.write(`${JSON.stringify(entry)}\n`);
7
7
  }
8
8
  }
@@ -3,6 +3,6 @@ import type { WoodchopperSinkStrategy } from "./woodchopper-sink.strategy";
3
3
 
4
4
  export class WoodchopperSinkStdoutHuman implements WoodchopperSinkStrategy {
5
5
  write(entry: LoggerEntry): void {
6
- process.stdout.write(JSON.stringify(entry, null, 2) + "\n");
6
+ process.stdout.write(`${JSON.stringify(entry, null, 2)}\n`);
7
7
  }
8
8
  }
@@ -3,6 +3,6 @@ import type { WoodchopperSinkStrategy } from "./woodchopper-sink.strategy";
3
3
 
4
4
  export class WoodchopperSinkStdout implements WoodchopperSinkStrategy {
5
5
  write(entry: LoggerEntry): void {
6
- process.stdout.write(JSON.stringify(entry) + "\n");
6
+ process.stdout.write(`${JSON.stringify(entry)}\n`);
7
7
  }
8
8
  }
@@ -1,6 +1,5 @@
1
1
  import * as tools from "@bgord/tools";
2
2
  import type { ClockPort } from "./clock.port";
3
- import { ErrorNormalizer } from "./error-normalizer.service";
4
3
  import {
5
4
  type LoggerAppType,
6
5
  type LoggerEntry,
@@ -64,7 +63,7 @@ export class Woodchopper implements LoggerPort, LoggerStatsProviderPort {
64
63
  let withNormalization: LoggerEntryBare | LoggerEntryBareWithError;
65
64
  try {
66
65
  withNormalization =
67
- "error" in entry ? { ...entry, error: ErrorNormalizer.normalize(entry.error) } : entry;
66
+ "error" in entry ? { ...entry, error: tools.ErrorNormalizer.normalize(entry.error) } : entry;
68
67
  } catch (error) {
69
68
  this.stats.recordDropped();
70
69
  this.config.diagnostics?.handle({ kind: "normalization", error });
@@ -1,4 +0,0 @@
1
- export declare function deepCloneWith<T>(value: T, replacer: (value: unknown, key?: string) => unknown, options?: {
2
- allowRootReplace?: boolean;
3
- }): T;
4
- //# sourceMappingURL=deep-clone-with.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deep-clone-with.d.ts","sourceRoot":"","sources":["../src/deep-clone-with.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,EACnD,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3C,CAAC,CAwBH"}
@@ -1,22 +0,0 @@
1
- import { isPlainObject } from "./is-plain-object";
2
- export function deepCloneWith(value, replacer, options = {}) {
3
- const allowRootReplace = options.allowRootReplace ?? false;
4
- function clone(current, key, isRoot = false) {
5
- const replaced = replacer(current, key);
6
- if (replaced !== undefined && (!isRoot || allowRootReplace))
7
- return replaced;
8
- if (Array.isArray(current))
9
- return current.map((item) => clone(item));
10
- if (isPlainObject(current)) {
11
- const result = {};
12
- for (const ownKey of Reflect.ownKeys(current)) {
13
- const value = current[ownKey];
14
- result[ownKey] = clone(value, ownKey);
15
- }
16
- return result;
17
- }
18
- return current;
19
- }
20
- return clone(value, undefined, true);
21
- }
22
- //# sourceMappingURL=deep-clone-with.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deep-clone-with.js","sourceRoot":"","sources":["../src/deep-clone-with.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,UAAU,aAAa,CAC3B,KAAQ,EACR,QAAmD,EACnD,UAA0C,EAAE;IAE5C,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC;IAE3D,SAAS,KAAK,CAAC,OAAgB,EAAE,GAAY,EAAE,MAAM,GAAG,KAAK;QAC3D,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAExC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,IAAI,gBAAgB,CAAC;YAAE,OAAO,QAAQ,CAAC;QAE7E,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAEtE,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAqC,EAAE,CAAC;YAEpD,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC9B,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,MAAgB,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAM,CAAC;AAC5C,CAAC"}
@@ -1,12 +0,0 @@
1
- export type NormalizedError = {
2
- message: string;
3
- name?: string;
4
- stack?: string;
5
- cause?: NormalizedError;
6
- };
7
- export declare class ErrorNormalizer {
8
- static normalize(error: unknown): NormalizedError;
9
- static isNormalizedError(value: unknown): value is NormalizedError;
10
- private static normalizeWithGuard;
11
- }
12
- //# sourceMappingURL=error-normalizer.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"error-normalizer.service.d.ts","sourceRoot":"","sources":["../src/error-normalizer.service.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,CAAA;CAAE,CAAC;AAE1G,qBAAa,eAAe;IAC1B,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe;IAIjD,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe;IAIlE,OAAO,CAAC,MAAM,CAAC,kBAAkB;CAkBlC"}
@@ -1,24 +0,0 @@
1
- import { isPlainObject } from "./is-plain-object";
2
- export class ErrorNormalizer {
3
- static normalize(error) {
4
- return ErrorNormalizer.normalizeWithGuard(error, new WeakSet());
5
- }
6
- static isNormalizedError(value) {
7
- return isPlainObject(value) && "message" in value && typeof value["message"] === "string";
8
- }
9
- static normalizeWithGuard(error, seen) {
10
- if (error instanceof Error) {
11
- if (seen.has(error))
12
- return { message: error.message, name: error.name };
13
- seen.add(error);
14
- const cause = error.cause instanceof Error
15
- ? ErrorNormalizer.normalizeWithGuard(error.cause, seen)
16
- : typeof error.cause === "string"
17
- ? { message: error.cause }
18
- : undefined;
19
- return { message: error.message, name: error.name, stack: error.stack, cause };
20
- }
21
- return { message: String(error) };
22
- }
23
- }
24
- //# sourceMappingURL=error-normalizer.service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"error-normalizer.service.js","sourceRoot":"","sources":["../src/error-normalizer.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIlD,MAAM,OAAO,eAAe;IAC1B,MAAM,CAAC,SAAS,CAAC,KAAc;QAC7B,OAAO,eAAe,CAAC,kBAAkB,CAAC,KAAK,EAAE,IAAI,OAAO,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,CAAC,iBAAiB,CAAC,KAAc;QACrC,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,SAAS,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC;IAC5F,CAAC;IAEO,MAAM,CAAC,kBAAkB,CAAC,KAAc,EAAE,IAAqB;QACrE,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YAEzE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAEhB,MAAM,KAAK,GACT,KAAK,CAAC,KAAK,YAAY,KAAK;gBAC1B,CAAC,CAAC,eAAe,CAAC,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC;gBACvD,CAAC,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;oBAC/B,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE;oBAC1B,CAAC,CAAC,SAAS,CAAC;YAElB,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;QACjF,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACpC,CAAC;CACF"}
@@ -1,2 +0,0 @@
1
- export declare function isPlainObject(value: unknown): value is Record<string | symbol, unknown>;
2
- //# sourceMappingURL=is-plain-object.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-plain-object.d.ts","sourceRoot":"","sources":["../src/is-plain-object.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAMvF"}
@@ -1,7 +0,0 @@
1
- export function isPlainObject(value) {
2
- if (!value)
3
- return false;
4
- const prototype = Object.getPrototypeOf(value);
5
- return prototype === Object.prototype || prototype === null;
6
- }
7
- //# sourceMappingURL=is-plain-object.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-plain-object.js","sourceRoot":"","sources":["../src/is-plain-object.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;AAC9D,CAAC"}
@@ -1,31 +0,0 @@
1
- import { isPlainObject } from "./is-plain-object";
2
-
3
- export function deepCloneWith<T>(
4
- value: T,
5
- replacer: (value: unknown, key?: string) => unknown,
6
- options: { allowRootReplace?: boolean } = {},
7
- ): T {
8
- const allowRootReplace = options.allowRootReplace ?? false;
9
-
10
- function clone(current: unknown, key?: string, isRoot = false): unknown {
11
- const replaced = replacer(current, key);
12
-
13
- if (replaced !== undefined && (!isRoot || allowRootReplace)) return replaced;
14
-
15
- if (Array.isArray(current)) return current.map((item) => clone(item));
16
-
17
- if (isPlainObject(current)) {
18
- const result: Record<string | symbol, unknown> = {};
19
-
20
- for (const ownKey of Reflect.ownKeys(current)) {
21
- const value = current[ownKey];
22
- result[ownKey] = clone(value, ownKey as string);
23
- }
24
- return result;
25
- }
26
-
27
- return current;
28
- }
29
-
30
- return clone(value, undefined, true) as T;
31
- }
@@ -1,32 +0,0 @@
1
- import { isPlainObject } from "./is-plain-object";
2
-
3
- export type NormalizedError = { message: string; name?: string; stack?: string; cause?: NormalizedError };
4
-
5
- export class ErrorNormalizer {
6
- static normalize(error: unknown): NormalizedError {
7
- return ErrorNormalizer.normalizeWithGuard(error, new WeakSet());
8
- }
9
-
10
- static isNormalizedError(value: unknown): value is NormalizedError {
11
- return isPlainObject(value) && "message" in value && typeof value["message"] === "string";
12
- }
13
-
14
- private static normalizeWithGuard(error: unknown, seen: WeakSet<object>): NormalizedError {
15
- if (error instanceof Error) {
16
- if (seen.has(error)) return { message: error.message, name: error.name };
17
-
18
- seen.add(error);
19
-
20
- const cause =
21
- error.cause instanceof Error
22
- ? ErrorNormalizer.normalizeWithGuard(error.cause, seen)
23
- : typeof error.cause === "string"
24
- ? { message: error.cause }
25
- : undefined;
26
-
27
- return { message: error.message, name: error.name, stack: error.stack, cause };
28
- }
29
-
30
- return { message: String(error) };
31
- }
32
- }
@@ -1,7 +0,0 @@
1
- export function isPlainObject(value: unknown): value is Record<string | symbol, unknown> {
2
- if (!value) return false;
3
-
4
- const prototype = Object.getPrototypeOf(value);
5
-
6
- return prototype === Object.prototype || prototype === null;
7
- }