@ddd-ts-kit/kernel 0.8.0 → 0.10.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/README.md +207 -2
- package/dist/application/criteria/index.d.ts +33 -0
- package/dist/application/criteria/index.d.ts.map +1 -0
- package/dist/application/criteria/index.js +33 -0
- package/dist/application/criteria/index.js.map +1 -0
- package/dist/application/event-sourcing/appended.d.ts +8 -0
- package/dist/application/event-sourcing/appended.d.ts.map +1 -0
- package/dist/application/event-sourcing/appended.js +2 -0
- package/dist/application/event-sourcing/appended.js.map +1 -0
- package/dist/application/event-sourcing/define-stored-event.d.ts +10 -0
- package/dist/application/event-sourcing/define-stored-event.d.ts.map +1 -0
- package/dist/application/event-sourcing/define-stored-event.js +22 -0
- package/dist/application/event-sourcing/define-stored-event.js.map +1 -0
- package/dist/application/event-sourcing/erased-personal-data.d.ts +3 -0
- package/dist/application/event-sourcing/erased-personal-data.d.ts.map +1 -0
- package/dist/application/event-sourcing/erased-personal-data.js +3 -0
- package/dist/application/event-sourcing/erased-personal-data.js.map +1 -0
- package/dist/application/event-sourcing/event-envelope.d.ts +9 -0
- package/dist/application/event-sourcing/event-envelope.d.ts.map +1 -0
- package/dist/application/event-sourcing/event-envelope.js +2 -0
- package/dist/application/event-sourcing/event-envelope.js.map +1 -0
- package/dist/application/event-sourcing/event-to-append.d.ts +15 -0
- package/dist/application/event-sourcing/event-to-append.d.ts.map +1 -0
- package/dist/application/event-sourcing/event-to-append.js +2 -0
- package/dist/application/event-sourcing/event-to-append.js.map +1 -0
- package/dist/application/event-sourcing/index.d.ts +21 -0
- package/dist/application/event-sourcing/index.d.ts.map +1 -0
- package/dist/application/event-sourcing/index.js +21 -0
- package/dist/application/event-sourcing/index.js.map +1 -0
- package/dist/application/event-sourcing/is-stored-data.d.ts +5 -0
- package/dist/application/event-sourcing/is-stored-data.d.ts.map +1 -0
- package/dist/application/event-sourcing/is-stored-data.js +5 -0
- package/dist/application/event-sourcing/is-stored-data.js.map +1 -0
- package/dist/application/event-sourcing/is-stored-list.d.ts +4 -0
- package/dist/application/event-sourcing/is-stored-list.d.ts.map +1 -0
- package/dist/application/event-sourcing/is-stored-list.js +5 -0
- package/dist/application/event-sourcing/is-stored-list.js.map +1 -0
- package/dist/application/event-sourcing/personal-data.d.ts +14 -0
- package/dist/application/event-sourcing/personal-data.d.ts.map +1 -0
- package/dist/application/event-sourcing/personal-data.js +9 -0
- package/dist/application/event-sourcing/personal-data.js.map +1 -0
- package/dist/application/event-sourcing/stored-data-of.d.ts +9 -0
- package/dist/application/event-sourcing/stored-data-of.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-data-of.js +40 -0
- package/dist/application/event-sourcing/stored-data-of.js.map +1 -0
- package/dist/application/event-sourcing/stored-data.d.ts +6 -0
- package/dist/application/event-sourcing/stored-data.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-data.js +2 -0
- package/dist/application/event-sourcing/stored-data.js.map +1 -0
- package/dist/application/event-sourcing/stored-event-data.d.ts +25 -0
- package/dist/application/event-sourcing/stored-event-data.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-event-data.js +82 -0
- package/dist/application/event-sourcing/stored-event-data.js.map +1 -0
- package/dist/application/event-sourcing/stored-event-spec.d.ts +20 -0
- package/dist/application/event-sourcing/stored-event-spec.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-event-spec.js +2 -0
- package/dist/application/event-sourcing/stored-event-spec.js.map +1 -0
- package/dist/application/event-sourcing/stored-event-type.d.ts +14 -0
- package/dist/application/event-sourcing/stored-event-type.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-event-type.js +2 -0
- package/dist/application/event-sourcing/stored-event-type.js.map +1 -0
- package/dist/application/event-sourcing/stored-event-types.d.ts +9 -0
- package/dist/application/event-sourcing/stored-event-types.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-event-types.js +2 -0
- package/dist/application/event-sourcing/stored-event-types.js.map +1 -0
- package/dist/application/event-sourcing/stored-event.d.ts +12 -0
- package/dist/application/event-sourcing/stored-event.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-event.js +2 -0
- package/dist/application/event-sourcing/stored-event.js.map +1 -0
- package/dist/application/event-sourcing/stored-json.d.ts +5 -0
- package/dist/application/event-sourcing/stored-json.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-json.js +2 -0
- package/dist/application/event-sourcing/stored-json.js.map +1 -0
- package/dist/application/event-sourcing/stored-snapshot.d.ts +11 -0
- package/dist/application/event-sourcing/stored-snapshot.d.ts.map +1 -0
- package/dist/application/event-sourcing/stored-snapshot.js +2 -0
- package/dist/application/event-sourcing/stored-snapshot.js.map +1 -0
- package/dist/application/event-sourcing/subject-key.d.ts +10 -0
- package/dist/application/event-sourcing/subject-key.d.ts.map +1 -0
- package/dist/application/event-sourcing/subject-key.js +2 -0
- package/dist/application/event-sourcing/subject-key.js.map +1 -0
- package/dist/application/event-sourcing/unreadable-event-error.d.ts +5 -0
- package/dist/application/event-sourcing/unreadable-event-error.d.ts.map +1 -0
- package/dist/application/event-sourcing/unreadable-event-error.js +8 -0
- package/dist/application/event-sourcing/unreadable-event-error.js.map +1 -0
- package/dist/application/event-sourcing/upcaster.d.ts +4 -0
- package/dist/application/event-sourcing/upcaster.d.ts.map +1 -0
- package/dist/application/event-sourcing/upcaster.js +2 -0
- package/dist/application/event-sourcing/upcaster.js.map +1 -0
- package/dist/application/files/accepts-media-type.d.ts +3 -0
- package/dist/application/files/accepts-media-type.d.ts.map +1 -0
- package/dist/application/files/accepts-media-type.js +11 -0
- package/dist/application/files/accepts-media-type.js.map +1 -0
- package/dist/application/files/assert-expiry.d.ts +3 -0
- package/dist/application/files/assert-expiry.d.ts.map +1 -0
- package/dist/application/files/assert-expiry.js +10 -0
- package/dist/application/files/assert-expiry.js.map +1 -0
- package/dist/application/files/assert-file-key.d.ts +3 -0
- package/dist/application/files/assert-file-key.d.ts.map +1 -0
- package/dist/application/files/assert-file-key.js +10 -0
- package/dist/application/files/assert-file-key.js.map +1 -0
- package/dist/application/files/assert-final-key.d.ts +3 -0
- package/dist/application/files/assert-final-key.d.ts.map +1 -0
- package/dist/application/files/assert-final-key.js +11 -0
- package/dist/application/files/assert-final-key.js.map +1 -0
- package/dist/application/files/content-disposition.d.ts +3 -0
- package/dist/application/files/content-disposition.d.ts.map +1 -0
- package/dist/application/files/content-disposition.js +9 -0
- package/dist/application/files/content-disposition.js.map +1 -0
- package/dist/application/files/content-expectation.d.ts +6 -0
- package/dist/application/files/content-expectation.d.ts.map +1 -0
- package/dist/application/files/content-expectation.js +2 -0
- package/dist/application/files/content-expectation.js.map +1 -0
- package/dist/application/files/content-matches.d.ts +7 -0
- package/dist/application/files/content-matches.d.ts.map +1 -0
- package/dist/application/files/content-matches.js +39 -0
- package/dist/application/files/content-matches.js.map +1 -0
- package/dist/application/files/download-url-options.d.ts +7 -0
- package/dist/application/files/download-url-options.d.ts.map +1 -0
- package/dist/application/files/download-url-options.js +2 -0
- package/dist/application/files/download-url-options.js.map +1 -0
- package/dist/application/files/file-content.d.ts +8 -0
- package/dist/application/files/file-content.d.ts.map +1 -0
- package/dist/application/files/file-content.js +2 -0
- package/dist/application/files/file-content.js.map +1 -0
- package/dist/application/files/file-error.d.ts +28 -0
- package/dist/application/files/file-error.d.ts.map +1 -0
- package/dist/application/files/file-error.js +29 -0
- package/dist/application/files/file-error.js.map +1 -0
- package/dist/application/files/file-metadata.d.ts +10 -0
- package/dist/application/files/file-metadata.d.ts.map +1 -0
- package/dist/application/files/file-metadata.js +2 -0
- package/dist/application/files/file-metadata.js.map +1 -0
- package/dist/application/files/file-source.d.ts +4 -0
- package/dist/application/files/file-source.d.ts.map +1 -0
- package/dist/application/files/file-source.js +2 -0
- package/dist/application/files/file-source.js.map +1 -0
- package/dist/application/files/file-upload.d.ts +25 -0
- package/dist/application/files/file-upload.d.ts.map +1 -0
- package/dist/application/files/file-upload.js +36 -0
- package/dist/application/files/file-upload.js.map +1 -0
- package/dist/application/files/index.d.ts +31 -0
- package/dist/application/files/index.d.ts.map +1 -0
- package/dist/application/files/index.js +31 -0
- package/dist/application/files/index.js.map +1 -0
- package/dist/application/files/inspection-limits.d.ts +8 -0
- package/dist/application/files/inspection-limits.d.ts.map +1 -0
- package/dist/application/files/inspection-limits.js +2 -0
- package/dist/application/files/inspection-limits.js.map +1 -0
- package/dist/application/files/is-file-key.d.ts +7 -0
- package/dist/application/files/is-file-key.d.ts.map +1 -0
- package/dist/application/files/is-file-key.js +11 -0
- package/dist/application/files/is-file-key.js.map +1 -0
- package/dist/application/files/listed-file.d.ts +7 -0
- package/dist/application/files/listed-file.d.ts.map +1 -0
- package/dist/application/files/listed-file.js +2 -0
- package/dist/application/files/listed-file.js.map +1 -0
- package/dist/application/files/max-signed-url-seconds.d.ts +3 -0
- package/dist/application/files/max-signed-url-seconds.d.ts.map +1 -0
- package/dist/application/files/max-signed-url-seconds.js +3 -0
- package/dist/application/files/max-signed-url-seconds.js.map +1 -0
- package/dist/application/files/media-type-of.d.ts +3 -0
- package/dist/application/files/media-type-of.d.ts.map +1 -0
- package/dist/application/files/media-type-of.js +5 -0
- package/dist/application/files/media-type-of.js.map +1 -0
- package/dist/application/files/pending-upload-link.d.ts +10 -0
- package/dist/application/files/pending-upload-link.d.ts.map +1 -0
- package/dist/application/files/pending-upload-link.js +2 -0
- package/dist/application/files/pending-upload-link.js.map +1 -0
- package/dist/application/files/pending-upload.d.ts +15 -0
- package/dist/application/files/pending-upload.d.ts.map +1 -0
- package/dist/application/files/pending-upload.js +2 -0
- package/dist/application/files/pending-upload.js.map +1 -0
- package/dist/application/files/put-options.d.ts +7 -0
- package/dist/application/files/put-options.d.ts.map +1 -0
- package/dist/application/files/put-options.js +2 -0
- package/dist/application/files/put-options.js.map +1 -0
- package/dist/application/files/received-file.d.ts +15 -0
- package/dist/application/files/received-file.d.ts.map +1 -0
- package/dist/application/files/received-file.js +2 -0
- package/dist/application/files/received-file.js.map +1 -0
- package/dist/application/files/scan-verdict.d.ts +8 -0
- package/dist/application/files/scan-verdict.d.ts.map +1 -0
- package/dist/application/files/scan-verdict.js +2 -0
- package/dist/application/files/scan-verdict.js.map +1 -0
- package/dist/application/files/signature-of.d.ts +3 -0
- package/dist/application/files/signature-of.d.ts.map +1 -0
- package/dist/application/files/signature-of.js +28 -0
- package/dist/application/files/signature-of.js.map +1 -0
- package/dist/application/files/signed-download.d.ts +6 -0
- package/dist/application/files/signed-download.d.ts.map +1 -0
- package/dist/application/files/signed-download.js +2 -0
- package/dist/application/files/signed-download.js.map +1 -0
- package/dist/application/files/signed-upload.d.ts +9 -0
- package/dist/application/files/signed-upload.d.ts.map +1 -0
- package/dist/application/files/signed-upload.js +2 -0
- package/dist/application/files/signed-upload.js.map +1 -0
- package/dist/application/files/signed-url.d.ts +6 -0
- package/dist/application/files/signed-url.d.ts.map +1 -0
- package/dist/application/files/signed-url.js +2 -0
- package/dist/application/files/signed-url.js.map +1 -0
- package/dist/application/files/staged-key-of.d.ts +5 -0
- package/dist/application/files/staged-key-of.d.ts.map +1 -0
- package/dist/application/files/staged-key-of.js +7 -0
- package/dist/application/files/staged-key-of.js.map +1 -0
- package/dist/application/files/stored-file.d.ts +16 -0
- package/dist/application/files/stored-file.d.ts.map +1 -0
- package/dist/application/files/stored-file.js +2 -0
- package/dist/application/files/stored-file.js.map +1 -0
- package/dist/application/files/upload-url-options.d.ts +12 -0
- package/dist/application/files/upload-url-options.d.ts.map +1 -0
- package/dist/application/files/upload-url-options.js +2 -0
- package/dist/application/files/upload-url-options.js.map +1 -0
- package/dist/application/persistence/append-changes.d.ts +18 -0
- package/dist/application/persistence/append-changes.d.ts.map +1 -0
- package/dist/application/persistence/append-changes.js +17 -0
- package/dist/application/persistence/append-changes.js.map +1 -0
- package/dist/application/ports/checkpoint-store.d.ts +14 -0
- package/dist/application/ports/checkpoint-store.d.ts.map +1 -0
- package/dist/application/ports/checkpoint-store.js +10 -0
- package/dist/application/ports/checkpoint-store.js.map +1 -0
- package/dist/application/ports/event-store.d.ts +24 -0
- package/dist/application/ports/event-store.d.ts.map +1 -0
- package/dist/application/ports/event-store.js +12 -0
- package/dist/application/ports/event-store.js.map +1 -0
- package/dist/application/ports/file-keys.d.ts +9 -0
- package/dist/application/ports/file-keys.d.ts.map +1 -0
- package/dist/application/ports/file-keys.js +10 -0
- package/dist/application/ports/file-keys.js.map +1 -0
- package/dist/application/ports/file-scanner.d.ts +13 -0
- package/dist/application/ports/file-scanner.d.ts.map +1 -0
- package/dist/application/ports/file-scanner.js +12 -0
- package/dist/application/ports/file-scanner.js.map +1 -0
- package/dist/application/ports/file-storage.d.ts +40 -0
- package/dist/application/ports/file-storage.d.ts.map +1 -0
- package/dist/application/ports/file-storage.js +15 -0
- package/dist/application/ports/file-storage.js.map +1 -0
- package/dist/application/ports/served-file-storage.d.ts +16 -0
- package/dist/application/ports/served-file-storage.d.ts.map +1 -0
- package/dist/application/ports/served-file-storage.js +12 -0
- package/dist/application/ports/served-file-storage.js.map +1 -0
- package/dist/application/ports/snapshot-store.d.ts +8 -0
- package/dist/application/ports/snapshot-store.d.ts.map +1 -0
- package/dist/application/ports/snapshot-store.js +7 -0
- package/dist/application/ports/snapshot-store.js.map +1 -0
- package/dist/application/ports/subject-key-store.d.ts +17 -0
- package/dist/application/ports/subject-key-store.d.ts.map +1 -0
- package/dist/application/ports/subject-key-store.js +13 -0
- package/dist/application/ports/subject-key-store.js.map +1 -0
- package/dist/declarations/decorators/projection-options.d.ts +5 -0
- package/dist/declarations/decorators/projection-options.d.ts.map +1 -0
- package/dist/declarations/decorators/projection-options.js +2 -0
- package/dist/declarations/decorators/projection-options.js.map +1 -0
- package/dist/declarations/decorators/projection.d.ts +4 -0
- package/dist/declarations/decorators/projection.d.ts.map +1 -1
- package/dist/declarations/decorators/projection.js +16 -8
- package/dist/declarations/decorators/projection.js.map +1 -1
- package/dist/declarations/model/projection-declaration.d.ts +3 -0
- package/dist/declarations/model/projection-declaration.d.ts.map +1 -1
- package/dist/declarations/model/projection-feed.d.ts +8 -0
- package/dist/declarations/model/projection-feed.d.ts.map +1 -0
- package/dist/declarations/model/projection-feed.js +2 -0
- package/dist/declarations/model/projection-feed.js.map +1 -0
- package/dist/declarations/projection/applying-projection.d.ts +14 -0
- package/dist/declarations/projection/applying-projection.d.ts.map +1 -0
- package/dist/declarations/projection/applying-projection.js +32 -0
- package/dist/declarations/projection/applying-projection.js.map +1 -0
- package/dist/declarations.d.ts +3 -0
- package/dist/declarations.d.ts.map +1 -1
- package/dist/declarations.js +1 -0
- package/dist/declarations.js.map +1 -1
- package/dist/domain/event-sourcing/aggregate-history.d.ts +10 -0
- package/dist/domain/event-sourcing/aggregate-history.d.ts.map +1 -0
- package/dist/domain/event-sourcing/aggregate-history.js +2 -0
- package/dist/domain/event-sourcing/aggregate-history.js.map +1 -0
- package/dist/domain/event-sourcing/aggregate-snapshot.d.ts +6 -0
- package/dist/domain/event-sourcing/aggregate-snapshot.d.ts.map +1 -0
- package/dist/domain/event-sourcing/aggregate-snapshot.js +2 -0
- package/dist/domain/event-sourcing/aggregate-snapshot.js.map +1 -0
- package/dist/domain/event-sourcing/appliers.d.ts +12 -0
- package/dist/domain/event-sourcing/appliers.d.ts.map +1 -0
- package/dist/domain/event-sourcing/appliers.js +2 -0
- package/dist/domain/event-sourcing/appliers.js.map +1 -0
- package/dist/domain/event-sourcing/event-sourced-aggregate.d.ts +28 -0
- package/dist/domain/event-sourcing/event-sourced-aggregate.d.ts.map +1 -0
- package/dist/domain/event-sourcing/event-sourced-aggregate.js +51 -0
- package/dist/domain/event-sourcing/event-sourced-aggregate.js.map +1 -0
- package/dist/domain/event-sourcing/unstored-events.d.ts +8 -0
- package/dist/domain/event-sourcing/unstored-events.d.ts.map +1 -0
- package/dist/domain/event-sourcing/unstored-events.js +7 -0
- package/dist/domain/event-sourcing/unstored-events.js.map +1 -0
- package/dist/index.d.ts +52 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -32
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/domain-events/after-commit.d.ts +10 -0
- package/dist/infrastructure/domain-events/after-commit.d.ts.map +1 -0
- package/dist/infrastructure/domain-events/after-commit.js +19 -0
- package/dist/infrastructure/domain-events/after-commit.js.map +1 -0
- package/dist/infrastructure/domain-events/at-commit.d.ts +11 -0
- package/dist/infrastructure/domain-events/at-commit.d.ts.map +1 -0
- package/dist/infrastructure/domain-events/at-commit.js +19 -0
- package/dist/infrastructure/domain-events/at-commit.js.map +1 -0
- package/dist/infrastructure/domain-events/commit-step.d.ts +10 -0
- package/dist/infrastructure/domain-events/commit-step.d.ts.map +1 -0
- package/dist/infrastructure/domain-events/commit-step.js +2 -0
- package/dist/infrastructure/domain-events/commit-step.js.map +1 -0
- package/dist/infrastructure/domain-events/unit-of-work-scope.d.ts +5 -0
- package/dist/infrastructure/domain-events/unit-of-work-scope.d.ts.map +1 -1
- package/dist/infrastructure/domain-events/unit-of-work-scope.js.map +1 -1
- package/dist/infrastructure/domain-events/within-unit-of-work.d.ts +3 -1
- package/dist/infrastructure/domain-events/within-unit-of-work.d.ts.map +1 -1
- package/dist/infrastructure/domain-events/within-unit-of-work.js +32 -5
- package/dist/infrastructure/domain-events/within-unit-of-work.js.map +1 -1
- package/dist/infrastructure/event-sourcing/catch-up-subscription.d.ts +33 -0
- package/dist/infrastructure/event-sourcing/catch-up-subscription.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/catch-up-subscription.js +39 -0
- package/dist/infrastructure/event-sourcing/catch-up-subscription.js.map +1 -0
- package/dist/infrastructure/event-sourcing/event-serializer.d.ts +35 -0
- package/dist/infrastructure/event-sourcing/event-serializer.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/event-serializer.js +104 -0
- package/dist/infrastructure/event-sourcing/event-serializer.js.map +1 -0
- package/dist/infrastructure/event-sourcing/event-sourced-repository.d.ts +32 -0
- package/dist/infrastructure/event-sourcing/event-sourced-repository.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/event-sourced-repository.js +68 -0
- package/dist/infrastructure/event-sourcing/event-sourced-repository.js.map +1 -0
- package/dist/infrastructure/event-sourcing/event-sourcing-stores.d.ts +12 -0
- package/dist/infrastructure/event-sourcing/event-sourcing-stores.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/event-sourcing-stores.js +2 -0
- package/dist/infrastructure/event-sourcing/event-sourcing-stores.js.map +1 -0
- package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.d.ts +34 -0
- package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.js +48 -0
- package/dist/infrastructure/event-sourcing/event-store-projection-rebuild.js.map +1 -0
- package/dist/infrastructure/event-sourcing/personal-data-cipher.d.ts +19 -0
- package/dist/infrastructure/event-sourcing/personal-data-cipher.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/personal-data-cipher.js +84 -0
- package/dist/infrastructure/event-sourcing/personal-data-cipher.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.d.ts +6 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.js +2 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-options.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.d.ts +9 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.js +32 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables-sql.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables.d.ts +9 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables.js +9 -0
- package/dist/infrastructure/event-sourcing/postgres/event-store-tables.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.d.ts +3 -0
- package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.js +22 -0
- package/dist/infrastructure/event-sourcing/postgres/is-append-conflict.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.d.ts +12 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.js +26 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-checkpoint-store.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.d.ts +6 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.js +14 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-sourcing.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.d.ts +31 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.js +120 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-event-store.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.d.ts +13 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.js +28 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-snapshot-store.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.d.ts +21 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.js +48 -0
- package/dist/infrastructure/event-sourcing/postgres/postgres-subject-key-store.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/qualified-table.d.ts +4 -0
- package/dist/infrastructure/event-sourcing/postgres/qualified-table.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/qualified-table.js +10 -0
- package/dist/infrastructure/event-sourcing/postgres/qualified-table.js.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/stored-data-from.d.ts +4 -0
- package/dist/infrastructure/event-sourcing/postgres/stored-data-from.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/postgres/stored-data-from.js +23 -0
- package/dist/infrastructure/event-sourcing/postgres/stored-data-from.js.map +1 -0
- package/dist/infrastructure/event-sourcing/rewrite-objects.d.ts +8 -0
- package/dist/infrastructure/event-sourcing/rewrite-objects.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/rewrite-objects.js +16 -0
- package/dist/infrastructure/event-sourcing/rewrite-objects.js.map +1 -0
- package/dist/infrastructure/event-sourcing/snapshot-policy.d.ts +14 -0
- package/dist/infrastructure/event-sourcing/snapshot-policy.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/snapshot-policy.js +2 -0
- package/dist/infrastructure/event-sourcing/snapshot-policy.js.map +1 -0
- package/dist/infrastructure/event-sourcing/stored-origins.d.ts +5 -0
- package/dist/infrastructure/event-sourcing/stored-origins.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/stored-origins.js +3 -0
- package/dist/infrastructure/event-sourcing/stored-origins.js.map +1 -0
- package/dist/infrastructure/event-sourcing/stored-stamp-of.d.ts +10 -0
- package/dist/infrastructure/event-sourcing/stored-stamp-of.d.ts.map +1 -0
- package/dist/infrastructure/event-sourcing/stored-stamp-of.js +14 -0
- package/dist/infrastructure/event-sourcing/stored-stamp-of.js.map +1 -0
- package/dist/infrastructure/files/accept-every-file-scanner.d.ts +7 -0
- package/dist/infrastructure/files/accept-every-file-scanner.d.ts.map +1 -0
- package/dist/infrastructure/files/accept-every-file-scanner.js +7 -0
- package/dist/infrastructure/files/accept-every-file-scanner.js.map +1 -0
- package/dist/infrastructure/files/collect.d.ts +4 -0
- package/dist/infrastructure/files/collect.d.ts.map +1 -0
- package/dist/infrastructure/files/collect.js +11 -0
- package/dist/infrastructure/files/collect.js.map +1 -0
- package/dist/infrastructure/files/file-grant.d.ts +11 -0
- package/dist/infrastructure/files/file-grant.d.ts.map +1 -0
- package/dist/infrastructure/files/file-grant.js +2 -0
- package/dist/infrastructure/files/file-grant.js.map +1 -0
- package/dist/infrastructure/files/file-inspection.d.ts +22 -0
- package/dist/infrastructure/files/file-inspection.d.ts.map +1 -0
- package/dist/infrastructure/files/file-inspection.js +66 -0
- package/dist/infrastructure/files/file-inspection.js.map +1 -0
- package/dist/infrastructure/files/file-staging.d.ts +59 -0
- package/dist/infrastructure/files/file-staging.d.ts.map +1 -0
- package/dist/infrastructure/files/file-staging.js +142 -0
- package/dist/infrastructure/files/file-staging.js.map +1 -0
- package/dist/infrastructure/files/file-uploads-middleware.d.ts +11 -0
- package/dist/infrastructure/files/file-uploads-middleware.d.ts.map +1 -0
- package/dist/infrastructure/files/file-uploads-middleware.js +25 -0
- package/dist/infrastructure/files/file-uploads-middleware.js.map +1 -0
- package/dist/infrastructure/files/in-memory-file-storage.d.ts +25 -0
- package/dist/infrastructure/files/in-memory-file-storage.d.ts.map +1 -0
- package/dist/infrastructure/files/in-memory-file-storage.js +73 -0
- package/dist/infrastructure/files/in-memory-file-storage.js.map +1 -0
- package/dist/infrastructure/files/is-file-grant.d.ts +3 -0
- package/dist/infrastructure/files/is-file-grant.d.ts.map +1 -0
- package/dist/infrastructure/files/is-file-grant.js +16 -0
- package/dist/infrastructure/files/is-file-grant.js.map +1 -0
- package/dist/infrastructure/files/is-stored-metadata.d.ts +3 -0
- package/dist/infrastructure/files/is-stored-metadata.d.ts.map +1 -0
- package/dist/infrastructure/files/is-stored-metadata.js +8 -0
- package/dist/infrastructure/files/is-stored-metadata.js.map +1 -0
- package/dist/infrastructure/files/local-file-storage-options.d.ts +6 -0
- package/dist/infrastructure/files/local-file-storage-options.d.ts.map +1 -0
- package/dist/infrastructure/files/local-file-storage-options.js +2 -0
- package/dist/infrastructure/files/local-file-storage-options.js.map +1 -0
- package/dist/infrastructure/files/local-file-storage.d.ts +29 -0
- package/dist/infrastructure/files/local-file-storage.d.ts.map +1 -0
- package/dist/infrastructure/files/local-file-storage.js +103 -0
- package/dist/infrastructure/files/local-file-storage.js.map +1 -0
- package/dist/infrastructure/files/local-paths.d.ts +12 -0
- package/dist/infrastructure/files/local-paths.d.ts.map +1 -0
- package/dist/infrastructure/files/local-paths.js +33 -0
- package/dist/infrastructure/files/local-paths.js.map +1 -0
- package/dist/infrastructure/files/purge-staged-files.d.ts +16 -0
- package/dist/infrastructure/files/purge-staged-files.d.ts.map +1 -0
- package/dist/infrastructure/files/purge-staged-files.js +21 -0
- package/dist/infrastructure/files/purge-staged-files.js.map +1 -0
- package/dist/infrastructure/files/self-signed-file-storage.d.ts +23 -0
- package/dist/infrastructure/files/self-signed-file-storage.d.ts.map +1 -0
- package/dist/infrastructure/files/self-signed-file-storage.js +57 -0
- package/dist/infrastructure/files/self-signed-file-storage.js.map +1 -0
- package/dist/infrastructure/files/signed-file-tokens.d.ts +20 -0
- package/dist/infrastructure/files/signed-file-tokens.d.ts.map +1 -0
- package/dist/infrastructure/files/signed-file-tokens.js +45 -0
- package/dist/infrastructure/files/signed-file-tokens.js.map +1 -0
- package/dist/infrastructure/files/signed-link-options.d.ts +10 -0
- package/dist/infrastructure/files/signed-link-options.d.ts.map +1 -0
- package/dist/infrastructure/files/signed-link-options.js +2 -0
- package/dist/infrastructure/files/signed-link-options.js.map +1 -0
- package/dist/infrastructure/files/stored-metadata.d.ts +6 -0
- package/dist/infrastructure/files/stored-metadata.d.ts.map +1 -0
- package/dist/infrastructure/files/stored-metadata.js +2 -0
- package/dist/infrastructure/files/stored-metadata.js.map +1 -0
- package/dist/infrastructure/files/tenant-file-keys.d.ts +20 -0
- package/dist/infrastructure/files/tenant-file-keys.d.ts.map +1 -0
- package/dist/infrastructure/files/tenant-file-keys.js +27 -0
- package/dist/infrastructure/files/tenant-file-keys.js.map +1 -0
- package/dist/infrastructure/files/upload-desk.d.ts +8 -0
- package/dist/infrastructure/files/upload-desk.d.ts.map +1 -0
- package/dist/infrastructure/files/upload-desk.js +2 -0
- package/dist/infrastructure/files/upload-desk.js.map +1 -0
- package/dist/infrastructure/files/without-trailing-slashes.d.ts +3 -0
- package/dist/infrastructure/files/without-trailing-slashes.d.ts.map +1 -0
- package/dist/infrastructure/files/without-trailing-slashes.js +9 -0
- package/dist/infrastructure/files/without-trailing-slashes.js.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-checkpoint-store.d.ts +8 -0
- package/dist/infrastructure/in-memory/in-memory-checkpoint-store.d.ts.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-checkpoint-store.js +15 -0
- package/dist/infrastructure/in-memory/in-memory-checkpoint-store.js.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-event-store.d.ts +14 -0
- package/dist/infrastructure/in-memory/in-memory-event-store.d.ts.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-event-store.js +37 -0
- package/dist/infrastructure/in-memory/in-memory-event-store.js.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-snapshot-store.d.ts +9 -0
- package/dist/infrastructure/in-memory/in-memory-snapshot-store.d.ts.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-snapshot-store.js +15 -0
- package/dist/infrastructure/in-memory/in-memory-snapshot-store.js.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-subject-key-store.d.ts +10 -0
- package/dist/infrastructure/in-memory/in-memory-subject-key-store.d.ts.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-subject-key-store.js +21 -0
- package/dist/infrastructure/in-memory/in-memory-subject-key-store.js.map +1 -0
- package/dist/infrastructure/read-model/shadow-read-model-store.d.ts +20 -0
- package/dist/infrastructure/read-model/shadow-read-model-store.d.ts.map +1 -0
- package/dist/infrastructure/read-model/shadow-read-model-store.js +25 -0
- package/dist/infrastructure/read-model/shadow-read-model-store.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { createReadStream, createWriteStream } from 'node:fs';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { pipeline } from 'node:stream/promises';
|
|
5
|
+
import { FileError } from '../../application/files/file-error.js';
|
|
6
|
+
import { mediaTypeOf } from '../../application/files/media-type-of.js';
|
|
7
|
+
import { FileInspection } from './file-inspection.js';
|
|
8
|
+
import { LocalPaths } from './local-paths.js';
|
|
9
|
+
import { isStoredMetadata } from './is-stored-metadata.js';
|
|
10
|
+
import { SelfSignedFileStorage } from './self-signed-file-storage.js';
|
|
11
|
+
/**
|
|
12
|
+
* The storage of development: a directory, each file under its key and what the file system does
|
|
13
|
+
* not know beside it in `.metadata/`. A write goes to `.incoming/` first and is renamed into place,
|
|
14
|
+
* so a failed or refused write leaves nothing under its key. One machine only: in a deployment
|
|
15
|
+
* with several instances, use an object store.
|
|
16
|
+
*/
|
|
17
|
+
export class LocalFileStorage extends SelfSignedFileStorage {
|
|
18
|
+
paths;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super(options);
|
|
21
|
+
this.paths = new LocalPaths(options.directory);
|
|
22
|
+
}
|
|
23
|
+
async put(key, content, options) {
|
|
24
|
+
const target = this.paths.contentOf(key);
|
|
25
|
+
const incoming = this.paths.incoming();
|
|
26
|
+
const inspection = new FileInspection(options.maxBytes === undefined ? {} : { maxBytes: options.maxBytes });
|
|
27
|
+
await fs.mkdir(path.dirname(incoming), { recursive: true });
|
|
28
|
+
await pipeline(content, inspection, createWriteStream(incoming)).catch(async (error) => {
|
|
29
|
+
await fs.rm(incoming, { force: true });
|
|
30
|
+
throw error;
|
|
31
|
+
});
|
|
32
|
+
const stored = {
|
|
33
|
+
key,
|
|
34
|
+
size: inspection.size,
|
|
35
|
+
mediaType: mediaTypeOf(options.mediaType),
|
|
36
|
+
checksum: inspection.checksum,
|
|
37
|
+
};
|
|
38
|
+
await this.writeMetadata(key, stored);
|
|
39
|
+
await placed(incoming, target);
|
|
40
|
+
return stored;
|
|
41
|
+
}
|
|
42
|
+
async get(key) {
|
|
43
|
+
const metadata = await this.stat(key);
|
|
44
|
+
return metadata === undefined ? undefined : { metadata, stream: createReadStream(this.paths.contentOf(key)) };
|
|
45
|
+
}
|
|
46
|
+
async stat(key) {
|
|
47
|
+
const found = await fs.stat(this.paths.contentOf(key)).catch(() => undefined);
|
|
48
|
+
if (found?.isFile() !== true) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const { mediaType, checksum } = await this.readMetadata(key);
|
|
52
|
+
return { key, size: found.size, mediaType, lastModified: found.mtime, ...(checksum === '' ? {} : { checksum }) };
|
|
53
|
+
}
|
|
54
|
+
async delete(key) {
|
|
55
|
+
await fs.rm(this.paths.contentOf(key), { force: true });
|
|
56
|
+
await fs.rm(this.paths.metadataOf(key), { force: true });
|
|
57
|
+
}
|
|
58
|
+
async copy(from, to) {
|
|
59
|
+
await this.existing(from);
|
|
60
|
+
await this.writeMetadata(to, await this.readMetadata(from));
|
|
61
|
+
await fs.mkdir(path.dirname(this.paths.contentOf(to)), { recursive: true });
|
|
62
|
+
await fs.copyFile(this.paths.contentOf(from), this.paths.contentOf(to));
|
|
63
|
+
}
|
|
64
|
+
async move(from, to) {
|
|
65
|
+
await this.existing(from);
|
|
66
|
+
await this.writeMetadata(to, await this.readMetadata(from));
|
|
67
|
+
await placed(this.paths.contentOf(from), this.paths.contentOf(to));
|
|
68
|
+
if (from !== to) {
|
|
69
|
+
await fs.rm(this.paths.metadataOf(from), { force: true });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async *list(prefix) {
|
|
73
|
+
const entries = await fs.readdir(this.paths.root, { recursive: true, withFileTypes: true }).catch(() => []);
|
|
74
|
+
for (const entry of entries.filter((found) => found.isFile())) {
|
|
75
|
+
const key = this.paths.keyOf(path.join(entry.parentPath, entry.name));
|
|
76
|
+
if (key?.startsWith(prefix) === true) {
|
|
77
|
+
const { size, mtime } = await fs.stat(this.paths.contentOf(key));
|
|
78
|
+
yield { key, size, lastModified: mtime };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async existing(key) {
|
|
83
|
+
if ((await this.stat(key)) === undefined) {
|
|
84
|
+
throw FileError.notFound(key);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async readMetadata(key) {
|
|
88
|
+
const text = await fs.readFile(this.paths.metadataOf(key), 'utf8').catch(() => '');
|
|
89
|
+
const value = text === '' ? undefined : JSON.parse(text);
|
|
90
|
+
return isStoredMetadata(value) ? value : { mediaType: 'application/octet-stream', checksum: '' };
|
|
91
|
+
}
|
|
92
|
+
async writeMetadata(key, metadata) {
|
|
93
|
+
const file = this.paths.metadataOf(key);
|
|
94
|
+
const { mediaType, checksum } = metadata;
|
|
95
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
96
|
+
await fs.writeFile(file, JSON.stringify({ mediaType, checksum }));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function placed(from, to) {
|
|
100
|
+
await fs.mkdir(path.dirname(to), { recursive: true });
|
|
101
|
+
await fs.rename(from, to);
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=local-file-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-file-storage.js","sourceRoot":"","sources":["../../../src/infrastructure/files/local-file-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Where the local storage puts a key: its content, its metadata, and a private place for a write in progress. */
|
|
2
|
+
export declare class LocalPaths {
|
|
3
|
+
readonly root: string;
|
|
4
|
+
constructor(directory: string);
|
|
5
|
+
contentOf(key: string): string;
|
|
6
|
+
metadataOf(key: string): string;
|
|
7
|
+
incoming(): string;
|
|
8
|
+
/** The key of a file found under the root, or `undefined` for what the storage keeps for itself. */
|
|
9
|
+
keyOf(file: string): string | undefined;
|
|
10
|
+
private inside;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=local-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-paths.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/local-paths.ts"],"names":[],"mappings":"AAIA,kHAAkH;AAClH,qBAAa,UAAU;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,SAAS,EAAE,MAAM,EAE5B;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7B;IAED,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9B;IAED,QAAQ,IAAI,MAAM,CAEjB;IAED,oGAAoG;IACpG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAItC;IAED,OAAO,CAAC,MAAM;CAUf"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { assertFileKey } from '../../application/files/assert-file-key.js';
|
|
4
|
+
/** Where the local storage puts a key: its content, its metadata, and a private place for a write in progress. */
|
|
5
|
+
export class LocalPaths {
|
|
6
|
+
root;
|
|
7
|
+
constructor(directory) {
|
|
8
|
+
this.root = path.resolve(directory);
|
|
9
|
+
}
|
|
10
|
+
contentOf(key) {
|
|
11
|
+
return this.inside(assertFileKey(key).split('/'));
|
|
12
|
+
}
|
|
13
|
+
metadataOf(key) {
|
|
14
|
+
return this.inside(['.metadata', ...assertFileKey(key).split('/')]) + '.json';
|
|
15
|
+
}
|
|
16
|
+
incoming() {
|
|
17
|
+
return this.inside(['.incoming', randomUUID()]);
|
|
18
|
+
}
|
|
19
|
+
/** The key of a file found under the root, or `undefined` for what the storage keeps for itself. */
|
|
20
|
+
keyOf(file) {
|
|
21
|
+
const segments = path.relative(this.root, file).split(path.sep);
|
|
22
|
+
return segments.some((segment) => segment.startsWith('.') || segment === '') ? undefined : segments.join('/');
|
|
23
|
+
}
|
|
24
|
+
inside(segments) {
|
|
25
|
+
const resolved = path.resolve(this.root, ...segments);
|
|
26
|
+
// A valid key cannot climb out; this holds the promise even if the key rules change one day.
|
|
27
|
+
if (!resolved.startsWith(this.root + path.sep)) {
|
|
28
|
+
throw new Error('A file key resolved outside the directory of the storage.');
|
|
29
|
+
}
|
|
30
|
+
return resolved;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=local-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-paths.js","sourceRoot":"","sources":["../../../src/infrastructure/files/local-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAE3E,kHAAkH;AAClH,MAAM,OAAO,UAAU;IACZ,IAAI,CAAS;IAEtB,YAAY,SAAiB;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,SAAS,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,UAAU,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAChF,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,oGAAoG;IACpG,KAAK,CAAC,IAAY;QAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEhE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChH,CAAC;IAEO,MAAM,CAAC,QAA2B;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC;QAEtD,6FAA6F;QAC7F,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Clock } from '../../application/ports/clock.js';
|
|
2
|
+
import type { ScheduledJob } from '../../application/scheduling/scheduled-job.js';
|
|
3
|
+
import type { FileStaging } from './file-staging.js';
|
|
4
|
+
/**
|
|
5
|
+
* The scheduled job of the platform that removes what rolled-back or crashed commands left in
|
|
6
|
+
* `staging/`: the files staged more than `olderThanMs` ago (a day by default). Registered under
|
|
7
|
+
* `files.purge-staged`, every hour, by the platform of a project that keeps files.
|
|
8
|
+
*/
|
|
9
|
+
export declare class PurgeStagedFiles implements ScheduledJob {
|
|
10
|
+
private readonly staging;
|
|
11
|
+
private readonly clock;
|
|
12
|
+
private readonly olderThanMs;
|
|
13
|
+
constructor(staging: FileStaging, clock: Clock, olderThanMs?: number);
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=purge-staged-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"purge-staged-files.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/purge-staged-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD;;;;GAIG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IAEjD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAH9B,YACmB,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,KAAK,EACZ,WAAW,GAAE,MAAiB,EAC7C;IAEE,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** A day: a command that staged a file has long committed or rolled back. */
|
|
2
|
+
const A_DAY_MS = 86_400_000;
|
|
3
|
+
/**
|
|
4
|
+
* The scheduled job of the platform that removes what rolled-back or crashed commands left in
|
|
5
|
+
* `staging/`: the files staged more than `olderThanMs` ago (a day by default). Registered under
|
|
6
|
+
* `files.purge-staged`, every hour, by the platform of a project that keeps files.
|
|
7
|
+
*/
|
|
8
|
+
export class PurgeStagedFiles {
|
|
9
|
+
staging;
|
|
10
|
+
clock;
|
|
11
|
+
olderThanMs;
|
|
12
|
+
constructor(staging, clock, olderThanMs = A_DAY_MS) {
|
|
13
|
+
this.staging = staging;
|
|
14
|
+
this.clock = clock;
|
|
15
|
+
this.olderThanMs = olderThanMs;
|
|
16
|
+
}
|
|
17
|
+
async run() {
|
|
18
|
+
await this.staging.purge(new Date(this.clock.now().getTime() - this.olderThanMs));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=purge-staged-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"purge-staged-files.js","sourceRoot":"","sources":["../../../src/infrastructure/files/purge-staged-files.ts"],"names":[],"mappings":"AAIA,6EAA6E;AAC7E,MAAM,QAAQ,GAAG,UAAU,CAAC;AAE5B;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IAER,OAAO;IACP,KAAK;IACL,WAAW;IAH9B,YACmB,OAAoB,EACpB,KAAY,EACZ,WAAW,GAAW,QAAQ;uBAF9B,OAAO;qBACP,KAAK;2BACL,WAAW;IAC3B,CAAC;IAEJ,KAAK,CAAC,GAAG;QACP,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACpF,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DownloadUrlOptions } from '../../application/files/download-url-options.js';
|
|
2
|
+
import type { FileSource } from '../../application/files/file-source.js';
|
|
3
|
+
import type { SignedDownload } from '../../application/files/signed-download.js';
|
|
4
|
+
import type { SignedUpload } from '../../application/files/signed-upload.js';
|
|
5
|
+
import type { SignedUrl } from '../../application/files/signed-url.js';
|
|
6
|
+
import type { StoredFile } from '../../application/files/stored-file.js';
|
|
7
|
+
import type { UploadUrlOptions } from '../../application/files/upload-url-options.js';
|
|
8
|
+
import { ServedFileStorage } from '../../application/ports/served-file-storage.js';
|
|
9
|
+
import type { SignedLinkOptions } from './signed-link-options.js';
|
|
10
|
+
/** The signed links of the storages the application serves itself: one token per link, under `baseUrl`. */
|
|
11
|
+
export declare abstract class SelfSignedFileStorage extends ServedFileStorage {
|
|
12
|
+
private readonly tokens;
|
|
13
|
+
private readonly baseUrl;
|
|
14
|
+
protected constructor(options: SignedLinkOptions);
|
|
15
|
+
signedDownloadUrl(key: string, options: DownloadUrlOptions): Promise<SignedUrl>;
|
|
16
|
+
signedUploadUrl(key: string, options: UploadUrlOptions): Promise<SignedUpload>;
|
|
17
|
+
openSigned(token: string): Promise<SignedDownload | undefined>;
|
|
18
|
+
/** Stores what a signed upload link sends, refused beyond the size the link was signed for (`FILE_TOO_LARGE`). */
|
|
19
|
+
acceptSigned(token: string, content: FileSource, mediaType: string): Promise<StoredFile | undefined>;
|
|
20
|
+
/** The token travels in the query, where no router limits its length the way it limits a path parameter. */
|
|
21
|
+
private linkOf;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=self-signed-file-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-signed-file-storage.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/self-signed-file-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAE1F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAEzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AAEnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAIlE,2GAA2G;AAC3G,8BAAsB,qBAAsB,SAAQ,iBAAiB;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAE1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,SAAS,aAAa,OAAO,EAAE,iBAAiB,EAS/C;IAED,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,CAM9E;IAED,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAW7E;IAEK,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CASnE;IAED,kHAAkH;IAC5G,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAUzG;IAED,4GAA4G;IAC5G,OAAO,CAAC,MAAM;CAGf"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { assertExpiry } from '../../application/files/assert-expiry.js';
|
|
3
|
+
import { assertFileKey } from '../../application/files/assert-file-key.js';
|
|
4
|
+
import { mediaTypeOf } from '../../application/files/media-type-of.js';
|
|
5
|
+
import { ServedFileStorage } from '../../application/ports/served-file-storage.js';
|
|
6
|
+
import { SystemClock } from '../clock/system-clock.js';
|
|
7
|
+
import { SignedFileTokens } from './signed-file-tokens.js';
|
|
8
|
+
import { withoutTrailingSlashes } from './without-trailing-slashes.js';
|
|
9
|
+
/** The signed links of the storages the application serves itself: one token per link, under `baseUrl`. */
|
|
10
|
+
export class SelfSignedFileStorage extends ServedFileStorage {
|
|
11
|
+
tokens;
|
|
12
|
+
baseUrl;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
super();
|
|
15
|
+
this.tokens = new SignedFileTokens(options.secret ?? randomBytes(32).toString('hex'), options.clock ?? new SystemClock());
|
|
16
|
+
this.baseUrl = withoutTrailingSlashes(options.baseUrl ?? 'http://localhost:3000/files');
|
|
17
|
+
}
|
|
18
|
+
signedDownloadUrl(key, options) {
|
|
19
|
+
const grant = { action: 'download', key: assertFileKey(key) };
|
|
20
|
+
const named = options.fileName === undefined ? grant : { ...grant, fileName: options.fileName };
|
|
21
|
+
const { token, expiresAt } = this.tokens.sign(named, assertExpiry(options.expiresInSeconds));
|
|
22
|
+
return Promise.resolve({ url: this.linkOf(token), expiresAt });
|
|
23
|
+
}
|
|
24
|
+
signedUploadUrl(key, options) {
|
|
25
|
+
const mediaType = mediaTypeOf(options.mediaType);
|
|
26
|
+
const grant = { action: 'upload', key: assertFileKey(key), mediaType, maxBytes: options.maxBytes };
|
|
27
|
+
const { token, expiresAt } = this.tokens.sign(grant, assertExpiry(options.expiresInSeconds));
|
|
28
|
+
return Promise.resolve({
|
|
29
|
+
url: this.linkOf(token),
|
|
30
|
+
method: 'PUT',
|
|
31
|
+
headers: { 'content-type': mediaType },
|
|
32
|
+
expiresAt,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async openSigned(token) {
|
|
36
|
+
const grant = this.tokens.verify(token, 'download');
|
|
37
|
+
const content = grant === undefined ? undefined : await this.get(grant.key);
|
|
38
|
+
if (grant?.fileName === undefined || content === undefined) {
|
|
39
|
+
return content;
|
|
40
|
+
}
|
|
41
|
+
return { ...content, fileName: grant.fileName };
|
|
42
|
+
}
|
|
43
|
+
/** Stores what a signed upload link sends, refused beyond the size the link was signed for (`FILE_TOO_LARGE`). */
|
|
44
|
+
async acceptSigned(token, content, mediaType) {
|
|
45
|
+
const grant = this.tokens.verify(token, 'upload');
|
|
46
|
+
if (grant?.mediaType === undefined || grant.mediaType !== mediaTypeOf(mediaType)) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const { key, maxBytes } = grant;
|
|
50
|
+
return this.put(key, content, { mediaType: grant.mediaType, ...(maxBytes === undefined ? {} : { maxBytes }) });
|
|
51
|
+
}
|
|
52
|
+
/** The token travels in the query, where no router limits its length the way it limits a path parameter. */
|
|
53
|
+
linkOf(token) {
|
|
54
|
+
return `${this.baseUrl}?token=${token}`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=self-signed-file-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-signed-file-storage.js","sourceRoot":"","sources":["../../../src/infrastructure/files/self-signed-file-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Clock } from '../../application/ports/clock.js';
|
|
2
|
+
import type { FileGrant } from './file-grant.js';
|
|
3
|
+
/**
|
|
4
|
+
* The tokens of the links a `ServedFileStorage` signs: the grant in base64url, a dot, and its
|
|
5
|
+
* HMAC-SHA256 under the secret. Whoever holds the token holds the grant until it expires; whoever
|
|
6
|
+
* changes a byte of it holds nothing.
|
|
7
|
+
*/
|
|
8
|
+
export declare class SignedFileTokens {
|
|
9
|
+
private readonly secret;
|
|
10
|
+
private readonly clock;
|
|
11
|
+
constructor(secret: string, clock: Clock);
|
|
12
|
+
sign(grant: Omit<FileGrant, 'expiresAt'>, expiresInSeconds: number): {
|
|
13
|
+
token: string;
|
|
14
|
+
expiresAt: Date;
|
|
15
|
+
};
|
|
16
|
+
/** The grant of a genuine, unexpired token for this action, or `undefined`. */
|
|
17
|
+
verify(token: string, action: FileGrant['action']): FileGrant | undefined;
|
|
18
|
+
private signatureOf;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=signed-file-tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signed-file-tokens.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/signed-file-tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;;;GAIG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFxB,YACmB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EAC3B;IAEJ,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,gBAAgB,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,CAKtG;IAED,+EAA+E;IAC/E,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,SAAS,CAaxE;IAED,OAAO,CAAC,WAAW;CAGpB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { isFileGrant } from './is-file-grant.js';
|
|
3
|
+
/**
|
|
4
|
+
* The tokens of the links a `ServedFileStorage` signs: the grant in base64url, a dot, and its
|
|
5
|
+
* HMAC-SHA256 under the secret. Whoever holds the token holds the grant until it expires; whoever
|
|
6
|
+
* changes a byte of it holds nothing.
|
|
7
|
+
*/
|
|
8
|
+
export class SignedFileTokens {
|
|
9
|
+
secret;
|
|
10
|
+
clock;
|
|
11
|
+
constructor(secret, clock) {
|
|
12
|
+
this.secret = secret;
|
|
13
|
+
this.clock = clock;
|
|
14
|
+
}
|
|
15
|
+
sign(grant, expiresInSeconds) {
|
|
16
|
+
const expiresAt = Math.floor(this.clock.now().getTime() / 1_000) + expiresInSeconds;
|
|
17
|
+
const payload = Buffer.from(JSON.stringify({ ...grant, expiresAt })).toString('base64url');
|
|
18
|
+
return { token: `${payload}.${this.signatureOf(payload)}`, expiresAt: new Date(expiresAt * 1_000) };
|
|
19
|
+
}
|
|
20
|
+
/** The grant of a genuine, unexpired token for this action, or `undefined`. */
|
|
21
|
+
verify(token, action) {
|
|
22
|
+
const [payload = '', signature = ''] = token.split('.');
|
|
23
|
+
const expected = Buffer.from(this.signatureOf(payload));
|
|
24
|
+
const given = Buffer.from(signature);
|
|
25
|
+
if (expected.length !== given.length || !timingSafeEqual(expected, given)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const grant = parsed(payload);
|
|
29
|
+
const now = this.clock.now().getTime() / 1_000;
|
|
30
|
+
return grant?.action === action && grant.expiresAt > now ? grant : undefined;
|
|
31
|
+
}
|
|
32
|
+
signatureOf(payload) {
|
|
33
|
+
return createHmac('sha256', this.secret).update(payload).digest('base64url');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function parsed(payload) {
|
|
37
|
+
try {
|
|
38
|
+
const value = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
|
|
39
|
+
return isFileGrant(value) ? value : undefined;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=signed-file-tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signed-file-tokens.js","sourceRoot":"","sources":["../../../src/infrastructure/files/signed-file-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IAER,MAAM;IACN,KAAK;IAFxB,YACmB,MAAc,EACd,KAAY;sBADZ,MAAM;qBACN,KAAK;IACrB,CAAC;IAEJ,IAAI,CAAC,KAAmC,EAAE,gBAAwB;QAChE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,GAAG,gBAAgB,CAAC;QACpF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAE3F,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC;IACtG,CAAC;IAED,+EAA+E;IAC/E,MAAM,CAAC,KAAa,EAAE,MAA2B;QAC/C,MAAM,CAAC,OAAO,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAErC,IAAI,QAAQ,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;YAC1E,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC;QAE/C,OAAO,KAAK,EAAE,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,CAAC;IAEO,WAAW,CAAC,OAAe;QACjC,OAAO,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC/E,CAAC;CACF;AAED,SAAS,MAAM,CAAC,OAAe;IAC7B,IAAI,CAAC;QACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAEtF,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Clock } from '../../application/ports/clock.js';
|
|
2
|
+
export interface SignedLinkOptions {
|
|
3
|
+
/** Where `signedFileRoutes` of `@ddd-ts-kit/http` answers, as a client reaches it: `http://localhost:3000/files`. A link is `<baseUrl>?token=<token>`. */
|
|
4
|
+
readonly baseUrl?: string;
|
|
5
|
+
/** Signs the links. Left out, a random one is drawn: the links then die with the process. */
|
|
6
|
+
readonly secret?: string;
|
|
7
|
+
/** Reads the expiry of the links. Default: the system clock. */
|
|
8
|
+
readonly clock?: Clock;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=signed-link-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signed-link-options.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/signed-link-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AAE9D,MAAM,WAAW,iBAAiB;IAChC,0JAA0J;IAC1J,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signed-link-options.js","sourceRoot":"","sources":["../../../src/infrastructure/files/signed-link-options.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-metadata.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/stored-metadata.ts"],"names":[],"mappings":"AAAA,2GAA2G;AAC3G,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-metadata.js","sourceRoot":"","sources":["../../../src/infrastructure/files/stored-metadata.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Clock } from '../../application/ports/clock.js';
|
|
2
|
+
import type { ExecutionScope } from '../../application/ports/execution-scope.js';
|
|
3
|
+
import type { FileKeys } from '../../application/ports/file-keys.js';
|
|
4
|
+
import type { IdGenerator } from '../../application/ports/id-generator.js';
|
|
5
|
+
/**
|
|
6
|
+
* Keys of the form `tenants/<tenant>/<area>/<year>/<month>/<id>`, the tenant segment only when
|
|
7
|
+
* the work in progress names a tenant: the files of a tenant then share a prefix that a bucket
|
|
8
|
+
* policy, an export or an erasure can address. A tenant id is a key segment as it is: the kernel
|
|
9
|
+
* refuses any other at every entry (`isTenantId`), so two tenants never share a prefix. An area that would put the key under `staging/`
|
|
10
|
+
* is refused (`INVALID_FILE_KEY`). The id comes from the `IdGenerator`, so a key is
|
|
11
|
+
* not guessable when the generator is not.
|
|
12
|
+
*/
|
|
13
|
+
export declare class TenantFileKeys implements FileKeys {
|
|
14
|
+
private readonly ids;
|
|
15
|
+
private readonly clock;
|
|
16
|
+
private readonly scope?;
|
|
17
|
+
constructor(ids: IdGenerator, clock: Clock, scope?: Pick<ExecutionScope, 'current'> | undefined);
|
|
18
|
+
next(area: string): string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=tenant-file-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-file-keys.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/tenant-file-keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAG3E;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,QAAQ;IAE3C,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;IAHzB,YACmB,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,KAAK,EACZ,KAAK,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,YAAA,EACtD;IAEJ,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOzB;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { assertFinalKey } from '../../application/files/assert-final-key.js';
|
|
2
|
+
/**
|
|
3
|
+
* Keys of the form `tenants/<tenant>/<area>/<year>/<month>/<id>`, the tenant segment only when
|
|
4
|
+
* the work in progress names a tenant: the files of a tenant then share a prefix that a bucket
|
|
5
|
+
* policy, an export or an erasure can address. A tenant id is a key segment as it is: the kernel
|
|
6
|
+
* refuses any other at every entry (`isTenantId`), so two tenants never share a prefix. An area that would put the key under `staging/`
|
|
7
|
+
* is refused (`INVALID_FILE_KEY`). The id comes from the `IdGenerator`, so a key is
|
|
8
|
+
* not guessable when the generator is not.
|
|
9
|
+
*/
|
|
10
|
+
export class TenantFileKeys {
|
|
11
|
+
ids;
|
|
12
|
+
clock;
|
|
13
|
+
scope;
|
|
14
|
+
constructor(ids, clock, scope) {
|
|
15
|
+
this.ids = ids;
|
|
16
|
+
this.clock = clock;
|
|
17
|
+
this.scope = scope;
|
|
18
|
+
}
|
|
19
|
+
next(area) {
|
|
20
|
+
const now = this.clock.now();
|
|
21
|
+
const month = String(now.getUTCMonth() + 1).padStart(2, '0');
|
|
22
|
+
const key = `${area}/${String(now.getUTCFullYear())}/${month}/${this.ids.next()}`;
|
|
23
|
+
const tenantId = this.scope?.current()?.tenantId;
|
|
24
|
+
return assertFinalKey(tenantId === undefined ? key : `tenants/${tenantId}/${key}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=tenant-file-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-file-keys.js","sourceRoot":"","sources":["../../../src/infrastructure/files/tenant-file-keys.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAE7E;;;;;;;GAOG;AACH,MAAM,OAAO,cAAc;IAEN,GAAG;IACH,KAAK;IACL,KAAK;IAHxB,YACmB,GAAgB,EAChB,KAAY,EACZ,KAAuC;mBAFvC,GAAG;qBACH,KAAK;qBACL,KAAK;IACrB,CAAC;IAEJ,IAAI,CAAC,IAAY;QACf,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAClF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,QAAQ,CAAC;QAEjD,OAAO,cAAc,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,QAAQ,IAAI,GAAG,EAAE,CAAC,CAAC;IACrF,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FileKeys } from '../../application/ports/file-keys.js';
|
|
2
|
+
import type { FileStaging } from './file-staging.js';
|
|
3
|
+
/** What `fileUploadsMiddleware` stages a file upload with: the keys of the server and the staging. */
|
|
4
|
+
export interface UploadDesk {
|
|
5
|
+
readonly keys: FileKeys;
|
|
6
|
+
readonly staging: FileStaging;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=upload-desk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-desk.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/upload-desk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,sGAAsG;AACtG,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-desk.js","sourceRoot":"","sources":["../../../src/infrastructure/files/upload-desk.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"without-trailing-slashes.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/files/without-trailing-slashes.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ5D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** `value` without the slashes it ends with. */
|
|
2
|
+
export function withoutTrailingSlashes(value) {
|
|
3
|
+
let end = value.length;
|
|
4
|
+
while (end > 0 && value[end - 1] === '/') {
|
|
5
|
+
end -= 1;
|
|
6
|
+
}
|
|
7
|
+
return value.slice(0, end);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=without-trailing-slashes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"without-trailing-slashes.js","sourceRoot":"","sources":["../../../src/infrastructure/files/without-trailing-slashes.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IAEvB,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACzC,GAAG,IAAI,CAAC,CAAC;IACX,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CheckpointStore } from '../../application/ports/checkpoint-store.js';
|
|
2
|
+
/** Reference implementation, for tests and single-process apps. */
|
|
3
|
+
export declare class InMemoryCheckpointStore implements CheckpointStore {
|
|
4
|
+
private readonly positions;
|
|
5
|
+
position(subscriber: string): Promise<number>;
|
|
6
|
+
advance(subscriber: string, from: number, to: number): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=in-memory-checkpoint-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-checkpoint-store.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/in-memory/in-memory-checkpoint-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAGnF,mEAAmE;AACnE,qBAAa,uBAAwB,YAAW,eAAe;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IAEjD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElD;IAEK,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ConcurrencyError } from '../../domain/errors/concurrency-error.js';
|
|
2
|
+
/** Reference implementation, for tests and single-process apps. */
|
|
3
|
+
export class InMemoryCheckpointStore {
|
|
4
|
+
positions = new Map();
|
|
5
|
+
async position(subscriber) {
|
|
6
|
+
return this.positions.get(subscriber) ?? 0;
|
|
7
|
+
}
|
|
8
|
+
async advance(subscriber, from, to) {
|
|
9
|
+
if ((this.positions.get(subscriber) ?? 0) !== from) {
|
|
10
|
+
throw new ConcurrencyError(subscriber);
|
|
11
|
+
}
|
|
12
|
+
this.positions.set(subscriber, to);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=in-memory-checkpoint-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-checkpoint-store.js","sourceRoot":"","sources":["../../../src/infrastructure/in-memory/in-memory-checkpoint-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAE5E,mEAAmE;AACnE,MAAM,OAAO,uBAAuB;IACjB,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvD,KAAK,CAAC,QAAQ,CAAC,UAAkB;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAkB,EAAE,IAAY,EAAE,EAAU;QACxD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACnD,MAAM,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Appended } from '../../application/event-sourcing/appended.js';
|
|
2
|
+
import type { EventToAppend } from '../../application/event-sourcing/event-to-append.js';
|
|
3
|
+
import type { StoredEvent } from '../../application/event-sourcing/stored-event.js';
|
|
4
|
+
import type { EventStore } from '../../application/ports/event-store.js';
|
|
5
|
+
/** Reference implementation, for tests and single-process apps. Not transactional: a failed unit of work keeps what it appended. */
|
|
6
|
+
export declare class InMemoryEventStore implements EventStore {
|
|
7
|
+
private readonly events;
|
|
8
|
+
append(stream: string, expectedVersion: number, events: readonly EventToAppend[]): Promise<Appended>;
|
|
9
|
+
readStream(stream: string, after?: number): Promise<readonly StoredEvent[]>;
|
|
10
|
+
readAll(after: number, limit: number): Promise<readonly StoredEvent[]>;
|
|
11
|
+
head(): Promise<number>;
|
|
12
|
+
private versionOf;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=in-memory-event-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-event-store.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/in-memory/in-memory-event-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8CAA8C,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGzE,oIAAoI;AACpI,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAEtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoBzG;IAEK,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAE3E;IAEK,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAE3E;IAEK,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAE5B;IAED,OAAO,CAAC,SAAS;CAGlB"}
|