@bgord/bun 0.30.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/antivirus-clamav.adapter.d.ts.map +1 -1
- package/dist/antivirus-clamav.adapter.js +6 -6
- package/dist/antivirus-clamav.adapter.js.map +1 -1
- package/dist/antivirus.port.d.ts +3 -6
- package/dist/antivirus.port.d.ts.map +1 -1
- package/dist/antivirus.port.js +1 -12
- package/dist/antivirus.port.js.map +1 -1
- package/dist/api-version.middleware.d.ts +4 -2
- package/dist/api-version.middleware.d.ts.map +1 -1
- package/dist/api-version.middleware.js.map +1 -1
- package/dist/basic-auth-password.vo.d.ts +9 -0
- package/dist/basic-auth-password.vo.d.ts.map +1 -0
- package/dist/basic-auth-password.vo.js +12 -0
- package/dist/basic-auth-password.vo.js.map +1 -0
- package/dist/basic-auth-username.vo.d.ts +9 -0
- package/dist/basic-auth-username.vo.d.ts.map +1 -0
- package/dist/basic-auth-username.vo.js +12 -0
- package/dist/basic-auth-username.vo.js.map +1 -0
- package/dist/basic-auth.service.d.ts +5 -22
- package/dist/basic-auth.service.d.ts.map +1 -1
- package/dist/basic-auth.service.js +0 -15
- package/dist/basic-auth.service.js.map +1 -1
- package/dist/better-auth-logger.service.d.ts.map +1 -1
- package/dist/better-auth-logger.service.js +4 -2
- package/dist/better-auth-logger.service.js.map +1 -1
- package/dist/binary.vo.d.ts +10 -0
- package/dist/binary.vo.d.ts.map +1 -0
- package/dist/binary.vo.js +16 -0
- package/dist/binary.vo.js.map +1 -0
- package/dist/build-info-repository.service.d.ts +2 -1
- package/dist/build-info-repository.service.d.ts.map +1 -1
- package/dist/build-info-repository.service.js +2 -5
- package/dist/build-info-repository.service.js.map +1 -1
- package/dist/cache-file.service.d.ts.map +1 -1
- package/dist/cache-file.service.js +1 -1
- package/dist/cache-file.service.js.map +1 -1
- package/dist/cache-response.middleware.d.ts.map +1 -1
- package/dist/cache-response.middleware.js.map +1 -1
- package/dist/certificate-inspector-tls.adapter.d.ts +1 -1
- package/dist/certificate-inspector-tls.adapter.d.ts.map +1 -1
- package/dist/certificate-inspector-tls.adapter.js +2 -2
- package/dist/certificate-inspector-tls.adapter.js.map +1 -1
- package/dist/client-from-hono.adapter.d.ts +1 -1
- package/dist/client-from-hono.adapter.d.ts.map +1 -1
- package/dist/client-from-hono.adapter.js +1 -1
- package/dist/client-from-hono.adapter.js.map +1 -1
- package/dist/clock-system.adapter.d.ts.map +1 -1
- package/dist/clock-system.adapter.js +1 -2
- package/dist/clock-system.adapter.js.map +1 -1
- package/dist/clock.port.d.ts.map +1 -1
- package/dist/context.middleware.d.ts.map +1 -1
- package/dist/context.middleware.js.map +1 -1
- package/dist/correlation-id.vo.d.ts.map +1 -1
- package/dist/correlation-storage.service.d.ts +3 -0
- package/dist/correlation-storage.service.d.ts.map +1 -1
- package/dist/correlation-storage.service.js +2 -1
- package/dist/correlation-storage.service.js.map +1 -1
- package/dist/env-validator.service.d.ts +3 -1
- package/dist/env-validator.service.d.ts.map +1 -1
- package/dist/env-validator.service.js +2 -2
- package/dist/env-validator.service.js.map +1 -1
- package/dist/etag-extractor.middleware.js +2 -2
- package/dist/etag-extractor.middleware.js.map +1 -1
- package/dist/event-store-like.types.d.ts.map +1 -1
- package/dist/event-stream.vo.d.ts +4 -2
- package/dist/event-stream.vo.d.ts.map +1 -1
- package/dist/event-stream.vo.js +8 -4
- package/dist/event-stream.vo.js.map +1 -1
- package/dist/file-cleaner-bun-forgiving.adapter.d.ts +6 -0
- package/dist/file-cleaner-bun-forgiving.adapter.d.ts.map +1 -0
- package/dist/file-cleaner-bun-forgiving.adapter.js +9 -0
- package/dist/file-cleaner-bun-forgiving.adapter.js.map +1 -0
- package/dist/file-cleaner-bun.adapter.d.ts +6 -0
- package/dist/file-cleaner-bun.adapter.d.ts.map +1 -0
- package/dist/file-cleaner-bun.adapter.js +6 -0
- package/dist/file-cleaner-bun.adapter.js.map +1 -0
- package/dist/file-cleaner-noop.adapter.d.ts +6 -0
- package/dist/file-cleaner-noop.adapter.d.ts.map +1 -0
- package/dist/file-cleaner-noop.adapter.js +4 -0
- package/dist/file-cleaner-noop.adapter.js.map +1 -0
- package/dist/file-cleaner.port.d.ts +5 -0
- package/dist/file-cleaner.port.d.ts.map +1 -0
- package/dist/file-cleaner.port.js +2 -0
- package/dist/file-cleaner.port.js.map +1 -0
- package/dist/file-draft.service.js +2 -2
- package/dist/file-draft.service.js.map +1 -1
- package/dist/file-renamer-fs-forgiving.adapter.d.ts +6 -0
- package/dist/file-renamer-fs-forgiving.adapter.d.ts.map +1 -0
- package/dist/file-renamer-fs-forgiving.adapter.js +12 -0
- package/dist/file-renamer-fs-forgiving.adapter.js.map +1 -0
- package/dist/file-renamer-fs.adapter.d.ts +6 -0
- package/dist/file-renamer-fs.adapter.d.ts.map +1 -0
- package/dist/file-renamer-fs.adapter.js +9 -0
- package/dist/file-renamer-fs.adapter.js.map +1 -0
- package/dist/file-renamer-noop.adapter.d.ts +6 -0
- package/dist/file-renamer-noop.adapter.d.ts.map +1 -0
- package/dist/file-renamer-noop.adapter.js +4 -0
- package/dist/file-renamer-noop.adapter.js.map +1 -0
- package/dist/file-renamer.port.d.ts +5 -0
- package/dist/file-renamer.port.d.ts.map +1 -0
- package/dist/file-renamer.port.js +2 -0
- package/dist/file-renamer.port.js.map +1 -0
- package/dist/graceful-shutdown.service.d.ts.map +1 -1
- package/dist/graceful-shutdown.service.js +1 -3
- package/dist/graceful-shutdown.service.js.map +1 -1
- package/dist/hcaptcha-secret-key.vo.d.ts +8 -0
- package/dist/hcaptcha-secret-key.vo.d.ts.map +1 -0
- package/dist/hcaptcha-secret-key.vo.js +10 -0
- package/dist/hcaptcha-secret-key.vo.js.map +1 -0
- package/dist/hcaptcha-site-key.vo.d.ts +8 -0
- package/dist/hcaptcha-site-key.vo.d.ts.map +1 -0
- package/dist/hcaptcha-site-key.vo.js +10 -0
- package/dist/hcaptcha-site-key.vo.js.map +1 -0
- package/dist/healthcheck.service.d.ts +4 -0
- package/dist/healthcheck.service.d.ts.map +1 -1
- package/dist/healthcheck.service.js +3 -3
- package/dist/healthcheck.service.js.map +1 -1
- package/dist/http-logger.middleware.d.ts.map +1 -1
- package/dist/http-logger.middleware.js +9 -9
- package/dist/http-logger.middleware.js.map +1 -1
- package/dist/i18n.service.d.ts +10 -3
- package/dist/i18n.service.d.ts.map +1 -1
- package/dist/i18n.service.js +7 -11
- package/dist/i18n.service.js.map +1 -1
- package/dist/id-provider-deterministic.adapter.d.ts +3 -0
- package/dist/id-provider-deterministic.adapter.d.ts.map +1 -1
- package/dist/id-provider-deterministic.adapter.js +4 -1
- package/dist/id-provider-deterministic.adapter.js.map +1 -1
- package/dist/image-alpha-noop.adapter.d.ts +1 -1
- package/dist/image-alpha-sharp.adapter.d.ts +8 -1
- package/dist/image-alpha-sharp.adapter.d.ts.map +1 -1
- package/dist/image-alpha-sharp.adapter.js +6 -3
- package/dist/image-alpha-sharp.adapter.js.map +1 -1
- package/dist/image-blur-noop.adapter.d.ts +1 -1
- package/dist/image-blur-sharp.adapter.d.ts +8 -1
- package/dist/image-blur-sharp.adapter.d.ts.map +1 -1
- package/dist/image-blur-sharp.adapter.js +6 -3
- package/dist/image-blur-sharp.adapter.js.map +1 -1
- package/dist/image-compressor-noop.adapter.d.ts +1 -1
- package/dist/image-compressor-sharp.adapter.d.ts +8 -1
- package/dist/image-compressor-sharp.adapter.d.ts.map +1 -1
- package/dist/image-compressor-sharp.adapter.js +5 -2
- package/dist/image-compressor-sharp.adapter.js.map +1 -1
- package/dist/image-exif-clear-noop.adapter.d.ts +1 -1
- package/dist/image-exif-clear-sharp.adapter.d.ts +8 -1
- package/dist/image-exif-clear-sharp.adapter.d.ts.map +1 -1
- package/dist/image-exif-clear-sharp.adapter.js +5 -2
- package/dist/image-exif-clear-sharp.adapter.js.map +1 -1
- package/dist/image-formatter-sharp.adapter.d.ts +10 -1
- package/dist/image-formatter-sharp.adapter.d.ts.map +1 -1
- package/dist/image-formatter-sharp.adapter.js +8 -5
- package/dist/image-formatter-sharp.adapter.js.map +1 -1
- package/dist/image-info-noop.adapter.d.ts +2 -2
- package/dist/image-info-sharp.adapter.d.ts +2 -2
- package/dist/image-info-sharp.adapter.d.ts.map +1 -1
- package/dist/image-info-sharp.adapter.js +5 -9
- package/dist/image-info-sharp.adapter.js.map +1 -1
- package/dist/image-processor-sharp.adapter.d.ts +9 -0
- package/dist/image-processor-sharp.adapter.d.ts.map +1 -1
- package/dist/image-processor-sharp.adapter.js +8 -5
- package/dist/image-processor-sharp.adapter.js.map +1 -1
- package/dist/image-resizer-noop.adapter.d.ts +1 -1
- package/dist/image-resizer-sharp.adapter.d.ts +8 -1
- package/dist/image-resizer-sharp.adapter.d.ts.map +1 -1
- package/dist/image-resizer-sharp.adapter.js +5 -2
- package/dist/image-resizer-sharp.adapter.js.map +1 -1
- package/dist/index.d.ts +25 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -5
- package/dist/index.js.map +1 -1
- package/dist/json-file-reader-bun-forgiving.adapter.d.ts +6 -0
- package/dist/json-file-reader-bun-forgiving.adapter.d.ts.map +1 -0
- package/dist/json-file-reader-bun-forgiving.adapter.js +11 -0
- package/dist/json-file-reader-bun-forgiving.adapter.js.map +1 -0
- package/dist/json-file-reader-bun.adapter.d.ts +6 -0
- package/dist/json-file-reader-bun.adapter.d.ts.map +1 -0
- package/dist/json-file-reader-bun.adapter.js +6 -0
- package/dist/json-file-reader-bun.adapter.js.map +1 -0
- package/dist/json-file-reader-noop.adapter.d.ts +8 -0
- package/dist/json-file-reader-noop.adapter.d.ts.map +1 -0
- package/dist/json-file-reader-noop.adapter.js +10 -0
- package/dist/json-file-reader-noop.adapter.js.map +1 -0
- package/dist/json-file-reader.port.d.ts +5 -0
- package/dist/json-file-reader.port.d.ts.map +1 -0
- package/dist/json-file-reader.port.js +2 -0
- package/dist/json-file-reader.port.js.map +1 -0
- package/dist/logger-format-error.service.d.ts +1 -1
- package/dist/logger-format-error.service.d.ts.map +1 -1
- package/dist/logger-format-error.service.js +9 -9
- package/dist/logger-format-error.service.js.map +1 -1
- package/dist/logger.port.d.ts +0 -4
- package/dist/logger.port.d.ts.map +1 -1
- package/dist/mailer-smtp-with-logger.adapter.d.ts.map +1 -1
- package/dist/mailer-smtp-with-logger.adapter.js.map +1 -1
- package/dist/mailer-smtp.adapter.d.ts +2 -23
- package/dist/mailer-smtp.adapter.d.ts.map +1 -1
- package/dist/mailer-smtp.adapter.js +0 -10
- package/dist/mailer-smtp.adapter.js.map +1 -1
- package/dist/mailer.vo.d.ts +34 -0
- package/dist/mailer.vo.d.ts.map +1 -0
- package/dist/mailer.vo.js +21 -0
- package/dist/mailer.vo.js.map +1 -0
- package/dist/modules/history/event-handlers/onHistoryPopulatedEvent.d.ts.map +1 -1
- package/dist/modules/history/event-handlers/onHistoryPopulatedEvent.js.map +1 -1
- package/dist/modules/history/events/HISTORY_CLEARED_EVENT.d.ts +4 -4
- package/dist/modules/history/events/HISTORY_CLEARED_EVENT.d.ts.map +1 -1
- package/dist/modules/history/events/HISTORY_CLEARED_EVENT.js +2 -8
- package/dist/modules/history/events/HISTORY_CLEARED_EVENT.js.map +1 -1
- package/dist/modules/history/events/HISTORY_POPULATED_EVENT.d.ts +6 -6
- package/dist/modules/history/events/HISTORY_POPULATED_EVENT.d.ts.map +1 -1
- package/dist/modules/history/events/HISTORY_POPULATED_EVENT.js +2 -8
- package/dist/modules/history/events/HISTORY_POPULATED_EVENT.js.map +1 -1
- package/dist/modules/history/ports/history-writer.d.ts.map +1 -1
- package/dist/modules/history/value-objects/history-subject.d.ts.map +1 -1
- package/dist/modules/preferences/open-host-queries/user-language.d.ts.map +1 -1
- package/dist/modules/preferences/open-host-queries/user-language.js.map +1 -1
- package/dist/modules/preferences/ports/user-language-resolver.d.ts +3 -3
- package/dist/modules/preferences/ports/user-language-resolver.d.ts.map +1 -1
- package/dist/modules/preferences/ports/user-language-resolver.js +2 -7
- package/dist/modules/preferences/ports/user-language-resolver.js.map +1 -1
- package/dist/modules/preferences/value-objects/supported-languages-set.d.ts +3 -3
- package/dist/modules/preferences/value-objects/supported-languages-set.d.ts.map +1 -1
- package/dist/modules/preferences/value-objects/supported-languages-set.js +2 -7
- package/dist/modules/preferences/value-objects/supported-languages-set.js.map +1 -1
- package/dist/pdf-generator-noop.adapter.d.ts +1 -1
- package/dist/pdf-generator-noop.adapter.d.ts.map +1 -1
- package/dist/pdf-generator-noop.adapter.js +1 -1
- package/dist/pdf-generator-noop.adapter.js.map +1 -1
- package/dist/port.vo.d.ts +4 -0
- package/dist/port.vo.d.ts.map +1 -1
- package/dist/port.vo.js +7 -1
- package/dist/port.vo.js.map +1 -1
- package/dist/prerequisites/binary.d.ts +2 -5
- package/dist/prerequisites/binary.d.ts.map +1 -1
- package/dist/prerequisites/binary.js +1 -8
- package/dist/prerequisites/binary.js.map +1 -1
- package/dist/prerequisites/dependency-vulnerabilities.js +3 -3
- package/dist/prerequisites/dependency-vulnerabilities.js.map +1 -1
- package/dist/prerequisites/directory.d.ts.map +1 -1
- package/dist/prerequisites/directory.js.map +1 -1
- package/dist/prerequisites/jobs.d.ts.map +1 -1
- package/dist/prerequisites/jobs.js +1 -2
- package/dist/prerequisites/jobs.js.map +1 -1
- package/dist/prerequisites/log-file.d.ts.map +1 -1
- package/dist/prerequisites/log-file.js.map +1 -1
- package/dist/prerequisites/mailer.d.ts.map +1 -1
- package/dist/prerequisites/mailer.js.map +1 -1
- package/dist/prerequisites/memory.js +1 -1
- package/dist/prerequisites/memory.js.map +1 -1
- package/dist/prerequisites/node.d.ts.map +1 -1
- package/dist/prerequisites/node.js.map +1 -1
- package/dist/prerequisites/port.d.ts.map +1 -1
- package/dist/prerequisites/port.js.map +1 -1
- package/dist/prerequisites/ram.d.ts.map +1 -1
- package/dist/prerequisites/ram.js +1 -1
- package/dist/prerequisites/ram.js.map +1 -1
- package/dist/prerequisites/running-user.d.ts.map +1 -1
- package/dist/prerequisites/running-user.js.map +1 -1
- package/dist/prerequisites/space.d.ts.map +1 -1
- package/dist/prerequisites/space.js +1 -1
- package/dist/prerequisites/space.js.map +1 -1
- package/dist/prerequisites/sqlite.d.ts.map +1 -1
- package/dist/prerequisites/sqlite.js +1 -1
- package/dist/prerequisites/sqlite.js.map +1 -1
- package/dist/prerequisites/ssl-certificate-expiry.js +1 -1
- package/dist/prerequisites/ssl-certificate-expiry.js.map +1 -1
- package/dist/prerequisites/timezone-utc.d.ts.map +1 -1
- package/dist/prerequisites/timezone-utc.js.map +1 -1
- package/dist/prerequisites/translations.d.ts +10 -3
- package/dist/prerequisites/translations.d.ts.map +1 -1
- package/dist/prerequisites/translations.js +15 -10
- package/dist/prerequisites/translations.js.map +1 -1
- package/dist/prerequisites.service.d.ts +3 -0
- package/dist/prerequisites.service.d.ts.map +1 -1
- package/dist/prerequisites.service.js +3 -3
- package/dist/prerequisites.service.js.map +1 -1
- package/dist/rate-limit-store-node-cache.adapter.d.ts +2 -2
- package/dist/rate-limit-store-node-cache.adapter.d.ts.map +1 -1
- package/dist/rate-limit-store-node-cache.adapter.js +1 -1
- package/dist/rate-limit-store-node-cache.adapter.js.map +1 -1
- package/dist/rate-limit-store.port.d.ts +1 -1
- package/dist/rate-limit-store.port.d.ts.map +1 -1
- package/dist/recaptcha-secret-key.vo.d.ts +8 -0
- package/dist/recaptcha-secret-key.vo.d.ts.map +1 -0
- package/dist/recaptcha-secret-key.vo.js +10 -0
- package/dist/recaptcha-secret-key.vo.js.map +1 -0
- package/dist/recaptcha-site-key.vo.d.ts +8 -0
- package/dist/recaptcha-site-key.vo.d.ts.map +1 -0
- package/dist/recaptcha-site-key.vo.js +10 -0
- package/dist/recaptcha-site-key.vo.js.map +1 -0
- package/dist/redactor-encrypt.adapter.js +2 -2
- package/dist/redactor-encrypt.adapter.js.map +1 -1
- package/dist/redactor-mask.adapter.d.ts.map +1 -1
- package/dist/redactor-mask.adapter.js +0 -3
- package/dist/redactor-mask.adapter.js.map +1 -1
- package/dist/remote-file-storage-disk.adapter.d.ts +9 -2
- package/dist/remote-file-storage-disk.adapter.d.ts.map +1 -1
- package/dist/remote-file-storage-disk.adapter.js +7 -9
- package/dist/remote-file-storage-disk.adapter.js.map +1 -1
- package/dist/safe-parse-body.service.d.ts.map +1 -1
- package/dist/safe-parse-body.service.js +1 -1
- package/dist/safe-parse-body.service.js.map +1 -1
- package/dist/setup.service.d.ts +3 -1
- package/dist/setup.service.d.ts.map +1 -1
- package/dist/setup.service.js +1 -1
- package/dist/setup.service.js.map +1 -1
- package/dist/shield-api-key.middleware.d.ts.map +1 -1
- package/dist/shield-api-key.middleware.js +1 -2
- package/dist/shield-api-key.middleware.js.map +1 -1
- package/dist/shield-auth.middleware.d.ts.map +1 -1
- package/dist/shield-auth.middleware.js +1 -3
- package/dist/shield-auth.middleware.js.map +1 -1
- package/dist/shield-captcha-hcaptcha-local.adapter.d.ts +2 -2
- package/dist/shield-captcha-hcaptcha-local.adapter.d.ts.map +1 -1
- package/dist/shield-captcha-hcaptcha-local.adapter.js +2 -2
- package/dist/shield-captcha-hcaptcha-local.adapter.js.map +1 -1
- package/dist/shield-captcha-hcaptcha.adapter.d.ts +2 -8
- package/dist/shield-captcha-hcaptcha.adapter.d.ts.map +1 -1
- package/dist/shield-captcha-hcaptcha.adapter.js +2 -6
- package/dist/shield-captcha-hcaptcha.adapter.js.map +1 -1
- package/dist/shield-captcha-noop.adapter.d.ts +1 -1
- package/dist/shield-captcha-noop.adapter.d.ts.map +1 -1
- package/dist/shield-captcha-noop.adapter.js +1 -1
- package/dist/shield-captcha-noop.adapter.js.map +1 -1
- package/dist/shield-captcha-recaptcha.adapter.d.ts +3 -7
- package/dist/shield-captcha-recaptcha.adapter.d.ts.map +1 -1
- package/dist/shield-captcha-recaptcha.adapter.js +12 -17
- package/dist/shield-captcha-recaptcha.adapter.js.map +1 -1
- package/dist/shield-rate-limit.middleware.d.ts +2 -2
- package/dist/shield-rate-limit.middleware.d.ts.map +1 -1
- package/dist/slower.middleware.d.ts.map +1 -1
- package/dist/slower.middleware.js.map +1 -1
- package/dist/temporary-file-absolute.adapter.d.ts +11 -3
- package/dist/temporary-file-absolute.adapter.d.ts.map +1 -1
- package/dist/temporary-file-absolute.adapter.js +11 -14
- package/dist/temporary-file-absolute.adapter.js.map +1 -1
- package/dist/temporary-file-noop.adapter.d.ts +1 -1
- package/dist/temporary-file-noop.adapter.d.ts.map +1 -1
- package/dist/temporary-file-noop.adapter.js +1 -1
- package/dist/temporary-file-noop.adapter.js.map +1 -1
- package/dist/temporary-file.port.d.ts +1 -1
- package/dist/temporary-file.port.d.ts.map +1 -1
- package/dist/time-zone-offset.middleware.d.ts.map +1 -1
- package/dist/time-zone-offset.middleware.js +2 -2
- package/dist/time-zone-offset.middleware.js.map +1 -1
- package/dist/translations.service.d.ts +8 -1
- package/dist/translations.service.d.ts.map +1 -1
- package/dist/translations.service.js +2 -2
- package/dist/translations.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/uptime.service.js +3 -3
- package/dist/uptime.service.js.map +1 -1
- package/dist/uuid.vo.d.ts +3 -0
- package/dist/uuid.vo.d.ts.map +1 -1
- package/dist/uuid.vo.js +2 -1
- package/dist/uuid.vo.js.map +1 -1
- package/dist/visitor-id-hash-hono.adapter.d.ts +1 -1
- package/dist/visitor-id-hash-hono.adapter.d.ts.map +1 -1
- package/dist/visitor-id-hash-hono.adapter.js +4 -4
- package/dist/visitor-id-hash-hono.adapter.js.map +1 -1
- package/dist/visitor-id-hash.adapter.d.ts +1 -1
- package/dist/visitor-id-hash.adapter.d.ts.map +1 -1
- package/dist/visitor-id-hash.adapter.js +3 -3
- package/dist/visitor-id-hash.adapter.js.map +1 -1
- package/dist/weak-etag-extractor.middleware.js +2 -2
- package/dist/weak-etag-extractor.middleware.js.map +1 -1
- package/package.json +7 -7
- package/readme.md +20 -5
- package/src/antivirus-clamav.adapter.ts +7 -12
- package/src/antivirus.port.ts +1 -13
- package/src/api-version.middleware.ts +4 -4
- package/src/basic-auth-password.vo.ts +15 -0
- package/src/basic-auth-username.vo.ts +15 -0
- package/src/basic-auth.service.ts +3 -22
- package/src/better-auth-logger.service.ts +4 -3
- package/src/binary.vo.ts +20 -0
- package/src/build-info-repository.service.ts +5 -7
- package/src/cache-file.service.ts +2 -1
- package/src/cache-response.middleware.ts +3 -0
- package/src/certificate-inspector-tls.adapter.ts +3 -2
- package/src/client-from-hono.adapter.ts +1 -1
- package/src/clock-system.adapter.ts +2 -2
- package/src/clock.port.ts +1 -0
- package/src/context.middleware.ts +1 -0
- package/src/correlation-id.vo.ts +1 -0
- package/src/correlation-storage.service.ts +4 -1
- package/src/env-validator.service.ts +2 -2
- package/src/etag-extractor.middleware.ts +2 -2
- package/src/event-store-like.types.ts +1 -0
- package/src/event-stream.vo.ts +9 -4
- package/src/file-cleaner-bun-forgiving.adapter.ts +10 -0
- package/src/file-cleaner-bun.adapter.ts +8 -0
- package/src/file-cleaner-noop.adapter.ts +6 -0
- package/src/file-cleaner.port.ts +5 -0
- package/src/file-draft.service.ts +2 -2
- package/src/file-renamer-fs-forgiving.adapter.ts +17 -0
- package/src/file-renamer-fs.adapter.ts +15 -0
- package/src/file-renamer-noop.adapter.ts +9 -0
- package/src/file-renamer.port.ts +8 -0
- package/src/graceful-shutdown.service.ts +1 -3
- package/src/hcaptcha-secret-key.vo.ts +13 -0
- package/src/hcaptcha-site-key.vo.ts +13 -0
- package/src/healthcheck.service.ts +6 -4
- package/src/http-logger.middleware.ts +9 -10
- package/src/i18n.service.ts +14 -11
- package/src/id-provider-deterministic.adapter.ts +5 -1
- package/src/image-alpha-sharp.adapter.ts +7 -4
- package/src/image-blur-sharp.adapter.ts +7 -4
- package/src/image-compressor-sharp.adapter.ts +6 -2
- package/src/image-exif-clear-sharp.adapter.ts +6 -2
- package/src/image-formatter-sharp.adapter.ts +10 -5
- package/src/image-info-sharp.adapter.ts +5 -11
- package/src/image-processor-sharp.adapter.ts +10 -5
- package/src/image-resizer-sharp.adapter.ts +6 -3
- package/src/index.ts +25 -5
- package/src/json-file-reader-bun-forgiving.adapter.ts +12 -0
- package/src/json-file-reader-bun.adapter.ts +8 -0
- package/src/json-file-reader-noop.adapter.ts +10 -0
- package/src/json-file-reader.port.ts +5 -0
- package/src/logger-format-error.service.ts +10 -9
- package/src/logger.port.ts +0 -4
- package/src/mailer-smtp-with-logger.adapter.ts +2 -0
- package/src/mailer-smtp.adapter.ts +2 -31
- package/src/mailer.vo.ts +38 -0
- package/src/modules/history/event-handlers/onHistoryPopulatedEvent.ts +1 -0
- package/src/modules/history/events/HISTORY_CLEARED_EVENT.ts +2 -8
- package/src/modules/history/events/HISTORY_POPULATED_EVENT.ts +2 -8
- package/src/modules/history/ports/history-writer.ts +1 -0
- package/src/modules/history/value-objects/history-subject.ts +1 -0
- package/src/modules/preferences/open-host-queries/user-language.ts +1 -0
- package/src/modules/preferences/ports/user-language-resolver.ts +2 -7
- package/src/modules/preferences/value-objects/supported-languages-set.ts +2 -8
- package/src/pdf-generator-noop.adapter.ts +1 -1
- package/src/port.vo.ts +9 -1
- package/src/prerequisites/binary.ts +4 -14
- package/src/prerequisites/dependency-vulnerabilities.ts +3 -3
- package/src/prerequisites/directory.ts +1 -0
- package/src/prerequisites/jobs.ts +2 -4
- package/src/prerequisites/log-file.ts +1 -0
- package/src/prerequisites/mailer.ts +1 -0
- package/src/prerequisites/memory.ts +1 -1
- package/src/prerequisites/node.ts +1 -0
- package/src/prerequisites/port.ts +1 -0
- package/src/prerequisites/ram.ts +2 -1
- package/src/prerequisites/running-user.ts +1 -0
- package/src/prerequisites/space.ts +2 -1
- package/src/prerequisites/sqlite.ts +1 -2
- package/src/prerequisites/ssl-certificate-expiry.ts +1 -1
- package/src/prerequisites/timezone-utc.ts +1 -0
- package/src/prerequisites/translations.ts +29 -17
- package/src/prerequisites.service.ts +4 -4
- package/src/rate-limit-store-node-cache.adapter.ts +2 -2
- package/src/rate-limit-store.port.ts +1 -1
- package/src/recaptcha-secret-key.vo.ts +13 -0
- package/src/recaptcha-site-key.vo.ts +13 -0
- package/src/redactor-encrypt.adapter.ts +2 -2
- package/src/redactor-mask.adapter.ts +0 -3
- package/src/remote-file-storage-disk.adapter.ts +13 -14
- package/src/safe-parse-body.service.ts +2 -1
- package/src/setup.service.ts +3 -1
- package/src/shield-api-key.middleware.ts +1 -3
- package/src/shield-auth.middleware.ts +5 -3
- package/src/shield-captcha-hcaptcha-local.adapter.ts +4 -3
- package/src/shield-captcha-hcaptcha.adapter.ts +5 -13
- package/src/shield-captcha-noop.adapter.ts +1 -1
- package/src/shield-captcha-recaptcha.adapter.ts +15 -25
- package/src/shield-rate-limit.middleware.ts +2 -2
- package/src/slower.middleware.ts +1 -0
- package/src/temporary-file-absolute.adapter.ts +16 -14
- package/src/temporary-file-noop.adapter.ts +1 -1
- package/src/temporary-file.port.ts +2 -1
- package/src/time-zone-offset.middleware.ts +2 -5
- package/src/translations.service.ts +7 -4
- package/src/uptime.service.ts +3 -3
- package/src/uuid.vo.ts +4 -1
- package/src/visitor-id-hash-hono.adapter.ts +5 -5
- package/src/visitor-id-hash.adapter.ts +3 -3
- package/src/weak-etag-extractor.middleware.ts +2 -2
- package/dist/encryption.service.d.ts +0 -25
- package/dist/encryption.service.d.ts.map +0 -1
- package/dist/encryption.service.js +0 -35
- package/dist/encryption.service.js.map +0 -1
- package/dist/gzip.service.d.ts +0 -13
- package/dist/gzip.service.d.ts.map +0 -1
- package/dist/gzip.service.js +0 -18
- package/dist/gzip.service.js.map +0 -1
- package/dist/open-graph.service.d.ts +0 -104
- package/dist/open-graph.service.d.ts.map +0 -1
- package/dist/open-graph.service.js +0 -159
- package/dist/open-graph.service.js.map +0 -1
- package/dist/sitemap.service.d.ts +0 -28
- package/dist/sitemap.service.d.ts.map +0 -1
- package/dist/sitemap.service.js +0 -57
- package/dist/sitemap.service.js.map +0 -1
- package/dist/url-wo-trailing-slash.vo.d.ts +0 -4
- package/dist/url-wo-trailing-slash.vo.d.ts.map +0 -1
- package/dist/url-wo-trailing-slash.vo.js +0 -8
- package/dist/url-wo-trailing-slash.vo.js.map +0 -1
- package/src/encryption.service.ts +0 -45
- package/src/gzip.service.ts +0 -23
- package/src/open-graph.service.ts +0 -242
- package/src/sitemap.service.ts +0 -91
- package/src/url-wo-trailing-slash.vo.ts +0 -9
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
2
|
import fsp from "node:fs/promises";
|
|
3
3
|
import type * as tools from "@bgord/tools";
|
|
4
|
-
import * as
|
|
4
|
+
import type * as types from "../i18n.service";
|
|
5
|
+
import { I18n } from "../i18n.service";
|
|
6
|
+
import type { JsonFileReaderPort } from "../json-file-reader.port";
|
|
7
|
+
import type { LoggerPort } from "../logger.port";
|
|
5
8
|
import * as prereqs from "../prerequisites.service";
|
|
6
9
|
|
|
7
10
|
type PrerequisiteTranslationsProblemType = {
|
|
8
|
-
key:
|
|
11
|
+
key: types.TranslationsKeyType;
|
|
9
12
|
existsIn: tools.LanguageType;
|
|
10
13
|
missingIn: tools.LanguageType;
|
|
11
14
|
};
|
|
@@ -15,13 +18,18 @@ export class PrerequisiteTranslations implements prereqs.Prerequisite {
|
|
|
15
18
|
readonly label: prereqs.PrerequisiteLabelType;
|
|
16
19
|
readonly enabled?: boolean = true;
|
|
17
20
|
|
|
18
|
-
private readonly translationsPath?: typeof
|
|
19
|
-
private readonly supportedLanguages:
|
|
21
|
+
private readonly translationsPath?: typeof I18n.DEFAULT_TRANSLATIONS_PATH;
|
|
22
|
+
private readonly supportedLanguages: types.I18nConfigType["supportedLanguages"];
|
|
23
|
+
|
|
24
|
+
private readonly Logger: LoggerPort;
|
|
25
|
+
private readonly JsonFileReader: JsonFileReaderPort;
|
|
20
26
|
|
|
21
27
|
constructor(
|
|
22
28
|
config: prereqs.PrerequisiteConfigType & {
|
|
23
|
-
translationsPath?: typeof
|
|
24
|
-
supportedLanguages:
|
|
29
|
+
translationsPath?: typeof I18n.DEFAULT_TRANSLATIONS_PATH;
|
|
30
|
+
supportedLanguages: types.I18nConfigType["supportedLanguages"];
|
|
31
|
+
Logger: LoggerPort;
|
|
32
|
+
JsonFileReader: JsonFileReaderPort;
|
|
25
33
|
},
|
|
26
34
|
) {
|
|
27
35
|
this.label = config.label;
|
|
@@ -29,51 +37,55 @@ export class PrerequisiteTranslations implements prereqs.Prerequisite {
|
|
|
29
37
|
|
|
30
38
|
this.translationsPath = config.translationsPath;
|
|
31
39
|
this.supportedLanguages = config.supportedLanguages;
|
|
40
|
+
|
|
41
|
+
this.Logger = config.Logger;
|
|
42
|
+
this.JsonFileReader = config.JsonFileReader;
|
|
32
43
|
}
|
|
33
44
|
|
|
34
45
|
async verify(): Promise<prereqs.VerifyOutcome> {
|
|
35
46
|
if (!this.enabled) return prereqs.Verification.undetermined();
|
|
36
47
|
|
|
37
|
-
const translationsPath = this.translationsPath ??
|
|
48
|
+
const translationsPath = this.translationsPath ?? I18n.DEFAULT_TRANSLATIONS_PATH;
|
|
49
|
+
|
|
50
|
+
const supportedLanguages = Object.keys(this.supportedLanguages);
|
|
51
|
+
const i18n = new I18n({ Logger: this.Logger, JsonFileReader: this.JsonFileReader });
|
|
38
52
|
|
|
39
53
|
try {
|
|
40
54
|
await fsp.access(translationsPath, constants.R_OK);
|
|
41
55
|
|
|
42
|
-
for (const language in
|
|
43
|
-
await fsp.access(
|
|
56
|
+
for (const language in supportedLanguages) {
|
|
57
|
+
await fsp.access(i18n.getTranslationPathForLanguage(language).get(), constants.R_OK);
|
|
44
58
|
}
|
|
45
59
|
} catch (error) {
|
|
46
60
|
return prereqs.Verification.failure(error as Error);
|
|
47
61
|
}
|
|
48
62
|
|
|
49
|
-
const supportedLanguages = Object.keys(this.supportedLanguages);
|
|
50
|
-
|
|
51
63
|
if (supportedLanguages.length === 1) return prereqs.Verification.success();
|
|
52
64
|
|
|
53
|
-
const languageToTranslationKeys: Record<tools.LanguageType,
|
|
65
|
+
const languageToTranslationKeys: Record<tools.LanguageType, types.TranslationsKeyType[]> = {};
|
|
54
66
|
|
|
55
67
|
const problems: PrerequisiteTranslationsProblemType[] = [];
|
|
56
68
|
|
|
57
69
|
for (const language of supportedLanguages) {
|
|
58
|
-
const translations = await
|
|
70
|
+
const translations = await i18n.getTranslations(language);
|
|
59
71
|
const translationKeys = Object.keys(translations);
|
|
60
72
|
|
|
61
73
|
languageToTranslationKeys[language] = translationKeys;
|
|
62
74
|
}
|
|
63
75
|
|
|
64
|
-
for (const
|
|
65
|
-
const translationKeys = languageToTranslationKeys[
|
|
76
|
+
for (const language in languageToTranslationKeys) {
|
|
77
|
+
const translationKeys = languageToTranslationKeys[language] ?? [];
|
|
66
78
|
|
|
67
79
|
for (const translationKey of translationKeys) {
|
|
68
80
|
for (const supportedLanguage of supportedLanguages) {
|
|
69
|
-
if (supportedLanguage ===
|
|
81
|
+
if (supportedLanguage === language) continue;
|
|
70
82
|
|
|
71
83
|
const translationKeyExists = languageToTranslationKeys[supportedLanguage]?.some(
|
|
72
84
|
(key) => translationKey === key,
|
|
73
85
|
);
|
|
74
86
|
|
|
75
87
|
if (!translationKeyExists) {
|
|
76
|
-
problems.push({ key: translationKey, existsIn:
|
|
88
|
+
problems.push({ key: translationKey, existsIn: language, missingIn: supportedLanguage });
|
|
77
89
|
}
|
|
78
90
|
}
|
|
79
91
|
}
|
|
@@ -48,6 +48,8 @@ export class Verification {
|
|
|
48
48
|
|
|
49
49
|
export type PrerequisiteConfigType = { label: string; enabled?: boolean };
|
|
50
50
|
|
|
51
|
+
export const PrerequisitesError = { Failure: "prerequisites.failure" } as const;
|
|
52
|
+
|
|
51
53
|
/** @public */
|
|
52
54
|
export class Prerequisites {
|
|
53
55
|
private readonly base = { component: "infra", operation: "startup" };
|
|
@@ -61,9 +63,7 @@ export class Prerequisites {
|
|
|
61
63
|
|
|
62
64
|
const failed = results.filter((result) => result.outcome.status === PrerequisiteStatusEnum.failure);
|
|
63
65
|
|
|
64
|
-
if (failed.length === 0) {
|
|
65
|
-
return this.logger.info({ message: "Prerequisites ok", ...this.base });
|
|
66
|
-
}
|
|
66
|
+
if (failed.length === 0) return this.logger.info({ message: "Prerequisites ok", ...this.base });
|
|
67
67
|
|
|
68
68
|
for (const failure of failed) {
|
|
69
69
|
this.logger.error({
|
|
@@ -75,6 +75,6 @@ export class Prerequisites {
|
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
throw new Error(
|
|
78
|
+
throw new Error(PrerequisitesError.Failure);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type * as tools from "@bgord/tools";
|
|
2
2
|
import NodeCache from "node-cache";
|
|
3
|
-
import type {
|
|
3
|
+
import type { RateLimitStorePort, RateLimitStoreSubjectType } from "./rate-limit-store.port";
|
|
4
4
|
|
|
5
|
-
export class
|
|
5
|
+
export class RateLimitStoreNodeCacheAdapter implements RateLimitStorePort {
|
|
6
6
|
private readonly store: NodeCache;
|
|
7
7
|
|
|
8
8
|
constructor(readonly ttl: tools.Duration) {
|
|
@@ -2,7 +2,7 @@ import type * as tools from "@bgord/tools";
|
|
|
2
2
|
|
|
3
3
|
export type RateLimitStoreSubjectType = string;
|
|
4
4
|
|
|
5
|
-
export interface
|
|
5
|
+
export interface RateLimitStorePort {
|
|
6
6
|
readonly ttl: tools.Duration;
|
|
7
7
|
get(subject: RateLimitStoreSubjectType): Promise<tools.RateLimiter | undefined>;
|
|
8
8
|
set(subject: RateLimitStoreSubjectType, limiter: tools.RateLimiter): Promise<void>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
|
|
3
|
+
export const RecaptchaSecretKeyError = {
|
|
4
|
+
Type: "recaptcha.secret.key.type",
|
|
5
|
+
Length: "recaptcha.secret.key.length",
|
|
6
|
+
} as const;
|
|
7
|
+
|
|
8
|
+
export const RecaptchaSecretKey = z
|
|
9
|
+
.string(RecaptchaSecretKeyError.Type)
|
|
10
|
+
.length(40, RecaptchaSecretKeyError.Length)
|
|
11
|
+
.brand("RecaptchaSecretKey");
|
|
12
|
+
|
|
13
|
+
export type RecaptchaSecretKeyType = z.infer<typeof RecaptchaSecretKey>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
|
|
3
|
+
export const RecaptchaSiteKeyError = {
|
|
4
|
+
Type: "recaptcha.site.key.type",
|
|
5
|
+
Length: "recaptcha.site.key.length",
|
|
6
|
+
} as const;
|
|
7
|
+
|
|
8
|
+
export const RecaptchaSiteKey = z
|
|
9
|
+
.string(RecaptchaSiteKeyError.Type)
|
|
10
|
+
.length(40, RecaptchaSiteKeyError.Length)
|
|
11
|
+
.brand("RecaptchaSiteKey");
|
|
12
|
+
|
|
13
|
+
export type RecaptchaSiteKeyType = z.infer<typeof RecaptchaSiteKey>;
|
|
@@ -15,8 +15,8 @@ export class RedactorEncryptionAdapter implements RedactorPort {
|
|
|
15
15
|
redact<T>(input: T): T {
|
|
16
16
|
const rootObject = Object(input);
|
|
17
17
|
|
|
18
|
-
return cloneDeepWith(input, (value, key,
|
|
19
|
-
if (
|
|
18
|
+
return cloneDeepWith(input, (value, key, parent) => {
|
|
19
|
+
if (parent === rootObject && typeof key === "string" && key.toLowerCase() === this.key) {
|
|
20
20
|
const iv = randomBytes(12);
|
|
21
21
|
const cipher = createCipheriv("aes-256-gcm", this.secret, iv);
|
|
22
22
|
const plaintext = Buffer.from(JSON.stringify(value), "utf8");
|
|
@@ -3,7 +3,6 @@ import type { RedactorPort } from "./redactor.port";
|
|
|
3
3
|
|
|
4
4
|
export class RedactorMaskAdapter implements RedactorPort {
|
|
5
5
|
static readonly DEFAULT_KEYS: readonly string[] = [
|
|
6
|
-
// auth & cookies
|
|
7
6
|
"authorization",
|
|
8
7
|
"cookie",
|
|
9
8
|
"set-cookie",
|
|
@@ -13,7 +12,6 @@ export class RedactorMaskAdapter implements RedactorPort {
|
|
|
13
12
|
"accessToken",
|
|
14
13
|
"refreshToken",
|
|
15
14
|
|
|
16
|
-
// passwords & secrets
|
|
17
15
|
"password",
|
|
18
16
|
"currentPassword",
|
|
19
17
|
"newPassword",
|
|
@@ -21,7 +19,6 @@ export class RedactorMaskAdapter implements RedactorPort {
|
|
|
21
19
|
"clientSecret",
|
|
22
20
|
"secret",
|
|
23
21
|
|
|
24
|
-
// one-time codes
|
|
25
22
|
"otp",
|
|
26
23
|
"code",
|
|
27
24
|
];
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import * as tools from "@bgord/tools";
|
|
3
|
+
import type { FileCleanerPort } from "./file-cleaner.port";
|
|
3
4
|
import type { FileHashPort } from "./file-hash.port";
|
|
5
|
+
import type { FileRenamerPort } from "./file-renamer.port";
|
|
4
6
|
import type {
|
|
5
7
|
RemoteFileStoragePort,
|
|
6
8
|
RemoteHeadResult,
|
|
@@ -8,14 +10,15 @@ import type {
|
|
|
8
10
|
RemotePutFromPathResult,
|
|
9
11
|
} from "./remote-file-storage.port";
|
|
10
12
|
|
|
11
|
-
type RemoteFileStorageDiskConfig = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
publicBaseUrl?: string;
|
|
15
|
-
};
|
|
13
|
+
type RemoteFileStorageDiskConfig = { root: tools.DirectoryPathAbsoluteType; publicBaseUrl?: string };
|
|
14
|
+
|
|
15
|
+
type Dependencies = { FileHash: FileHashPort; FileCleaner: FileCleanerPort; FileRenamer: FileRenamerPort };
|
|
16
16
|
|
|
17
17
|
export class RemoteFileStorageDiskAdapter implements RemoteFileStoragePort {
|
|
18
|
-
constructor(
|
|
18
|
+
constructor(
|
|
19
|
+
private readonly config: RemoteFileStorageDiskConfig,
|
|
20
|
+
private readonly deps: Dependencies,
|
|
21
|
+
) {}
|
|
19
22
|
|
|
20
23
|
private resolveKeyToAbsoluteFilePath(key: tools.ObjectKeyType): tools.FilePathAbsolute {
|
|
21
24
|
const parts = key.split("/");
|
|
@@ -39,16 +42,16 @@ export class RemoteFileStorageDiskAdapter implements RemoteFileStoragePort {
|
|
|
39
42
|
|
|
40
43
|
const source = Bun.file(input.path.get());
|
|
41
44
|
await Bun.write(temporary.get(), source);
|
|
42
|
-
await
|
|
45
|
+
await this.deps.FileRenamer.rename(temporary, final);
|
|
43
46
|
|
|
44
|
-
return this.
|
|
47
|
+
return this.deps.FileHash.hash(final);
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
async head(key: tools.ObjectKeyType): Promise<RemoteHeadResult> {
|
|
48
51
|
const path = this.resolveKeyToAbsoluteFilePath(key);
|
|
49
52
|
|
|
50
53
|
try {
|
|
51
|
-
return { exists: true, ...(await this.
|
|
54
|
+
return { exists: true, ...(await this.deps.FileHash.hash(path)) };
|
|
52
55
|
} catch {
|
|
53
56
|
return { exists: false };
|
|
54
57
|
}
|
|
@@ -65,10 +68,6 @@ export class RemoteFileStorageDiskAdapter implements RemoteFileStoragePort {
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
async delete(key: tools.ObjectKeyType): Promise<void> {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
await fs.unlink(path.get());
|
|
72
|
-
} catch (error) {}
|
|
71
|
+
await this.deps.FileCleaner.delete(this.resolveKeyToAbsoluteFilePath(key));
|
|
73
72
|
}
|
|
74
73
|
}
|
|
@@ -3,7 +3,8 @@ import type hono from "hono";
|
|
|
3
3
|
export async function safeParseBody(c: hono.Context): Promise<any> {
|
|
4
4
|
try {
|
|
5
5
|
const rawBody = await c.req.text();
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
if (!rawBody.trim()) return {};
|
|
7
8
|
return JSON.parse(rawBody);
|
|
8
9
|
} catch {
|
|
9
10
|
return {};
|
package/src/setup.service.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { ETagExtractor } from "./etag-extractor.middleware";
|
|
|
15
15
|
import { HttpLogger, type HttpLoggerOptions } from "./http-logger.middleware";
|
|
16
16
|
import type { I18nConfigType } from "./i18n.service";
|
|
17
17
|
import type { IdProviderPort } from "./id-provider.port";
|
|
18
|
+
import type { JsonFileReaderPort } from "./json-file-reader.port";
|
|
18
19
|
import type { LoggerPort } from "./logger.port";
|
|
19
20
|
import { TimeZoneOffset } from "./time-zone-offset.middleware";
|
|
20
21
|
import { WeakETagExtractor } from "./weak-etag-extractor.middleware";
|
|
@@ -32,6 +33,7 @@ type Dependencies = {
|
|
|
32
33
|
IdProvider: IdProviderPort;
|
|
33
34
|
I18n: I18nConfigType;
|
|
34
35
|
Clock: ClockPort;
|
|
36
|
+
JsonFileReader: JsonFileReaderPort;
|
|
35
37
|
};
|
|
36
38
|
|
|
37
39
|
export class Setup {
|
|
@@ -43,7 +45,7 @@ export class Setup {
|
|
|
43
45
|
secureHeaders(secureHeadersOptions),
|
|
44
46
|
bodyLimit({ maxSize: BODY_LIMIT_MAX_SIZE }),
|
|
45
47
|
uaBlocker({ blocklist: BOTS_REGEX }),
|
|
46
|
-
ApiVersion.build({ Clock: deps.Clock }),
|
|
48
|
+
ApiVersion.build({ Clock: deps.Clock, JsonFileReader: deps.JsonFileReader }),
|
|
47
49
|
cors(corsOptions),
|
|
48
50
|
languageDetector({
|
|
49
51
|
supportedLanguages: Object.keys(deps.I18n.supportedLanguages),
|
|
@@ -12,9 +12,7 @@ export class ShieldApiKey {
|
|
|
12
12
|
constructor(private readonly config: ApiKeyShieldConfigType) {}
|
|
13
13
|
|
|
14
14
|
verify = createMiddleware(async (c, next) => {
|
|
15
|
-
if (c.req.header(ShieldApiKey.HEADER_NAME) === this.config.API_KEY)
|
|
16
|
-
return next();
|
|
17
|
-
}
|
|
15
|
+
if (c.req.header(ShieldApiKey.HEADER_NAME) === this.config.API_KEY) return next();
|
|
18
16
|
|
|
19
17
|
throw AccessDeniedApiKeyError;
|
|
20
18
|
});
|
|
@@ -5,9 +5,7 @@ import type hono from "hono";
|
|
|
5
5
|
import { createMiddleware } from "hono/factory";
|
|
6
6
|
import { HTTPException } from "hono/http-exception";
|
|
7
7
|
|
|
8
|
-
export const AccessDeniedAuthShieldError = new HTTPException(403, {
|
|
9
|
-
message: "access_denied_auth_shield",
|
|
10
|
-
});
|
|
8
|
+
export const AccessDeniedAuthShieldError = new HTTPException(403, { message: "access_denied_auth_shield" });
|
|
11
9
|
|
|
12
10
|
export class ShieldAuth {
|
|
13
11
|
cors = {
|
|
@@ -25,22 +23,26 @@ export class ShieldAuth {
|
|
|
25
23
|
if (!session) {
|
|
26
24
|
c.set("user", null);
|
|
27
25
|
c.set("session", null);
|
|
26
|
+
|
|
28
27
|
return next();
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
c.set("user", session.user);
|
|
32
31
|
c.set("session", session.session);
|
|
32
|
+
|
|
33
33
|
return next();
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
verify = createMiddleware(async (c: hono.Context, next: hono.Next) => {
|
|
37
37
|
const user = c.get("user");
|
|
38
|
+
|
|
38
39
|
if (!user) throw AccessDeniedAuthShieldError;
|
|
39
40
|
return next();
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
reverse = createMiddleware(async (c: hono.Context, next: hono.Next) => {
|
|
43
44
|
const user = c.get("user");
|
|
45
|
+
|
|
44
46
|
if (user) throw AccessDeniedAuthShieldError;
|
|
45
47
|
return next();
|
|
46
48
|
});
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import hcaptcha from "hcaptcha";
|
|
2
2
|
import { createMiddleware } from "hono/factory";
|
|
3
3
|
import { HTTPException } from "hono/http-exception";
|
|
4
|
+
import type { HCaptchaSecretKeyType } from "./hcaptcha-secret-key.vo";
|
|
4
5
|
import type { ShieldCaptchaPort } from "./shield-captcha.port";
|
|
5
|
-
import type { HCaptchaSecretKeyType } from "./shield-captcha-hcaptcha.adapter";
|
|
6
6
|
|
|
7
7
|
export const AccessDeniedHcaptchaLocalError = new HTTPException(403, {
|
|
8
8
|
message: "access_denied_hcaptcha_local",
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
export class
|
|
11
|
+
export class ShieldCaptchaHcaptchaLocalAdapter implements ShieldCaptchaPort {
|
|
12
12
|
constructor(private readonly secretKey: HCaptchaSecretKeyType) {}
|
|
13
13
|
|
|
14
14
|
verify = createMiddleware(async (_c, next) => {
|
|
15
15
|
try {
|
|
16
16
|
const result = await hcaptcha.verify(this.secretKey, "10000000-aaaa-bbbb-cccc-000000000001");
|
|
17
|
+
|
|
17
18
|
if (!result?.success) throw AccessDeniedHcaptchaLocalError;
|
|
18
19
|
return next();
|
|
19
|
-
} catch
|
|
20
|
+
} catch {
|
|
20
21
|
throw AccessDeniedHcaptchaLocalError;
|
|
21
22
|
}
|
|
22
23
|
});
|
|
@@ -1,31 +1,23 @@
|
|
|
1
1
|
import hcaptcha from "hcaptcha";
|
|
2
2
|
import { createMiddleware } from "hono/factory";
|
|
3
3
|
import { HTTPException } from "hono/http-exception";
|
|
4
|
-
import {
|
|
4
|
+
import type { HCaptchaSecretKeyType } from "./hcaptcha-secret-key.vo";
|
|
5
5
|
import type { ShieldCaptchaPort } from "./shield-captcha.port";
|
|
6
6
|
|
|
7
|
-
export const HCaptchaSecretKey = z.string().trim().length(42).brand("HCaptchaSecretKey");
|
|
8
|
-
export type HCaptchaSecretKeyType = z.infer<typeof HCaptchaSecretKey>;
|
|
9
|
-
|
|
10
|
-
export const HCaptchaSiteKey = z.string().trim().length(36);
|
|
11
|
-
export type HCaptchaSiteKeyType = z.infer<typeof HCaptchaSiteKey>;
|
|
12
|
-
|
|
13
|
-
export const HCaptchaResponseToken = z.string().trim();
|
|
14
|
-
export type HCaptchaResponseTokenType = z.infer<typeof HCaptchaResponseToken>;
|
|
15
|
-
|
|
16
7
|
export const AccessDeniedHcaptchaError = new HTTPException(403, { message: "access_denied_hcaptcha" });
|
|
17
8
|
|
|
18
|
-
export class
|
|
9
|
+
export class ShieldCaptchaHcaptchaAdapter implements ShieldCaptchaPort {
|
|
19
10
|
constructor(private readonly secretKey: HCaptchaSecretKeyType) {}
|
|
20
11
|
|
|
21
12
|
verify = createMiddleware(async (c, next) => {
|
|
22
13
|
try {
|
|
23
14
|
const form = await c.req.formData();
|
|
24
|
-
const hcaptchaTokenFormData = form.get("h-captcha-response")?.toString() as
|
|
15
|
+
const hcaptchaTokenFormData = form.get("h-captcha-response")?.toString() as string;
|
|
25
16
|
const result = await hcaptcha.verify(this.secretKey, hcaptchaTokenFormData);
|
|
17
|
+
|
|
26
18
|
if (!result?.success) throw AccessDeniedHcaptchaError;
|
|
27
19
|
return next();
|
|
28
|
-
} catch
|
|
20
|
+
} catch {
|
|
29
21
|
throw AccessDeniedHcaptchaError;
|
|
30
22
|
}
|
|
31
23
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createMiddleware } from "hono/factory";
|
|
2
2
|
import type { ShieldCaptchaPort } from "./shield-captcha.port";
|
|
3
3
|
|
|
4
|
-
export class
|
|
4
|
+
export class ShieldCaptchaNoopAdapter implements ShieldCaptchaPort {
|
|
5
5
|
verify = createMiddleware(async (_c, next) => next());
|
|
6
6
|
}
|
|
@@ -1,42 +1,30 @@
|
|
|
1
1
|
import { createMiddleware } from "hono/factory";
|
|
2
2
|
import { HTTPException } from "hono/http-exception";
|
|
3
|
-
import {
|
|
3
|
+
import type { RecaptchaSecretKeyType } from "./recaptcha-secret-key.vo";
|
|
4
4
|
import type { ShieldCaptchaPort } from "./shield-captcha.port";
|
|
5
5
|
|
|
6
|
-
export const RecaptchaSiteKey = z.string().trim().length(40);
|
|
7
|
-
export type RecaptchaSiteKeyType = z.infer<typeof RecaptchaSiteKey>;
|
|
8
|
-
|
|
9
|
-
export const RecaptchaSecretKey = z.string().trim().length(40).brand("RecaptchaSecretKey");
|
|
10
|
-
export type RecaptchaSecretKeyType = z.infer<typeof RecaptchaSecretKey>;
|
|
11
|
-
|
|
12
6
|
export type RecaptchaVerifierConfigType = { secretKey: RecaptchaSecretKeyType };
|
|
13
7
|
export type RecaptchaResultType = { success: boolean; score: number };
|
|
14
8
|
|
|
15
9
|
export const AccessDeniedRecaptchaError = new HTTPException(403, { message: "access_denied_recaptcha" });
|
|
16
10
|
|
|
17
|
-
export class
|
|
18
|
-
private readonly
|
|
19
|
-
|
|
20
|
-
constructor(config: RecaptchaVerifierConfigType) {
|
|
21
|
-
this.secretKey = config.secretKey;
|
|
22
|
-
}
|
|
11
|
+
export class ShieldCaptchaRecaptchaAdapter implements ShieldCaptchaPort {
|
|
12
|
+
constructor(private readonly config: RecaptchaVerifierConfigType) {}
|
|
23
13
|
|
|
24
14
|
verify = createMiddleware(async (c, next) => {
|
|
25
15
|
try {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
16
|
+
const header = c.req.header("x-recaptcha-token");
|
|
17
|
+
const query = c.req.query("recaptchaToken");
|
|
18
|
+
const form = (await c.req.formData()).get("g-recaptcha-response")?.toString();
|
|
28
19
|
|
|
29
|
-
const
|
|
30
|
-
const recaptchaTokenFormData = form.get("g-recaptcha-response")?.toString();
|
|
31
|
-
|
|
32
|
-
const xForwardedForHeader = c.req.header("x-forwarded-for");
|
|
33
|
-
// cSpell:ignore remoteip
|
|
34
|
-
const remoteip = xForwardedForHeader ?? "";
|
|
20
|
+
const token = header ?? query ?? form;
|
|
35
21
|
|
|
36
|
-
const token = recaptchaTokenHeader ?? recaptchaTokenQuery ?? recaptchaTokenFormData;
|
|
37
22
|
if (!token) throw AccessDeniedRecaptchaError;
|
|
38
23
|
|
|
39
|
-
|
|
24
|
+
// cSpell:ignore remoteip
|
|
25
|
+
const remoteip = c.req.header("x-forwarded-for") ?? "";
|
|
26
|
+
|
|
27
|
+
const params = new URLSearchParams({ secret: this.config.secretKey, response: token, remoteip });
|
|
40
28
|
|
|
41
29
|
const response = await fetch("https://www.google.com/recaptcha/api/siteverify", {
|
|
42
30
|
method: "POST",
|
|
@@ -44,10 +32,12 @@ export class ShieldCaptchaRecaptcha implements ShieldCaptchaPort {
|
|
|
44
32
|
body: params,
|
|
45
33
|
});
|
|
46
34
|
|
|
47
|
-
const result =
|
|
35
|
+
const result: RecaptchaResultType = await response.json();
|
|
36
|
+
|
|
48
37
|
if (!result.success || result.score < 0.5) throw AccessDeniedRecaptchaError;
|
|
38
|
+
|
|
49
39
|
await next();
|
|
50
|
-
} catch
|
|
40
|
+
} catch {
|
|
51
41
|
throw AccessDeniedRecaptchaError;
|
|
52
42
|
}
|
|
53
43
|
});
|
|
@@ -3,10 +3,10 @@ import type { Context } from "hono";
|
|
|
3
3
|
import { createMiddleware } from "hono/factory";
|
|
4
4
|
import { HTTPException } from "hono/http-exception";
|
|
5
5
|
import type { ClockPort } from "./clock.port";
|
|
6
|
-
import type {
|
|
6
|
+
import type { RateLimitStorePort } from "./rate-limit-store.port";
|
|
7
7
|
|
|
8
8
|
type SubjectResolver = (c: Context) => string;
|
|
9
|
-
type RateLimitShieldOptionsType = { enabled: boolean; store:
|
|
9
|
+
type RateLimitShieldOptionsType = { enabled: boolean; store: RateLimitStorePort; subject: SubjectResolver };
|
|
10
10
|
type Dependencies = { Clock: ClockPort };
|
|
11
11
|
|
|
12
12
|
export const AnonSubjectResolver: SubjectResolver = () => "anon";
|
package/src/slower.middleware.ts
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
1
|
import * as tools from "@bgord/tools";
|
|
2
|
+
import type { FileCleanerPort } from "./file-cleaner.port";
|
|
3
|
+
import type { FileRenamerPort } from "./file-renamer.port";
|
|
3
4
|
import type { TemporaryFilePort } from "./temporary-file.port";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
constructor(private readonly directory: tools.DirectoryPathAbsoluteType) {}
|
|
6
|
+
type Dependencies = { FileCleaner: FileCleanerPort; FileRenamer: FileRenamerPort };
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export class TemporaryFileAbsoluteAdapter implements TemporaryFilePort {
|
|
9
|
+
constructor(
|
|
10
|
+
private readonly directory: tools.DirectoryPathAbsoluteType,
|
|
11
|
+
private readonly deps: Dependencies,
|
|
12
|
+
) {}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
async write(filename: tools.Filename, content: File) {
|
|
15
|
+
const temporary = tools.FilePathAbsolute.fromPartsSafe(this.directory, filename.withSuffix("-part"));
|
|
16
|
+
const final = tools.FilePathAbsolute.fromPartsSafe(this.directory, filename);
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
await Bun.write(temporary.get(), content);
|
|
19
|
+
await this.deps.FileRenamer.rename(temporary, final);
|
|
20
|
+
|
|
21
|
+
return { path: final };
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
async cleanup(filename: tools.Filename) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
await fs.unlink(path.get());
|
|
23
|
-
} catch (error) {}
|
|
25
|
+
await this.deps.FileCleaner.delete(tools.FilePathAbsolute.fromPartsSafe(this.directory, filename));
|
|
24
26
|
}
|
|
25
27
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as tools from "@bgord/tools";
|
|
2
2
|
import type { TemporaryFilePort } from "./temporary-file.port";
|
|
3
3
|
|
|
4
|
-
export class
|
|
4
|
+
export class TemporaryFileNoopAdapter implements TemporaryFilePort {
|
|
5
5
|
constructor(private readonly directory: tools.DirectoryPathAbsoluteType) {}
|
|
6
6
|
|
|
7
7
|
async write(filename: tools.Filename) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type * as tools from "@bgord/tools";
|
|
2
2
|
|
|
3
3
|
export interface TemporaryFilePort {
|
|
4
|
-
write(filename: tools.Filename,
|
|
4
|
+
write(filename: tools.Filename, content: File): Promise<{ path: tools.FilePathAbsolute }>;
|
|
5
|
+
|
|
5
6
|
cleanup(filename: tools.Filename): Promise<void>;
|
|
6
7
|
}
|
|
@@ -7,11 +7,8 @@ export class TimeZoneOffset {
|
|
|
7
7
|
static TIME_ZONE_OFFSET_HEADER_NAME = "time-zone-offset";
|
|
8
8
|
|
|
9
9
|
static attach = createMiddleware(async (c, next) => {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
c.set("timeZoneOffset", tools.Duration.Minutes(timeZoneOffsetMinutes));
|
|
10
|
+
const offset = tools.TimeZoneOffsetValue.parse(c.req.header(TimeZoneOffset.TIME_ZONE_OFFSET_HEADER_NAME));
|
|
11
|
+
c.set("timeZoneOffset", tools.Duration.Minutes(offset));
|
|
15
12
|
|
|
16
13
|
await next();
|
|
17
14
|
});
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import type * as tools from "@bgord/tools";
|
|
2
1
|
import { createFactory } from "hono/factory";
|
|
3
2
|
import { I18n } from "./i18n.service";
|
|
3
|
+
import type { JsonFileReaderPort } from "./json-file-reader.port";
|
|
4
|
+
import type { LoggerPort } from "./logger.port";
|
|
4
5
|
|
|
5
6
|
const handler = createFactory();
|
|
6
7
|
|
|
8
|
+
type Dependencies = { JsonFileReader: JsonFileReaderPort; Logger: LoggerPort };
|
|
9
|
+
|
|
7
10
|
export class Translations {
|
|
8
|
-
static build = () =>
|
|
11
|
+
static build = (deps: Dependencies) =>
|
|
9
12
|
handler.createHandlers(async (c) => {
|
|
10
|
-
const language = c.get("language")
|
|
11
|
-
const translations = await new I18n().getTranslations(language);
|
|
13
|
+
const language = c.get("language");
|
|
14
|
+
const translations = await new I18n(deps).getTranslations(language);
|
|
12
15
|
|
|
13
16
|
return c.json({ translations, language });
|
|
14
17
|
});
|
package/src/uptime.service.ts
CHANGED
|
@@ -10,9 +10,9 @@ export class Uptime {
|
|
|
10
10
|
private static readonly rounding = new tools.RoundToNearest();
|
|
11
11
|
|
|
12
12
|
static get(clock: ClockPort): UptimeResultType {
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const duration = tools.Duration.Seconds(Uptime.rounding.round(process.uptime()));
|
|
14
|
+
const formatted = tools.DateFormatters.relative(clock.now().Minus(duration));
|
|
15
15
|
|
|
16
|
-
return { duration
|
|
16
|
+
return { duration, formatted };
|
|
17
17
|
}
|
|
18
18
|
}
|