@bgord/bun 1.19.13 → 1.19.14

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 (245) hide show
  1. package/dist/ab-hono-noop.middleware.d.ts +2 -3
  2. package/dist/ab-hono-noop.middleware.d.ts.map +1 -1
  3. package/dist/ab-hono-noop.middleware.js +4 -9
  4. package/dist/ab-hono-noop.middleware.js.map +1 -1
  5. package/dist/ab-variant-name.vo.d.ts +9 -0
  6. package/dist/ab-variant-name.vo.d.ts.map +1 -0
  7. package/dist/ab-variant-name.vo.js +10 -0
  8. package/dist/ab-variant-name.vo.js.map +1 -0
  9. package/dist/ab-variant.vo.d.ts +2 -1
  10. package/dist/ab-variant.vo.d.ts.map +1 -1
  11. package/dist/ab-variant.vo.js.map +1 -1
  12. package/dist/basic-auth-password.vo.d.ts +2 -1
  13. package/dist/basic-auth-password.vo.d.ts.map +1 -1
  14. package/dist/basic-auth-password.vo.js +2 -1
  15. package/dist/basic-auth-password.vo.js.map +1 -1
  16. package/dist/basic-auth-username.vo.d.ts +2 -1
  17. package/dist/basic-auth-username.vo.d.ts.map +1 -1
  18. package/dist/basic-auth-username.vo.js +2 -1
  19. package/dist/basic-auth-username.vo.js.map +1 -1
  20. package/dist/cache-repository-redis.adapter.d.ts +1 -2
  21. package/dist/cache-repository-redis.adapter.d.ts.map +1 -1
  22. package/dist/cache-repository-redis.adapter.js.map +1 -1
  23. package/dist/certificate-inspector-noop.adapter.d.ts +2 -1
  24. package/dist/certificate-inspector-noop.adapter.d.ts.map +1 -1
  25. package/dist/certificate-inspector-noop.adapter.js.map +1 -1
  26. package/dist/certificate-inspector-tls.adapter.d.ts +2 -1
  27. package/dist/certificate-inspector-tls.adapter.d.ts.map +1 -1
  28. package/dist/certificate-inspector-tls.adapter.js.map +1 -1
  29. package/dist/certificate-inspector.port.d.ts +2 -1
  30. package/dist/certificate-inspector.port.d.ts.map +1 -1
  31. package/dist/csv-stringifier.adapter.d.ts.map +1 -1
  32. package/dist/csv-stringifier.adapter.js +1 -0
  33. package/dist/csv-stringifier.adapter.js.map +1 -1
  34. package/dist/environment-loader-encrypted.adapter.d.ts +1 -1
  35. package/dist/environment-loader-encrypted.adapter.d.ts.map +1 -1
  36. package/dist/environment-loader-encrypted.adapter.js +5 -7
  37. package/dist/environment-loader-encrypted.adapter.js.map +1 -1
  38. package/dist/environment-loader-noop.adapter.d.ts +1 -1
  39. package/dist/environment-loader-noop.adapter.d.ts.map +1 -1
  40. package/dist/environment-loader-noop.adapter.js +5 -7
  41. package/dist/environment-loader-noop.adapter.js.map +1 -1
  42. package/dist/environment-loader-process-safe.adapter.d.ts +1 -1
  43. package/dist/environment-loader-process-safe.adapter.d.ts.map +1 -1
  44. package/dist/environment-loader-process-safe.adapter.js +2 -9
  45. package/dist/environment-loader-process-safe.adapter.js.map +1 -1
  46. package/dist/environment-loader-process.adapter.d.ts +1 -1
  47. package/dist/environment-loader-process.adapter.d.ts.map +1 -1
  48. package/dist/environment-loader-process.adapter.js +5 -7
  49. package/dist/environment-loader-process.adapter.js.map +1 -1
  50. package/dist/environment-loader.port.d.ts +0 -3
  51. package/dist/environment-loader.port.d.ts.map +1 -1
  52. package/dist/environment-loader.port.js +1 -1
  53. package/dist/environment-loader.port.js.map +1 -1
  54. package/dist/event-upcaster-chain.adapter.d.ts.map +1 -1
  55. package/dist/event-upcaster-chain.adapter.js +5 -0
  56. package/dist/event-upcaster-chain.adapter.js.map +1 -1
  57. package/dist/event-validator-registry.adapter.d.ts +1 -1
  58. package/dist/event-validator-registry.adapter.d.ts.map +1 -1
  59. package/dist/event-validator-registry.adapter.js +2 -7
  60. package/dist/event-validator-registry.adapter.js.map +1 -1
  61. package/dist/event-validator-registry.port.d.ts +0 -3
  62. package/dist/event-validator-registry.port.d.ts.map +1 -1
  63. package/dist/event-validator-registry.port.js +1 -1
  64. package/dist/event-validator-registry.port.js.map +1 -1
  65. package/dist/file-uploader-hono.middleware.d.ts.map +1 -1
  66. package/dist/file-uploader-hono.middleware.js +4 -13
  67. package/dist/file-uploader-hono.middleware.js.map +1 -1
  68. package/dist/file-uploader.middleware.d.ts.map +1 -1
  69. package/dist/file-uploader.middleware.js +1 -0
  70. package/dist/file-uploader.middleware.js.map +1 -1
  71. package/dist/graceful-shutdown.service.d.ts +8 -4
  72. package/dist/graceful-shutdown.service.d.ts.map +1 -1
  73. package/dist/graceful-shutdown.service.js +27 -26
  74. package/dist/graceful-shutdown.service.js.map +1 -1
  75. package/dist/hostname.vo.d.ts +8 -0
  76. package/dist/hostname.vo.d.ts.map +1 -0
  77. package/dist/hostname.vo.js +9 -0
  78. package/dist/hostname.vo.js.map +1 -0
  79. package/dist/http-logger.middleware.js +1 -1
  80. package/dist/http-logger.middleware.js.map +1 -1
  81. package/dist/image-blur.adapter.d.ts +2 -0
  82. package/dist/image-blur.adapter.d.ts.map +1 -1
  83. package/dist/image-blur.adapter.js +1 -1
  84. package/dist/image-blur.adapter.js.map +1 -1
  85. package/dist/image-compressor.adapter.d.ts +2 -0
  86. package/dist/image-compressor.adapter.d.ts.map +1 -1
  87. package/dist/image-compressor.adapter.js +1 -1
  88. package/dist/image-compressor.adapter.js.map +1 -1
  89. package/dist/image-exif-clear.adapter.d.ts +2 -0
  90. package/dist/image-exif-clear.adapter.d.ts.map +1 -1
  91. package/dist/image-exif-clear.adapter.js +1 -1
  92. package/dist/image-exif-clear.adapter.js.map +1 -1
  93. package/dist/image-formatter.adapter.d.ts +2 -0
  94. package/dist/image-formatter.adapter.d.ts.map +1 -1
  95. package/dist/image-formatter.adapter.js +1 -1
  96. package/dist/image-formatter.adapter.js.map +1 -1
  97. package/dist/image-generator-web-view.adapter.d.ts.map +1 -1
  98. package/dist/image-generator-web-view.adapter.js +1 -0
  99. package/dist/image-generator-web-view.adapter.js.map +1 -1
  100. package/dist/image-grayscale.adapter.d.ts +2 -0
  101. package/dist/image-grayscale.adapter.d.ts.map +1 -1
  102. package/dist/image-grayscale.adapter.js +1 -1
  103. package/dist/image-grayscale.adapter.js.map +1 -1
  104. package/dist/image-processor.adapter.d.ts +2 -0
  105. package/dist/image-processor.adapter.d.ts.map +1 -1
  106. package/dist/image-processor.adapter.js +1 -1
  107. package/dist/image-processor.adapter.js.map +1 -1
  108. package/dist/image-resizer.adapter.d.ts +2 -0
  109. package/dist/image-resizer.adapter.d.ts.map +1 -1
  110. package/dist/image-resizer.adapter.js +1 -1
  111. package/dist/image-resizer.adapter.js.map +1 -1
  112. package/dist/image.types.d.ts +1 -1
  113. package/dist/image.types.d.ts.map +1 -1
  114. package/dist/index.d.ts +2 -0
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +2 -0
  117. package/dist/index.js.map +1 -1
  118. package/dist/job-registry.adapter.d.ts +1 -1
  119. package/dist/job-registry.adapter.d.ts.map +1 -1
  120. package/dist/job-registry.adapter.js +2 -7
  121. package/dist/job-registry.adapter.js.map +1 -1
  122. package/dist/job-registry.port.d.ts +0 -3
  123. package/dist/job-registry.port.d.ts.map +1 -1
  124. package/dist/job-registry.port.js +1 -1
  125. package/dist/job-registry.port.js.map +1 -1
  126. package/dist/prerequisite-verifier-binary.adapter.js +1 -1
  127. package/dist/prerequisite-verifier-binary.adapter.js.map +1 -1
  128. package/dist/prerequisite-verifier-dns.adapter.d.ts +2 -1
  129. package/dist/prerequisite-verifier-dns.adapter.d.ts.map +1 -1
  130. package/dist/prerequisite-verifier-dns.adapter.js.map +1 -1
  131. package/dist/prerequisite-verifier-ssl-certificate-expiry.adapter.d.ts +2 -1
  132. package/dist/prerequisite-verifier-ssl-certificate-expiry.adapter.d.ts.map +1 -1
  133. package/dist/prerequisite-verifier-ssl-certificate-expiry.adapter.js.map +1 -1
  134. package/dist/prerequisite-verifier-translations.adapter.js +5 -5
  135. package/dist/prerequisite-verifier-translations.adapter.js.map +1 -1
  136. package/dist/reactive-config-file-json.adapter.d.ts +1 -1
  137. package/dist/reactive-config-file-json.adapter.d.ts.map +1 -1
  138. package/dist/reactive-config-file-json.adapter.js +2 -7
  139. package/dist/reactive-config-file-json.adapter.js.map +1 -1
  140. package/dist/reactive-config-noop.adapter.d.ts +1 -1
  141. package/dist/reactive-config-noop.adapter.d.ts.map +1 -1
  142. package/dist/reactive-config-noop.adapter.js +2 -7
  143. package/dist/reactive-config-noop.adapter.js.map +1 -1
  144. package/dist/reactive-config-with-fallback.adapter.d.ts +1 -1
  145. package/dist/reactive-config-with-fallback.adapter.d.ts.map +1 -1
  146. package/dist/reactive-config-with-fallback.adapter.js +2 -7
  147. package/dist/reactive-config-with-fallback.adapter.js.map +1 -1
  148. package/dist/reactive-config.port.d.ts +0 -3
  149. package/dist/reactive-config.port.d.ts.map +1 -1
  150. package/dist/reactive-config.port.js +1 -1
  151. package/dist/reactive-config.port.js.map +1 -1
  152. package/dist/remote-file-storage-disk.adapter.d.ts +2 -0
  153. package/dist/remote-file-storage-disk.adapter.d.ts.map +1 -1
  154. package/dist/remote-file-storage-disk.adapter.js +1 -1
  155. package/dist/remote-file-storage-disk.adapter.js.map +1 -1
  156. package/dist/shield-api-key.strategy.d.ts.map +1 -1
  157. package/dist/shield-api-key.strategy.js +6 -1
  158. package/dist/shield-api-key.strategy.js.map +1 -1
  159. package/dist/shield-basic-auth.strategy.d.ts.map +1 -1
  160. package/dist/shield-basic-auth.strategy.js +3 -2
  161. package/dist/shield-basic-auth.strategy.js.map +1 -1
  162. package/dist/shield-recaptcha.strategy.js +1 -1
  163. package/dist/shield-recaptcha.strategy.js.map +1 -1
  164. package/dist/sitemap-entry.vo.d.ts +1 -0
  165. package/dist/sitemap-entry.vo.d.ts.map +1 -1
  166. package/dist/sitemap-entry.vo.js +9 -1
  167. package/dist/sitemap-entry.vo.js.map +1 -1
  168. package/dist/standard-schema-validator.service.d.ts +5 -0
  169. package/dist/standard-schema-validator.service.d.ts.map +1 -0
  170. package/dist/standard-schema-validator.service.js +14 -0
  171. package/dist/standard-schema-validator.service.js.map +1 -0
  172. package/dist/subject-application-resolver.vo.d.ts +0 -1
  173. package/dist/subject-application-resolver.vo.d.ts.map +1 -1
  174. package/dist/subject-application-resolver.vo.js +2 -3
  175. package/dist/subject-application-resolver.vo.js.map +1 -1
  176. package/dist/subject-request-resolver.vo.d.ts +0 -1
  177. package/dist/subject-request-resolver.vo.d.ts.map +1 -1
  178. package/dist/subject-request-resolver.vo.js +2 -3
  179. package/dist/subject-request-resolver.vo.js.map +1 -1
  180. package/dist/temporary-file-absolute.adapter.d.ts +2 -0
  181. package/dist/temporary-file-absolute.adapter.d.ts.map +1 -1
  182. package/dist/temporary-file-absolute.adapter.js +1 -1
  183. package/dist/temporary-file-absolute.adapter.js.map +1 -1
  184. package/dist/timing.middleware.d.ts.map +1 -1
  185. package/dist/timing.middleware.js +1 -2
  186. package/dist/timing.middleware.js.map +1 -1
  187. package/dist/woodchopper-sampling-every-nth.strategy.d.ts.map +1 -1
  188. package/dist/woodchopper-sampling-every-nth.strategy.js +1 -3
  189. package/dist/woodchopper-sampling-every-nth.strategy.js.map +1 -1
  190. package/package.json +7 -7
  191. package/readme.md +3 -0
  192. package/src/ab-hono-noop.middleware.ts +2 -13
  193. package/src/ab-variant-name.vo.ts +17 -0
  194. package/src/ab-variant.vo.ts +2 -1
  195. package/src/basic-auth-password.vo.ts +5 -0
  196. package/src/basic-auth-username.vo.ts +5 -0
  197. package/src/cache-repository-redis.adapter.ts +1 -2
  198. package/src/certificate-inspector-noop.adapter.ts +2 -1
  199. package/src/certificate-inspector-tls.adapter.ts +2 -1
  200. package/src/certificate-inspector.port.ts +2 -1
  201. package/src/csv-stringifier.adapter.ts +1 -0
  202. package/src/environment-loader-encrypted.adapter.ts +9 -9
  203. package/src/environment-loader-noop.adapter.ts +9 -9
  204. package/src/environment-loader-process-safe.adapter.ts +8 -11
  205. package/src/environment-loader-process.adapter.ts +9 -9
  206. package/src/environment-loader.port.ts +0 -2
  207. package/src/event-upcaster-chain.adapter.ts +5 -0
  208. package/src/event-validator-registry.adapter.ts +3 -9
  209. package/src/event-validator-registry.port.ts +0 -2
  210. package/src/file-uploader-hono.middleware.ts +3 -17
  211. package/src/file-uploader.middleware.ts +1 -0
  212. package/src/graceful-shutdown.service.ts +27 -28
  213. package/src/hostname.vo.ts +15 -0
  214. package/src/http-logger.middleware.ts +1 -1
  215. package/src/image-blur.adapter.ts +9 -2
  216. package/src/image-compressor.adapter.ts +9 -2
  217. package/src/image-exif-clear.adapter.ts +9 -2
  218. package/src/image-formatter.adapter.ts +5 -1
  219. package/src/image-generator-web-view.adapter.ts +1 -0
  220. package/src/image-grayscale.adapter.ts +9 -2
  221. package/src/image-processor.adapter.ts +5 -1
  222. package/src/image-resizer.adapter.ts +9 -2
  223. package/src/image.types.ts +1 -1
  224. package/src/index.ts +2 -0
  225. package/src/job-registry.adapter.ts +3 -6
  226. package/src/job-registry.port.ts +0 -2
  227. package/src/prerequisite-verifier-binary.adapter.ts +1 -1
  228. package/src/prerequisite-verifier-dns.adapter.ts +2 -1
  229. package/src/prerequisite-verifier-ssl-certificate-expiry.adapter.ts +2 -1
  230. package/src/prerequisite-verifier-translations.adapter.ts +4 -4
  231. package/src/reactive-config-file-json.adapter.ts +3 -9
  232. package/src/reactive-config-noop.adapter.ts +3 -9
  233. package/src/reactive-config-with-fallback.adapter.ts +3 -9
  234. package/src/reactive-config.port.ts +0 -2
  235. package/src/remote-file-storage-disk.adapter.ts +5 -1
  236. package/src/shield-api-key.strategy.ts +7 -1
  237. package/src/shield-basic-auth.strategy.ts +4 -2
  238. package/src/shield-recaptcha.strategy.ts +1 -1
  239. package/src/sitemap-entry.vo.ts +11 -4
  240. package/src/standard-schema-validator.service.ts +15 -0
  241. package/src/subject-application-resolver.vo.ts +2 -6
  242. package/src/subject-request-resolver.vo.ts +2 -6
  243. package/src/temporary-file-absolute.adapter.ts +6 -1
  244. package/src/timing.middleware.ts +1 -3
  245. package/src/woodchopper-sampling-every-nth.strategy.ts +1 -2
@@ -1,8 +1,5 @@
1
- import {
2
- ReactiveConfigError,
3
- type ReactiveConfigPort,
4
- type ReactiveConfigSchema,
5
- } from "./reactive-config.port";
1
+ import type { ReactiveConfigPort, ReactiveConfigSchema } from "./reactive-config.port";
2
+ import { StandardSchemaValidator } from "./standard-schema-validator.service";
6
3
 
7
4
  export class ReactiveConfigNoopAdapter<T extends object> implements ReactiveConfigPort<T> {
8
5
  constructor(
@@ -11,9 +8,6 @@ export class ReactiveConfigNoopAdapter<T extends object> implements ReactiveConf
11
8
  ) {}
12
9
 
13
10
  async get(): Promise<Readonly<T>> {
14
- const result = this.schema["~standard"].validate(this.value);
15
- if (result instanceof Promise) throw new Error(ReactiveConfigError.NoAsyncSchema);
16
- if (result.issues) throw new Error(result.issues[0]?.message);
17
- return Object.freeze(result.value);
11
+ return Object.freeze(StandardSchemaValidator.validate(this.schema, this.value));
18
12
  }
19
13
  }
@@ -1,8 +1,5 @@
1
- import {
2
- ReactiveConfigError,
3
- type ReactiveConfigPort,
4
- type ReactiveConfigSchema,
5
- } from "./reactive-config.port";
1
+ import type { ReactiveConfigPort, ReactiveConfigSchema } from "./reactive-config.port";
2
+ import { StandardSchemaValidator } from "./standard-schema-validator.service";
6
3
 
7
4
  export class ReactiveConfigWithFallbackAdapter<T extends object> implements ReactiveConfigPort<T> {
8
5
  constructor(
@@ -15,10 +12,7 @@ export class ReactiveConfigWithFallbackAdapter<T extends object> implements Reac
15
12
  try {
16
13
  return await this.inner.get();
17
14
  } catch {
18
- const result = this.schema["~standard"].validate(this.fallback);
19
- if (result instanceof Promise) throw new Error(ReactiveConfigError.NoAsyncSchema);
20
- if (result.issues) throw new Error(result.issues[0]?.message);
21
- return Object.freeze(result.value);
15
+ return Object.freeze(StandardSchemaValidator.validate(this.schema, this.fallback));
22
16
  }
23
17
  }
24
18
  }
@@ -1,7 +1,5 @@
1
1
  import type { StandardSchemaV1 } from "@standard-schema/spec";
2
2
 
3
- export const ReactiveConfigError = { NoAsyncSchema: "reactive.config.no.async.schema" };
4
-
5
3
  export type ReactiveConfigSchema<T extends object> = StandardSchemaV1<unknown, T>;
6
4
 
7
5
  export interface ReactiveConfigPort<T extends object> {
@@ -5,6 +5,7 @@ import type { FileCleanerPort } from "./file-cleaner.port";
5
5
  import type { FileCopierPort } from "./file-copier.port";
6
6
  import type { FileRenamerPort } from "./file-renamer.port";
7
7
  import type { HashFilePort } from "./hash-file.port";
8
+ import type { NonceProviderPort } from "./nonce-provider.port";
8
9
  import type {
9
10
  RemoteFileStoragePort,
10
11
  RemoteHeadResult,
@@ -18,6 +19,7 @@ type Dependencies = {
18
19
  FileRenamer: FileRenamerPort;
19
20
  FileCopier: FileCopierPort;
20
21
  DirectoryEnsurer: DirectoryEnsurerPort;
22
+ NonceProvider: NonceProviderPort;
21
23
  };
22
24
 
23
25
  type Config = { root: tools.DirectoryPathAbsoluteType };
@@ -39,7 +41,9 @@ export class RemoteFileStorageDiskAdapter implements RemoteFileStoragePort {
39
41
 
40
42
  async putFromPath(input: RemotePutFromPathInput): Promise<RemotePutFromPathResult> {
41
43
  const final = this.resolveKeyToAbsoluteFilePath(input.key);
42
- const temporary = final.withFilename(final.getFilename().withSuffix("-part"));
44
+ const temporary = final.withFilename(
45
+ final.getFilename().withSuffix(`-part-${this.deps.NonceProvider.generate()}`),
46
+ );
43
47
 
44
48
  await this.deps.DirectoryEnsurer.ensure(final.getDirectory());
45
49
  await this.deps.FileCopier.copy(input.path, temporary);
@@ -1,3 +1,4 @@
1
+ import { timingSafeEqual } from "node:crypto";
1
2
  import type * as tools from "@bgord/tools";
2
3
  import type { HasRequestHeader } from "./request-context.port";
3
4
 
@@ -11,6 +12,11 @@ export class ShieldApiKeyStrategy {
11
12
  constructor(private readonly config: ApiKeyShieldConfig) {}
12
13
 
13
14
  evaluate(context: HasRequestHeader): boolean {
14
- return context.request.header(ShieldApiKeyStrategy.HEADER_NAME) === this.config.API_KEY;
15
+ const header = context.request.header(ShieldApiKeyStrategy.HEADER_NAME);
16
+ const config = this.config.API_KEY;
17
+
18
+ if (header?.length !== config.length) return false;
19
+
20
+ return timingSafeEqual(Buffer.from(header), Buffer.from(config));
15
21
  }
16
22
  }
@@ -1,3 +1,4 @@
1
+ import { timingSafeEqual } from "node:crypto";
1
2
  import type { BasicAuthPasswordType } from "./basic-auth-password.vo";
2
3
  import type { BasicAuthUsernameType } from "./basic-auth-username.vo";
3
4
  import type { HasRequestHeader } from "./request-context.port";
@@ -18,9 +19,10 @@ export class ShieldBasicAuthStrategy {
18
19
  const [username, password] = credentials.split(":");
19
20
 
20
21
  if (username !== this.config.username) return false;
21
- if (password !== this.config.password) return false;
22
22
 
23
- return true;
23
+ if (password?.length !== this.config.password.length) return false;
24
+
25
+ return timingSafeEqual(Buffer.from(password), Buffer.from(this.config.password));
24
26
  } catch {
25
27
  return false;
26
28
  }
@@ -25,7 +25,7 @@ export class ShieldRecaptchaStrategy {
25
25
  try {
26
26
  const header = context.request.header("x-recaptcha-token");
27
27
  const query = context.request.query()["recaptchaToken"];
28
- const remoteip = context.request.header("x-forwarded-for") ?? "";
28
+ const remoteip = context.request.header("x-forwarded-for")?.split(",")[0] ?? "";
29
29
 
30
30
  const token = header ?? query ?? formToken;
31
31
 
@@ -1,3 +1,4 @@
1
+ // cspell:ignore apos
1
2
  import type * as tools from "@bgord/tools";
2
3
  import type { SitemapChangefreqEnum } from "./sitemap-changefreq.vo";
3
4
  import type { SitemapPriorityType } from "./sitemap-priority.vo";
@@ -13,16 +14,22 @@ export type SitemapEntryType = {
13
14
  export class SitemapEntry {
14
15
  constructor(private readonly entry: SitemapEntryType) {}
15
16
 
17
+ private escapeXml(str: string): string {
18
+ return str
19
+ .replace(/&/g, "&amp;")
20
+ .replace(/</g, "&lt;")
21
+ .replace(/>/g, "&gt;")
22
+ .replace(/"/g, "&quot;")
23
+ .replace(/'/g, "&apos;");
24
+ }
25
+
16
26
  toXml(): string {
27
+ const loc = `<loc>${this.escapeXml(this.entry.loc)}</loc>`;
17
28
  const lastmod = this.entry.lastmod ? `<lastmod>${this.entry.lastmod}</lastmod>` : "";
18
-
19
29
  const changefreq = this.entry.changefreq ? `<changefreq>${this.entry.changefreq}</changefreq>` : "";
20
-
21
30
  const priority =
22
31
  this.entry.priority !== undefined ? `<priority>${this.entry.priority.toFixed(1)}</priority>` : "";
23
32
 
24
- const loc = `<loc>${this.entry.loc}</loc>`;
25
-
26
33
  return ["<url>", loc, lastmod, changefreq, priority, "</url>"].join("");
27
34
  }
28
35
  }
@@ -0,0 +1,15 @@
1
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
2
+
3
+ const StandardSchemaValidatorError = {
4
+ NoAsyncSchema: "standard.schema.validate.error.no.async.schema",
5
+ };
6
+
7
+ export class StandardSchemaValidator {
8
+ static validate<Output>(schema: StandardSchemaV1<unknown, Output>, raw: unknown): Output {
9
+ const result = schema["~standard"].validate(raw);
10
+
11
+ if (result instanceof Promise) throw new Error(StandardSchemaValidatorError.NoAsyncSchema);
12
+ if (result.issues) throw new Error(result.issues[0]?.message);
13
+ return result.value;
14
+ }
15
+ }
@@ -11,8 +11,6 @@ export const SubjectApplicationResolverError = {
11
11
  };
12
12
 
13
13
  export class SubjectApplicationResolver {
14
- private readonly SEPARATOR = "|";
15
-
16
14
  constructor(
17
15
  private readonly segments: ReadonlyArray<SubjectSegmentApplicationStrategy>,
18
16
  private readonly deps: Dependencies,
@@ -22,10 +20,8 @@ export class SubjectApplicationResolver {
22
20
  }
23
21
 
24
22
  async resolve(): Promise<{ hex: Hash; raw: ReadonlyArray<SubjectSegmentType> }> {
25
- const segments = this.segments.map((segment) =>
26
- segment.create().replaceAll(this.SEPARATOR, encodeURIComponent(this.SEPARATOR)),
27
- );
28
- const subject = segments.join(this.SEPARATOR);
23
+ const segments = this.segments.map((segment) => segment.create());
24
+ const subject = JSON.stringify(segments);
29
25
 
30
26
  const hex = await this.deps.HashContent.hash(subject);
31
27
 
@@ -11,8 +11,6 @@ export const SubjectRequestResolverError = {
11
11
  };
12
12
 
13
13
  export class SubjectRequestResolver {
14
- private readonly SEPARATOR = "|";
15
-
16
14
  constructor(
17
15
  private readonly segments: ReadonlyArray<SubjectSegmentRequestStrategy>,
18
16
  private readonly deps: Dependencies,
@@ -22,10 +20,8 @@ export class SubjectRequestResolver {
22
20
  }
23
21
 
24
22
  async resolve(context: RequestContext): Promise<{ hex: Hash; raw: ReadonlyArray<SubjectSegmentType> }> {
25
- const segments = this.segments.map((segment) =>
26
- segment.create(context).replaceAll(this.SEPARATOR, encodeURIComponent(this.SEPARATOR)),
27
- );
28
- const subject = segments.join(this.SEPARATOR);
23
+ const segments = this.segments.map((segment) => segment.create(context));
24
+ const subject = JSON.stringify(segments);
29
25
 
30
26
  const hex = await this.deps.HashContent.hash(subject);
31
27
 
@@ -2,12 +2,14 @@ import * as tools from "@bgord/tools";
2
2
  import type { FileCleanerPort } from "./file-cleaner.port";
3
3
  import type { FileRenamerPort } from "./file-renamer.port";
4
4
  import type { FileWriterPort } from "./file-writer.port";
5
+ import type { NonceProviderPort } from "./nonce-provider.port";
5
6
  import type { TemporaryFilePort } from "./temporary-file.port";
6
7
 
7
8
  type Dependencies = {
8
9
  FileCleaner: FileCleanerPort;
9
10
  FileRenamer: FileRenamerPort;
10
11
  FileWriter: FileWriterPort;
12
+ NonceProvider: NonceProviderPort;
11
13
  };
12
14
 
13
15
  export class TemporaryFileAbsoluteAdapter implements TemporaryFilePort {
@@ -17,7 +19,10 @@ export class TemporaryFileAbsoluteAdapter implements TemporaryFilePort {
17
19
  ) {}
18
20
 
19
21
  async write(filename: tools.Filename, content: File): Promise<tools.FilePathAbsolute> {
20
- const temporary = tools.FilePathAbsolute.fromPartsSafe(this.directory, filename.withSuffix("-part"));
22
+ const temporary = tools.FilePathAbsolute.fromPartsSafe(
23
+ this.directory,
24
+ filename.withSuffix(`-part-${this.deps.NonceProvider.generate()}`),
25
+ );
21
26
  const final = tools.FilePathAbsolute.fromPartsSafe(this.directory, filename);
22
27
 
23
28
  await this.deps.FileWriter.write(temporary.get(), content);
@@ -10,9 +10,7 @@ export class TimingMiddleware {
10
10
  constructor(private readonly deps: Dependencies) {}
11
11
 
12
12
  async measure(context: RequestContext, action: () => void | Promise<void>): Promise<string | null> {
13
- const header = context.request.header("accept");
14
-
15
- if (header === "text/event-stream") return null;
13
+ if (context.request.header("accept")?.toLowerCase().startsWith("text/event-stream")) return null;
16
14
 
17
15
  const stopwatch = new Stopwatch(this.deps);
18
16
 
@@ -14,7 +14,6 @@ export class WoodchopperSamplingEveryNth implements WoodchopperSamplingStrategy
14
14
  this.counter++;
15
15
  // Stryker restore all
16
16
 
17
- if (this.counter % this.config.n !== 0) return false;
18
- return true;
17
+ return this.counter % this.config.n === 0;
19
18
  }
20
19
  }