@farukada/aws-langgraph-dynamodb-ts 0.8.0 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +282 -49
- package/dist/checkpointer/actions/delete-thread.d.ts +3 -2
- package/dist/checkpointer/actions/delete-thread.js +5 -2
- package/dist/checkpointer/actions/get-tuple.d.ts +3 -2
- package/dist/checkpointer/actions/get-tuple.js +10 -4
- package/dist/checkpointer/actions/list.d.ts +14 -4
- package/dist/checkpointer/actions/list.js +94 -61
- package/dist/checkpointer/actions/put-writes.d.ts +5 -5
- package/dist/checkpointer/actions/put-writes.js +12 -40
- package/dist/checkpointer/actions/put.d.ts +10 -3
- package/dist/checkpointer/actions/put.js +42 -12
- package/dist/checkpointer/internal/assemble.d.ts +10 -3
- package/dist/checkpointer/internal/assemble.js +7 -6
- package/dist/checkpointer/internal/checkpoint-write-verify.d.ts +24 -0
- package/dist/checkpointer/internal/checkpoint-write-verify.js +67 -0
- package/dist/checkpointer/internal/configurable.d.ts +0 -1
- package/dist/checkpointer/internal/configurable.js +10 -9
- package/dist/checkpointer/internal/fetch.d.ts +14 -5
- package/dist/checkpointer/internal/fetch.js +56 -14
- package/dist/checkpointer/internal/filter-match.d.ts +3 -2
- package/dist/checkpointer/internal/filter-match.js +4 -3
- package/dist/checkpointer/internal/item-reader.d.ts +31 -6
- package/dist/checkpointer/internal/item-reader.js +54 -15
- package/dist/checkpointer/internal/item-writer.d.ts +12 -3
- package/dist/checkpointer/internal/item-writer.js +26 -10
- package/dist/checkpointer/internal/keys.d.ts +11 -1
- package/dist/checkpointer/internal/keys.js +33 -3
- package/dist/checkpointer/internal/list-scope.d.ts +61 -0
- package/dist/checkpointer/internal/list-scope.js +108 -0
- package/dist/checkpointer/internal/pending-sends.d.ts +13 -0
- package/dist/checkpointer/internal/pending-sends.js +29 -0
- package/dist/checkpointer/internal/query.d.ts +2 -1
- package/dist/checkpointer/internal/query.js +9 -3
- package/dist/checkpointer/internal/regular-write.d.ts +28 -0
- package/dist/checkpointer/internal/regular-write.js +66 -0
- package/dist/checkpointer/internal/setup.d.ts +3 -1
- package/dist/checkpointer/internal/setup.js +10 -8
- package/dist/checkpointer/internal/special-write-cas.d.ts +29 -0
- package/dist/checkpointer/internal/special-write-cas.js +104 -0
- package/dist/checkpointer/internal/special-write-cleanup.d.ts +19 -14
- package/dist/checkpointer/internal/special-write-cleanup.js +35 -87
- package/dist/checkpointer/internal/special-write-verify.d.ts +53 -0
- package/dist/checkpointer/internal/special-write-verify.js +80 -0
- package/dist/checkpointer/internal/stored-channels.d.ts +31 -0
- package/dist/checkpointer/internal/stored-channels.js +70 -0
- package/dist/checkpointer/internal/validation.d.ts +11 -6
- package/dist/checkpointer/internal/validation.js +19 -9
- package/dist/checkpointer/internal/write-guard.d.ts +8 -9
- package/dist/checkpointer/internal/write-guard.js +16 -16
- package/dist/checkpointer/internal/write-index.d.ts +8 -1
- package/dist/checkpointer/internal/write-index.js +6 -3
- package/dist/checkpointer/saver.d.ts +50 -10
- package/dist/checkpointer/saver.js +59 -17
- package/dist/checkpointer/types.d.ts +14 -1
- package/dist/checkpointer/types.js +0 -1
- package/dist/factory/factory.d.ts +22 -25
- package/dist/factory/factory.js +58 -18
- package/dist/factory/types.d.ts +57 -0
- package/dist/factory/types.js +2 -0
- package/dist/history/actions/add-messages.d.ts +1 -2
- package/dist/history/actions/add-messages.js +4 -4
- package/dist/history/actions/clear.d.ts +3 -2
- package/dist/history/actions/clear.js +5 -2
- package/dist/history/actions/get-messages.d.ts +13 -6
- package/dist/history/actions/get-messages.js +63 -42
- package/dist/history/actions/list-sessions.d.ts +1 -1
- package/dist/history/actions/list-sessions.js +8 -12
- package/dist/history/actions/reconcile-count.d.ts +1 -2
- package/dist/history/actions/reconcile-count.js +20 -7
- package/dist/history/chat-message-history.d.ts +51 -26
- package/dist/history/chat-message-history.js +60 -30
- package/dist/history/internal/append-saga.d.ts +7 -2
- package/dist/history/internal/append-saga.js +58 -14
- package/dist/history/internal/compensation.d.ts +6 -2
- package/dist/history/internal/compensation.js +14 -6
- package/dist/history/internal/item-mapper.d.ts +0 -3
- package/dist/history/internal/item-mapper.js +2 -8
- package/dist/history/internal/keys.d.ts +0 -1
- package/dist/history/internal/keys.js +0 -1
- package/dist/history/internal/message-chunker.d.ts +0 -1
- package/dist/history/internal/message-chunker.js +0 -1
- package/dist/history/internal/message-transaction.d.ts +0 -1
- package/dist/history/internal/message-transaction.js +3 -2
- package/dist/history/internal/message-window.d.ts +17 -0
- package/dist/history/internal/message-window.js +49 -0
- package/dist/history/internal/query.d.ts +16 -3
- package/dist/history/internal/query.js +13 -5
- package/dist/history/internal/session-count.d.ts +8 -2
- package/dist/history/internal/session-count.js +14 -8
- package/dist/history/internal/session-title.d.ts +0 -1
- package/dist/history/internal/session-title.js +1 -2
- package/dist/history/internal/session-update.d.ts +0 -1
- package/dist/history/internal/session-update.js +0 -1
- package/dist/history/internal/setup.d.ts +3 -1
- package/dist/history/internal/setup.js +16 -8
- package/dist/history/internal/title-generator.d.ts +0 -1
- package/dist/history/internal/title-generator.js +19 -3
- package/dist/history/internal/ttl-anchor.d.ts +1 -2
- package/dist/history/internal/ttl-anchor.js +5 -5
- package/dist/history/internal/validation.d.ts +19 -3
- package/dist/history/internal/validation.js +41 -4
- package/dist/history/session-adapter.d.ts +9 -3
- package/dist/history/session-adapter.js +6 -3
- package/dist/history/types.d.ts +23 -2
- package/dist/history/types.js +0 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +5 -3
- package/dist/shared/clock.d.ts +6 -1
- package/dist/shared/clock.js +9 -1
- package/dist/shared/codec/codec.d.ts +26 -17
- package/dist/shared/codec/codec.js +46 -24
- package/dist/shared/codec/compression.d.ts +1 -2
- package/dist/shared/codec/compression.js +2 -3
- package/dist/shared/codec/descriptor-keys.d.ts +11 -3
- package/dist/shared/codec/descriptor-keys.js +2 -2
- package/dist/shared/codec/encode.d.ts +13 -0
- package/dist/shared/codec/encode.js +43 -0
- package/dist/shared/codec/json-serde.d.ts +0 -1
- package/dist/shared/codec/json-serde.js +0 -1
- package/dist/shared/codec/payload-loss.d.ts +12 -0
- package/dist/shared/codec/payload-loss.js +38 -0
- package/dist/shared/codec/s3/adapter-config.d.ts +13 -0
- package/dist/shared/codec/s3/adapter-config.js +22 -0
- package/dist/shared/codec/s3/bounded-body.d.ts +14 -0
- package/dist/shared/codec/s3/bounded-body.js +47 -0
- package/dist/shared/codec/s3/client-types.d.ts +34 -0
- package/dist/shared/codec/s3/client-types.js +7 -0
- package/dist/shared/codec/s3/client.d.ts +11 -5
- package/dist/shared/codec/s3/client.js +25 -3
- package/dist/shared/codec/s3/config.d.ts +32 -5
- package/dist/shared/codec/s3/config.js +37 -5
- package/dist/shared/codec/s3/delete.d.ts +0 -1
- package/dist/shared/codec/s3/delete.js +0 -1
- package/dist/shared/codec/s3/key-scope.d.ts +23 -0
- package/dist/shared/codec/s3/key-scope.js +44 -0
- package/dist/shared/codec/s3/lifecycle.d.ts +11 -5
- package/dist/shared/codec/s3/lifecycle.js +32 -16
- package/dist/shared/codec/s3/offloader.d.ts +6 -2
- package/dist/shared/codec/s3/offloader.js +21 -3
- package/dist/shared/codec/s3/orphans.d.ts +6 -1
- package/dist/shared/codec/s3/orphans.js +15 -2
- package/dist/shared/codec/s3/read-write.d.ts +7 -3
- package/dist/shared/codec/s3/read-write.js +16 -8
- package/dist/shared/codec/s3/retry.d.ts +4 -4
- package/dist/shared/codec/s3/retry.js +13 -16
- package/dist/shared/concurrency.d.ts +6 -0
- package/dist/shared/concurrency.js +30 -0
- package/dist/shared/constants.d.ts +68 -5
- package/dist/shared/constants.js +70 -7
- package/dist/shared/dynamodb/abort.d.ts +9 -0
- package/dist/shared/dynamodb/abort.js +27 -0
- package/dist/shared/dynamodb/backoff.d.ts +4 -4
- package/dist/shared/dynamodb/backoff.js +7 -7
- package/dist/shared/dynamodb/batch-write.d.ts +0 -1
- package/dist/shared/dynamodb/batch-write.js +0 -1
- package/dist/shared/dynamodb/cancellation.d.ts +0 -1
- package/dist/shared/dynamodb/cancellation.js +0 -1
- package/dist/shared/dynamodb/client.d.ts +9 -2
- package/dist/shared/dynamodb/client.js +24 -1
- package/dist/shared/dynamodb/conditional-put.d.ts +67 -0
- package/dist/shared/dynamodb/conditional-put.js +76 -0
- package/dist/shared/dynamodb/drain-unprocessed.d.ts +3 -1
- package/dist/shared/dynamodb/drain-unprocessed.js +1 -2
- package/dist/shared/dynamodb/expiry.d.ts +16 -0
- package/dist/shared/dynamodb/expiry.js +29 -0
- package/dist/shared/dynamodb/paginate-core.d.ts +5 -3
- package/dist/shared/dynamodb/paginate-core.js +47 -17
- package/dist/shared/dynamodb/paginate.d.ts +0 -1
- package/dist/shared/dynamodb/paginate.js +1 -2
- package/dist/shared/dynamodb/partition-delete.d.ts +7 -1
- package/dist/shared/dynamodb/partition-delete.js +4 -3
- package/dist/shared/dynamodb/retry-classifier.d.ts +10 -2
- package/dist/shared/dynamodb/retry-classifier.js +42 -11
- package/dist/shared/dynamodb/retry-policy.d.ts +26 -0
- package/dist/shared/dynamodb/retry-policy.js +22 -0
- package/dist/shared/dynamodb/retry.d.ts +14 -1
- package/dist/shared/dynamodb/retry.js +11 -7
- package/dist/shared/dynamodb/scan.d.ts +0 -1
- package/dist/shared/dynamodb/scan.js +1 -2
- package/dist/shared/dynamodb/types.d.ts +1 -2
- package/dist/shared/dynamodb/types.js +0 -1
- package/dist/shared/errors/base-error.d.ts +14 -6
- package/dist/shared/errors/base-error.js +8 -9
- package/dist/shared/errors/boundary.d.ts +18 -0
- package/dist/shared/errors/boundary.js +46 -0
- package/dist/shared/errors/error-code.d.ts +2 -2
- package/dist/shared/errors/error-code.js +1 -1
- package/dist/shared/errors/errors.d.ts +13 -13
- package/dist/shared/errors/errors.js +18 -16
- package/dist/shared/errors/upstream-error.d.ts +16 -0
- package/dist/shared/errors/upstream-error.js +27 -0
- package/dist/shared/errors/wrap-error.d.ts +0 -9
- package/dist/shared/errors/wrap-error.js +0 -15
- package/dist/shared/logging/logger.d.ts +6 -2
- package/dist/shared/logging/logger.js +0 -1
- package/dist/shared/logging/redaction-walk.d.ts +2 -2
- package/dist/shared/logging/redaction-walk.js +38 -18
- package/dist/shared/logging/redaction.d.ts +14 -6
- package/dist/shared/logging/redaction.js +19 -4
- package/dist/shared/logging/secret-patterns.d.ts +54 -3
- package/dist/shared/logging/secret-patterns.js +67 -8
- package/dist/shared/options.d.ts +9 -4
- package/dist/shared/options.js +0 -1
- package/dist/shared/ulid.d.ts +15 -2
- package/dist/shared/ulid.js +35 -3
- package/dist/shared/validation/options.d.ts +8 -0
- package/dist/shared/validation/options.js +90 -0
- package/dist/shared/validation/primitives.d.ts +14 -10
- package/dist/shared/validation/primitives.js +23 -25
- package/dist/shared/validation/ttl.d.ts +14 -7
- package/dist/shared/validation/ttl.js +29 -11
- package/dist/store/actions/get.d.ts +11 -3
- package/dist/store/actions/get.js +52 -14
- package/dist/store/actions/list-namespaces.d.ts +0 -1
- package/dist/store/actions/list-namespaces.js +10 -6
- package/dist/store/actions/put.d.ts +0 -1
- package/dist/store/actions/put.js +27 -28
- package/dist/store/actions/reconcile-vector-index.d.ts +3 -2
- package/dist/store/actions/reconcile-vector-index.js +2 -3
- package/dist/store/actions/search.d.ts +1 -2
- package/dist/store/actions/search.js +11 -38
- package/dist/store/internal/backend-search.d.ts +1 -2
- package/dist/store/internal/backend-search.js +14 -7
- package/dist/store/internal/batch-plan.d.ts +11 -0
- package/dist/store/internal/batch-plan.js +52 -0
- package/dist/store/internal/candidates.d.ts +23 -0
- package/dist/store/internal/candidates.js +94 -0
- package/dist/store/internal/filter.d.ts +0 -1
- package/dist/store/internal/filter.js +25 -6
- package/dist/store/internal/index-reconcile.d.ts +5 -6
- package/dist/store/internal/index-reconcile.js +32 -13
- package/dist/store/internal/index-sync.d.ts +0 -1
- package/dist/store/internal/index-sync.js +0 -1
- package/dist/store/internal/item-mapper.d.ts +6 -3
- package/dist/store/internal/item-mapper.js +16 -6
- package/dist/store/internal/keys.d.ts +0 -1
- package/dist/store/internal/keys.js +0 -1
- package/dist/store/internal/namespace-match.d.ts +0 -1
- package/dist/store/internal/namespace-match.js +0 -1
- package/dist/store/internal/option-validation.d.ts +13 -0
- package/dist/store/internal/option-validation.js +77 -0
- package/dist/store/internal/overwrite-swap.d.ts +32 -0
- package/dist/store/internal/overwrite-swap.js +68 -0
- package/dist/store/internal/persist.d.ts +24 -7
- package/dist/store/internal/persist.js +49 -19
- package/dist/store/internal/query.d.ts +6 -1
- package/dist/store/internal/query.js +17 -1
- package/dist/store/internal/ranker.d.ts +7 -2
- package/dist/store/internal/ranker.js +10 -2
- package/dist/store/internal/read-existing.d.ts +23 -0
- package/dist/store/internal/read-existing.js +41 -0
- package/dist/store/internal/score-direction.d.ts +31 -0
- package/dist/store/internal/score-direction.js +38 -0
- package/dist/store/internal/search-filter.d.ts +0 -1
- package/dist/store/internal/search-filter.js +0 -1
- package/dist/store/internal/semantic-search.d.ts +26 -5
- package/dist/store/internal/semantic-search.js +59 -19
- package/dist/store/internal/setup.d.ts +6 -12
- package/dist/store/internal/setup.js +12 -24
- package/dist/store/internal/text-path.d.ts +17 -0
- package/dist/store/internal/text-path.js +147 -0
- package/dist/store/internal/validation.d.ts +8 -3
- package/dist/store/internal/validation.js +21 -5
- package/dist/store/internal/write-verify.d.ts +27 -9
- package/dist/store/internal/write-verify.js +35 -19
- package/dist/store/store.d.ts +37 -9
- package/dist/store/store.js +52 -17
- package/dist/store/types.d.ts +22 -2
- package/dist/store/types.js +0 -1
- package/dist/store/vector-backend.d.ts +6 -7
- package/dist/store/vector-backend.js +0 -1
- package/package.json +21 -15
- package/dist/checkpointer/actions/delete-thread.d.ts.map +0 -1
- package/dist/checkpointer/actions/delete-thread.js.map +0 -1
- package/dist/checkpointer/actions/get-tuple.d.ts.map +0 -1
- package/dist/checkpointer/actions/get-tuple.js.map +0 -1
- package/dist/checkpointer/actions/list.d.ts.map +0 -1
- package/dist/checkpointer/actions/list.js.map +0 -1
- package/dist/checkpointer/actions/put-writes.d.ts.map +0 -1
- package/dist/checkpointer/actions/put-writes.js.map +0 -1
- package/dist/checkpointer/actions/put.d.ts.map +0 -1
- package/dist/checkpointer/actions/put.js.map +0 -1
- package/dist/checkpointer/internal/assemble.d.ts.map +0 -1
- package/dist/checkpointer/internal/assemble.js.map +0 -1
- package/dist/checkpointer/internal/configurable.d.ts.map +0 -1
- package/dist/checkpointer/internal/configurable.js.map +0 -1
- package/dist/checkpointer/internal/fetch.d.ts.map +0 -1
- package/dist/checkpointer/internal/fetch.js.map +0 -1
- package/dist/checkpointer/internal/filter-match.d.ts.map +0 -1
- package/dist/checkpointer/internal/filter-match.js.map +0 -1
- package/dist/checkpointer/internal/item-reader.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-reader.js.map +0 -1
- package/dist/checkpointer/internal/item-writer.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-writer.js.map +0 -1
- package/dist/checkpointer/internal/keys.d.ts.map +0 -1
- package/dist/checkpointer/internal/keys.js.map +0 -1
- package/dist/checkpointer/internal/query.d.ts.map +0 -1
- package/dist/checkpointer/internal/query.js.map +0 -1
- package/dist/checkpointer/internal/setup.d.ts.map +0 -1
- package/dist/checkpointer/internal/setup.js.map +0 -1
- package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-cleanup.js.map +0 -1
- package/dist/checkpointer/internal/validation.d.ts.map +0 -1
- package/dist/checkpointer/internal/validation.js.map +0 -1
- package/dist/checkpointer/internal/write-guard.d.ts.map +0 -1
- package/dist/checkpointer/internal/write-guard.js.map +0 -1
- package/dist/checkpointer/internal/write-index.d.ts.map +0 -1
- package/dist/checkpointer/internal/write-index.js.map +0 -1
- package/dist/checkpointer/saver.d.ts.map +0 -1
- package/dist/checkpointer/saver.js.map +0 -1
- package/dist/checkpointer/types.d.ts.map +0 -1
- package/dist/checkpointer/types.js.map +0 -1
- package/dist/factory/factory.d.ts.map +0 -1
- package/dist/factory/factory.js.map +0 -1
- package/dist/history/actions/add-messages.d.ts.map +0 -1
- package/dist/history/actions/add-messages.js.map +0 -1
- package/dist/history/actions/clear.d.ts.map +0 -1
- package/dist/history/actions/clear.js.map +0 -1
- package/dist/history/actions/get-messages.d.ts.map +0 -1
- package/dist/history/actions/get-messages.js.map +0 -1
- package/dist/history/actions/list-sessions.d.ts.map +0 -1
- package/dist/history/actions/list-sessions.js.map +0 -1
- package/dist/history/actions/reconcile-count.d.ts.map +0 -1
- package/dist/history/actions/reconcile-count.js.map +0 -1
- package/dist/history/chat-message-history.d.ts.map +0 -1
- package/dist/history/chat-message-history.js.map +0 -1
- package/dist/history/internal/append-saga.d.ts.map +0 -1
- package/dist/history/internal/append-saga.js.map +0 -1
- package/dist/history/internal/compensation.d.ts.map +0 -1
- package/dist/history/internal/compensation.js.map +0 -1
- package/dist/history/internal/item-mapper.d.ts.map +0 -1
- package/dist/history/internal/item-mapper.js.map +0 -1
- package/dist/history/internal/keys.d.ts.map +0 -1
- package/dist/history/internal/keys.js.map +0 -1
- package/dist/history/internal/message-chunker.d.ts.map +0 -1
- package/dist/history/internal/message-chunker.js.map +0 -1
- package/dist/history/internal/message-transaction.d.ts.map +0 -1
- package/dist/history/internal/message-transaction.js.map +0 -1
- package/dist/history/internal/query.d.ts.map +0 -1
- package/dist/history/internal/query.js.map +0 -1
- package/dist/history/internal/session-count.d.ts.map +0 -1
- package/dist/history/internal/session-count.js.map +0 -1
- package/dist/history/internal/session-title.d.ts.map +0 -1
- package/dist/history/internal/session-title.js.map +0 -1
- package/dist/history/internal/session-update.d.ts.map +0 -1
- package/dist/history/internal/session-update.js.map +0 -1
- package/dist/history/internal/setup.d.ts.map +0 -1
- package/dist/history/internal/setup.js.map +0 -1
- package/dist/history/internal/title-generator.d.ts.map +0 -1
- package/dist/history/internal/title-generator.js.map +0 -1
- package/dist/history/internal/ttl-anchor.d.ts.map +0 -1
- package/dist/history/internal/ttl-anchor.js.map +0 -1
- package/dist/history/internal/validation.d.ts.map +0 -1
- package/dist/history/internal/validation.js.map +0 -1
- package/dist/history/session-adapter.d.ts.map +0 -1
- package/dist/history/session-adapter.js.map +0 -1
- package/dist/history/types.d.ts.map +0 -1
- package/dist/history/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/shared/clock.d.ts.map +0 -1
- package/dist/shared/clock.js.map +0 -1
- package/dist/shared/codec/codec.d.ts.map +0 -1
- package/dist/shared/codec/codec.js.map +0 -1
- package/dist/shared/codec/compression.d.ts.map +0 -1
- package/dist/shared/codec/compression.js.map +0 -1
- package/dist/shared/codec/descriptor-keys.d.ts.map +0 -1
- package/dist/shared/codec/descriptor-keys.js.map +0 -1
- package/dist/shared/codec/json-serde.d.ts.map +0 -1
- package/dist/shared/codec/json-serde.js.map +0 -1
- package/dist/shared/codec/s3/client.d.ts.map +0 -1
- package/dist/shared/codec/s3/client.js.map +0 -1
- package/dist/shared/codec/s3/config.d.ts.map +0 -1
- package/dist/shared/codec/s3/config.js.map +0 -1
- package/dist/shared/codec/s3/delete.d.ts.map +0 -1
- package/dist/shared/codec/s3/delete.js.map +0 -1
- package/dist/shared/codec/s3/lifecycle.d.ts.map +0 -1
- package/dist/shared/codec/s3/lifecycle.js.map +0 -1
- package/dist/shared/codec/s3/offloader.d.ts.map +0 -1
- package/dist/shared/codec/s3/offloader.js.map +0 -1
- package/dist/shared/codec/s3/orphans.d.ts.map +0 -1
- package/dist/shared/codec/s3/orphans.js.map +0 -1
- package/dist/shared/codec/s3/read-write.d.ts.map +0 -1
- package/dist/shared/codec/s3/read-write.js.map +0 -1
- package/dist/shared/codec/s3/retry.d.ts.map +0 -1
- package/dist/shared/codec/s3/retry.js.map +0 -1
- package/dist/shared/constants.d.ts.map +0 -1
- package/dist/shared/constants.js.map +0 -1
- package/dist/shared/dynamodb/backoff.d.ts.map +0 -1
- package/dist/shared/dynamodb/backoff.js.map +0 -1
- package/dist/shared/dynamodb/batch-write.d.ts.map +0 -1
- package/dist/shared/dynamodb/batch-write.js.map +0 -1
- package/dist/shared/dynamodb/cancellation.d.ts.map +0 -1
- package/dist/shared/dynamodb/cancellation.js.map +0 -1
- package/dist/shared/dynamodb/client.d.ts.map +0 -1
- package/dist/shared/dynamodb/client.js.map +0 -1
- package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +0 -1
- package/dist/shared/dynamodb/drain-unprocessed.js.map +0 -1
- package/dist/shared/dynamodb/paginate-core.d.ts.map +0 -1
- package/dist/shared/dynamodb/paginate-core.js.map +0 -1
- package/dist/shared/dynamodb/paginate.d.ts.map +0 -1
- package/dist/shared/dynamodb/paginate.js.map +0 -1
- package/dist/shared/dynamodb/partition-delete.d.ts.map +0 -1
- package/dist/shared/dynamodb/partition-delete.js.map +0 -1
- package/dist/shared/dynamodb/retry-classifier.d.ts.map +0 -1
- package/dist/shared/dynamodb/retry-classifier.js.map +0 -1
- package/dist/shared/dynamodb/retry.d.ts.map +0 -1
- package/dist/shared/dynamodb/retry.js.map +0 -1
- package/dist/shared/dynamodb/scan.d.ts.map +0 -1
- package/dist/shared/dynamodb/scan.js.map +0 -1
- package/dist/shared/dynamodb/types.d.ts.map +0 -1
- package/dist/shared/dynamodb/types.js.map +0 -1
- package/dist/shared/errors/base-error.d.ts.map +0 -1
- package/dist/shared/errors/base-error.js.map +0 -1
- package/dist/shared/errors/error-code.d.ts.map +0 -1
- package/dist/shared/errors/error-code.js.map +0 -1
- package/dist/shared/errors/errors.d.ts.map +0 -1
- package/dist/shared/errors/errors.js.map +0 -1
- package/dist/shared/errors/wrap-error.d.ts.map +0 -1
- package/dist/shared/errors/wrap-error.js.map +0 -1
- package/dist/shared/logging/logger.d.ts.map +0 -1
- package/dist/shared/logging/logger.js.map +0 -1
- package/dist/shared/logging/redaction-walk.d.ts.map +0 -1
- package/dist/shared/logging/redaction-walk.js.map +0 -1
- package/dist/shared/logging/redaction.d.ts.map +0 -1
- package/dist/shared/logging/redaction.js.map +0 -1
- package/dist/shared/logging/secret-patterns.d.ts.map +0 -1
- package/dist/shared/logging/secret-patterns.js.map +0 -1
- package/dist/shared/options.d.ts.map +0 -1
- package/dist/shared/options.js.map +0 -1
- package/dist/shared/ulid.d.ts.map +0 -1
- package/dist/shared/ulid.js.map +0 -1
- package/dist/shared/validation/primitives.d.ts.map +0 -1
- package/dist/shared/validation/primitives.js.map +0 -1
- package/dist/shared/validation/ttl.d.ts.map +0 -1
- package/dist/shared/validation/ttl.js.map +0 -1
- package/dist/store/actions/get.d.ts.map +0 -1
- package/dist/store/actions/get.js.map +0 -1
- package/dist/store/actions/list-namespaces.d.ts.map +0 -1
- package/dist/store/actions/list-namespaces.js.map +0 -1
- package/dist/store/actions/put.d.ts.map +0 -1
- package/dist/store/actions/put.js.map +0 -1
- package/dist/store/actions/reconcile-vector-index.d.ts.map +0 -1
- package/dist/store/actions/reconcile-vector-index.js.map +0 -1
- package/dist/store/actions/search.d.ts.map +0 -1
- package/dist/store/actions/search.js.map +0 -1
- package/dist/store/internal/backend-search.d.ts.map +0 -1
- package/dist/store/internal/backend-search.js.map +0 -1
- package/dist/store/internal/filter.d.ts.map +0 -1
- package/dist/store/internal/filter.js.map +0 -1
- package/dist/store/internal/index-reconcile.d.ts.map +0 -1
- package/dist/store/internal/index-reconcile.js.map +0 -1
- package/dist/store/internal/index-sync.d.ts.map +0 -1
- package/dist/store/internal/index-sync.js.map +0 -1
- package/dist/store/internal/item-mapper.d.ts.map +0 -1
- package/dist/store/internal/item-mapper.js.map +0 -1
- package/dist/store/internal/keys.d.ts.map +0 -1
- package/dist/store/internal/keys.js.map +0 -1
- package/dist/store/internal/namespace-match.d.ts.map +0 -1
- package/dist/store/internal/namespace-match.js.map +0 -1
- package/dist/store/internal/persist.d.ts.map +0 -1
- package/dist/store/internal/persist.js.map +0 -1
- package/dist/store/internal/query.d.ts.map +0 -1
- package/dist/store/internal/query.js.map +0 -1
- package/dist/store/internal/ranker.d.ts.map +0 -1
- package/dist/store/internal/ranker.js.map +0 -1
- package/dist/store/internal/search-filter.d.ts.map +0 -1
- package/dist/store/internal/search-filter.js.map +0 -1
- package/dist/store/internal/semantic-search.d.ts.map +0 -1
- package/dist/store/internal/semantic-search.js.map +0 -1
- package/dist/store/internal/setup.d.ts.map +0 -1
- package/dist/store/internal/setup.js.map +0 -1
- package/dist/store/internal/validation.d.ts.map +0 -1
- package/dist/store/internal/validation.js.map +0 -1
- package/dist/store/internal/write-verify.d.ts.map +0 -1
- package/dist/store/internal/write-verify.js.map +0 -1
- package/dist/store/store.d.ts.map +0 -1
- package/dist/store/store.js.map +0 -1
- package/dist/store/types.d.ts.map +0 -1
- package/dist/store/types.js.map +0 -1
- package/dist/store/vector-backend.d.ts.map +0 -1
- package/dist/store/vector-backend.js.map +0 -1
|
@@ -1,22 +1,74 @@
|
|
|
1
1
|
/** Marker substituted for anything recognised as secret. */
|
|
2
2
|
export declare const REDACTED = "[REDACTED]";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Key names whose value is a secret. Each entry is a *normalised* name — see
|
|
5
|
+
* {@link normaliseKey} — and matches a key whose normalised form equals it or
|
|
6
|
+
* ends with it. Suffix matching is what catches `secretAccessKey`, `x-api-key`,
|
|
7
|
+
* `client_secret` and `AUTH_TOKEN`; requiring the pattern to be a suffix, not a
|
|
8
|
+
* substring, is what spares `maxTokens`, `total_tokens`, `tokenizer` and
|
|
9
|
+
* `secretary`, which the old substring rule redacted.
|
|
10
|
+
*/
|
|
4
11
|
export declare const DEFAULT_SECRET_KEY_PATTERNS: readonly string[];
|
|
12
|
+
/**
|
|
13
|
+
* Canonical form of a key name for matching: lower-case with every character
|
|
14
|
+
* that is not a letter or digit removed, so `api_key`, `x-api-key`, `ApiKey`
|
|
15
|
+
* and `API KEY` all become `apikey`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function normaliseKey(key: string): string;
|
|
5
18
|
/**
|
|
6
19
|
* Secret shapes recognisable in free text, where key-name matching cannot
|
|
7
20
|
* reach: an error's `message`/`stack`, or any other string value. Deliberately
|
|
8
21
|
* high-confidence — each pattern describes a credential *format* rather than a
|
|
9
22
|
* word that merely sounds sensitive — so ordinary operational text survives
|
|
10
23
|
* redaction unchanged.
|
|
24
|
+
*
|
|
25
|
+
* The credential-pair pattern (last) tolerates a **closing quote after the
|
|
26
|
+
* keyword**, because that is what `JSON.stringify` produces
|
|
27
|
+
* (`{"password":"…"}`) and requiring the separator to follow the bare keyword
|
|
28
|
+
* matched nothing at all there — a silent, complete bypass on the single most
|
|
29
|
+
* common shape a downstream HTTP error arrives in. Its group 1 is the keyword
|
|
30
|
+
* and separator, preserved by {@link redactText}.
|
|
31
|
+
*
|
|
32
|
+
* Its value side tries three shapes, and their order is load-bearing:
|
|
33
|
+
* 1. a fully-quoted span that consumes escapes, so `{"password":"a\"b"}` is
|
|
34
|
+
* redacted whole. Ending the span at the escaped quote stopped the
|
|
35
|
+
* redaction short and printed the rest of the secret verbatim.
|
|
36
|
+
* 2. an unquoted JSON scalar — number, `true`, `false`, `null` — required to
|
|
37
|
+
* end at a real delimiter — `,`, `}`, `]` or end of input, optionally
|
|
38
|
+
* preceded by whitespace. Without this alternative,
|
|
39
|
+
* `{"apiKey":123,"region":"us-east-1"}` fell through to the fallback below,
|
|
40
|
+
* which then destroyed every sibling field after the secret. The lookahead
|
|
41
|
+
* is what stops the alternative truncating a value it does not fully
|
|
42
|
+
* describe, such as `token=123abc`, and leaking the tail it left behind.
|
|
43
|
+
* Whitespace alone does not end a scalar: treating a space as a delimiter
|
|
44
|
+
* made `api_key: 5 items` redact to `api_key: [REDACTED] items`, which
|
|
45
|
+
* reads as a partial redaction of a value the pattern never described.
|
|
46
|
+
* 3. the rest of the line, so a multi-word secret is redacted whole instead of
|
|
47
|
+
* up to its first space. Trying the two precise shapes first is what keeps
|
|
48
|
+
* this fallback from over-redacting sibling JSON fields.
|
|
11
49
|
*/
|
|
12
50
|
export declare const DEFAULT_SECRET_VALUE_PATTERNS: readonly RegExp[];
|
|
13
|
-
/** True when `key`
|
|
51
|
+
/** True when `key`'s normalised form equals or ends with any (normalised) pattern. */
|
|
14
52
|
export declare function isSecretKey(key: string, patterns: readonly string[]): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* An error's message with recognised credential shapes redacted, for embedding
|
|
55
|
+
* in another error's message: a wrapper that quotes its cause must not leak a
|
|
56
|
+
* `password=` or token the cause happened to carry.
|
|
57
|
+
*/
|
|
58
|
+
export declare function redactedMessage(error: Error): string;
|
|
15
59
|
/**
|
|
16
60
|
* Replace every recognised secret shape inside `value` with {@link REDACTED},
|
|
17
61
|
* leaving the surrounding text intact so a redacted message stays readable.
|
|
18
62
|
* Each pattern is rebuilt per call so a `g` flag's `lastIndex` never leaks
|
|
19
63
|
* between invocations.
|
|
64
|
+
*
|
|
65
|
+
* A pattern may capture a leading group it wants **preserved**: only the rest
|
|
66
|
+
* of the match is replaced, which is what keeps `apiKey=[REDACTED]` saying
|
|
67
|
+
* which field was redacted instead of collapsing to a bare marker. A pattern
|
|
68
|
+
* with no group is replaced whole, as before. `String.prototype.replace`
|
|
69
|
+
* passes the match *offset* — a number — as the second callback argument when
|
|
70
|
+
* the pattern has no group, hence the `typeof` test rather than an
|
|
71
|
+
* `undefined` check.
|
|
20
72
|
*/
|
|
21
73
|
export declare function redactText(value: string, patterns: readonly RegExp[]): string;
|
|
22
74
|
/**
|
|
@@ -38,4 +90,3 @@ export interface RedactedErrorText {
|
|
|
38
90
|
* rebuilding it so the secret cannot escape.
|
|
39
91
|
*/
|
|
40
92
|
export declare function redactErrorText(error: Error, patterns: readonly RegExp[]): RedactedErrorText;
|
|
41
|
-
//# sourceMappingURL=secret-patterns.d.ts.map
|
|
@@ -1,52 +1,112 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DEFAULT_SECRET_VALUE_PATTERNS = exports.DEFAULT_SECRET_KEY_PATTERNS = exports.REDACTED = void 0;
|
|
4
|
+
exports.normaliseKey = normaliseKey;
|
|
4
5
|
exports.isSecretKey = isSecretKey;
|
|
6
|
+
exports.redactedMessage = redactedMessage;
|
|
5
7
|
exports.redactText = redactText;
|
|
6
8
|
exports.binaryLabel = binaryLabel;
|
|
7
9
|
exports.redactErrorText = redactErrorText;
|
|
8
10
|
/** Marker substituted for anything recognised as secret. */
|
|
9
11
|
exports.REDACTED = '[REDACTED]';
|
|
10
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Key names whose value is a secret. Each entry is a *normalised* name — see
|
|
14
|
+
* {@link normaliseKey} — and matches a key whose normalised form equals it or
|
|
15
|
+
* ends with it. Suffix matching is what catches `secretAccessKey`, `x-api-key`,
|
|
16
|
+
* `client_secret` and `AUTH_TOKEN`; requiring the pattern to be a suffix, not a
|
|
17
|
+
* substring, is what spares `maxTokens`, `total_tokens`, `tokenizer` and
|
|
18
|
+
* `secretary`, which the old substring rule redacted.
|
|
19
|
+
*/
|
|
11
20
|
exports.DEFAULT_SECRET_KEY_PATTERNS = [
|
|
12
21
|
'accesskey',
|
|
13
|
-
'
|
|
22
|
+
'accesskeyid',
|
|
14
23
|
'secret',
|
|
15
24
|
'sessiontoken',
|
|
16
25
|
'securitytoken',
|
|
17
26
|
'authorization',
|
|
18
27
|
'password',
|
|
28
|
+
'passwd',
|
|
29
|
+
'passphrase',
|
|
19
30
|
'apikey',
|
|
20
31
|
'bearer',
|
|
21
32
|
'token',
|
|
22
33
|
'privatekey',
|
|
23
34
|
];
|
|
35
|
+
/**
|
|
36
|
+
* Canonical form of a key name for matching: lower-case with every character
|
|
37
|
+
* that is not a letter or digit removed, so `api_key`, `x-api-key`, `ApiKey`
|
|
38
|
+
* and `API KEY` all become `apikey`.
|
|
39
|
+
*/
|
|
40
|
+
function normaliseKey(key) {
|
|
41
|
+
return key.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
42
|
+
}
|
|
24
43
|
/**
|
|
25
44
|
* Secret shapes recognisable in free text, where key-name matching cannot
|
|
26
45
|
* reach: an error's `message`/`stack`, or any other string value. Deliberately
|
|
27
46
|
* high-confidence — each pattern describes a credential *format* rather than a
|
|
28
47
|
* word that merely sounds sensitive — so ordinary operational text survives
|
|
29
48
|
* redaction unchanged.
|
|
49
|
+
*
|
|
50
|
+
* The credential-pair pattern (last) tolerates a **closing quote after the
|
|
51
|
+
* keyword**, because that is what `JSON.stringify` produces
|
|
52
|
+
* (`{"password":"…"}`) and requiring the separator to follow the bare keyword
|
|
53
|
+
* matched nothing at all there — a silent, complete bypass on the single most
|
|
54
|
+
* common shape a downstream HTTP error arrives in. Its group 1 is the keyword
|
|
55
|
+
* and separator, preserved by {@link redactText}.
|
|
56
|
+
*
|
|
57
|
+
* Its value side tries three shapes, and their order is load-bearing:
|
|
58
|
+
* 1. a fully-quoted span that consumes escapes, so `{"password":"a\"b"}` is
|
|
59
|
+
* redacted whole. Ending the span at the escaped quote stopped the
|
|
60
|
+
* redaction short and printed the rest of the secret verbatim.
|
|
61
|
+
* 2. an unquoted JSON scalar — number, `true`, `false`, `null` — required to
|
|
62
|
+
* end at a real delimiter — `,`, `}`, `]` or end of input, optionally
|
|
63
|
+
* preceded by whitespace. Without this alternative,
|
|
64
|
+
* `{"apiKey":123,"region":"us-east-1"}` fell through to the fallback below,
|
|
65
|
+
* which then destroyed every sibling field after the secret. The lookahead
|
|
66
|
+
* is what stops the alternative truncating a value it does not fully
|
|
67
|
+
* describe, such as `token=123abc`, and leaking the tail it left behind.
|
|
68
|
+
* Whitespace alone does not end a scalar: treating a space as a delimiter
|
|
69
|
+
* made `api_key: 5 items` redact to `api_key: [REDACTED] items`, which
|
|
70
|
+
* reads as a partial redaction of a value the pattern never described.
|
|
71
|
+
* 3. the rest of the line, so a multi-word secret is redacted whole instead of
|
|
72
|
+
* up to its first space. Trying the two precise shapes first is what keeps
|
|
73
|
+
* this fallback from over-redacting sibling JSON fields.
|
|
30
74
|
*/
|
|
31
75
|
exports.DEFAULT_SECRET_VALUE_PATTERNS = [
|
|
32
76
|
/\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g,
|
|
33
77
|
/\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi,
|
|
34
78
|
/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g,
|
|
35
|
-
/(?:aws_)?(?:secret_access_key|secretaccesskey|password|passwd|api_?key|token)
|
|
79
|
+
/((?:aws_)?(?:secret_access_key|secretaccesskey|password|passwd|api_?key|token)["']?\s*[=:]\s*)(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)(?=\s*[,}\]]|\s*$)|[^\r\n]+)/gi,
|
|
36
80
|
];
|
|
37
|
-
/** True when `key`
|
|
81
|
+
/** True when `key`'s normalised form equals or ends with any (normalised) pattern. */
|
|
38
82
|
function isSecretKey(key, patterns) {
|
|
39
|
-
const
|
|
40
|
-
return patterns.some((pattern) =>
|
|
83
|
+
const normalised = normaliseKey(key);
|
|
84
|
+
return patterns.some((pattern) => normalised === pattern || normalised.endsWith(pattern));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* An error's message with recognised credential shapes redacted, for embedding
|
|
88
|
+
* in another error's message: a wrapper that quotes its cause must not leak a
|
|
89
|
+
* `password=` or token the cause happened to carry.
|
|
90
|
+
*/
|
|
91
|
+
function redactedMessage(error) {
|
|
92
|
+
return redactText(error.message, exports.DEFAULT_SECRET_VALUE_PATTERNS);
|
|
41
93
|
}
|
|
42
94
|
/**
|
|
43
95
|
* Replace every recognised secret shape inside `value` with {@link REDACTED},
|
|
44
96
|
* leaving the surrounding text intact so a redacted message stays readable.
|
|
45
97
|
* Each pattern is rebuilt per call so a `g` flag's `lastIndex` never leaks
|
|
46
98
|
* between invocations.
|
|
99
|
+
*
|
|
100
|
+
* A pattern may capture a leading group it wants **preserved**: only the rest
|
|
101
|
+
* of the match is replaced, which is what keeps `apiKey=[REDACTED]` saying
|
|
102
|
+
* which field was redacted instead of collapsing to a bare marker. A pattern
|
|
103
|
+
* with no group is replaced whole, as before. `String.prototype.replace`
|
|
104
|
+
* passes the match *offset* — a number — as the second callback argument when
|
|
105
|
+
* the pattern has no group, hence the `typeof` test rather than an
|
|
106
|
+
* `undefined` check.
|
|
47
107
|
*/
|
|
48
108
|
function redactText(value, patterns) {
|
|
49
|
-
return patterns.reduce((text, pattern) => text.replace(new RegExp(pattern.source, pattern.flags), exports.REDACTED), value);
|
|
109
|
+
return patterns.reduce((text, pattern) => text.replace(new RegExp(pattern.source, pattern.flags), (_match, prefix) => typeof prefix === 'string' ? `${prefix}${exports.REDACTED}` : exports.REDACTED), value);
|
|
50
110
|
}
|
|
51
111
|
/**
|
|
52
112
|
* A short label for a binary view. Recursing one would explode it into a
|
|
@@ -71,4 +131,3 @@ function redactErrorText(error, patterns) {
|
|
|
71
131
|
changed: message !== error.message || stack !== error.stack,
|
|
72
132
|
};
|
|
73
133
|
}
|
|
74
|
-
//# sourceMappingURL=secret-patterns.js.map
|
package/dist/shared/options.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
|
|
2
2
|
import type { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
|
|
3
3
|
import type { CompressionConfig } from './codec/compression';
|
|
4
4
|
import type { S3OffloadConfig } from './codec/s3/config';
|
|
5
|
+
import type { RetryPolicy } from './dynamodb/retry-policy';
|
|
5
6
|
import type { Logger } from './logging/logger';
|
|
6
7
|
import type { TtlOption } from './validation/ttl';
|
|
7
8
|
/**
|
|
@@ -15,12 +16,12 @@ export interface BaseAdapterOptions {
|
|
|
15
16
|
client?: DynamoDBDocument;
|
|
16
17
|
/** Config used to build a client when `client` is not provided. */
|
|
17
18
|
clientConfig?: DynamoDBClientConfig;
|
|
18
|
-
/** Factory seam for constructing the underlying client (testing). */
|
|
19
|
-
createClient?: (config: DynamoDBClientConfig) => DynamoDBClient;
|
|
20
19
|
/** Optional time-to-live applied to written items. */
|
|
21
20
|
ttl?: TtlOption;
|
|
22
21
|
/** Optional per-instance logger (defaults to a silent logger). */
|
|
23
22
|
logger?: Logger;
|
|
23
|
+
/** Retry budget and backoff for every DynamoDB call (see the README "Retries and backoff"). */
|
|
24
|
+
retry?: RetryPolicy;
|
|
24
25
|
}
|
|
25
26
|
/** Options enabling payload compression and/or S3 offloading. */
|
|
26
27
|
export interface CodecOptions {
|
|
@@ -29,4 +30,8 @@ export interface CodecOptions {
|
|
|
29
30
|
/** S3 offload configuration for payloads over DynamoDB's item limit. */
|
|
30
31
|
s3?: S3OffloadConfig;
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
/** Per-call cancellation for the long-running adapter methods. */
|
|
34
|
+
export interface CancelOptions {
|
|
35
|
+
/** Aborting it rejects the call with `AbortError` (`ABORTED`) at the next wait. */
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
}
|
package/dist/shared/options.js
CHANGED
package/dist/shared/ulid.d.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A CSPRNG-backed `rng` seam: uniform values in `[0, 1)` from `crypto.randomBytes`,
|
|
3
|
+
* drawn from a refilled pool so a burst of ids costs one syscall per 256
|
|
4
|
+
* digits rather than one per digit. `Math.random` is fine for uniqueness and
|
|
5
|
+
* ordering but is not a cryptographically secure source, which security
|
|
6
|
+
* baselines flag in identifier generation; the ULID spec recommends a CSPRNG.
|
|
7
|
+
*/
|
|
8
|
+
export declare function secureRng(): () => number;
|
|
9
|
+
/**
|
|
10
|
+
* The 10 time characters every ULID generated at `timeMs` starts with. Used
|
|
11
|
+
* as a sort-key bound: every id from that millisecond onwards sorts at or
|
|
12
|
+
* after it, every earlier id before it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ulidTimePrefix(timeMs: number): string;
|
|
1
15
|
/**
|
|
2
16
|
* Build a monotonic ULID generator: lexicographically sortable 26-char ids
|
|
3
17
|
* whose first 10 chars encode the millisecond timestamp. Ids strictly increase
|
|
4
18
|
* even when the clock regresses or the same-millisecond random space overflows:
|
|
5
19
|
* any non-advancing clock reuses the last timestamp and increments the random
|
|
6
20
|
* component, carrying into the timestamp on overflow. `now`/`rng` are seams for
|
|
7
|
-
* deterministic tests.
|
|
21
|
+
* deterministic tests; the default `rng` is {@link secureRng}.
|
|
8
22
|
*/
|
|
9
23
|
export declare function createUlidFactory(now?: () => number, rng?: () => number): () => string;
|
|
10
|
-
//# sourceMappingURL=ulid.d.ts.map
|
package/dist/shared/ulid.js
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secureRng = secureRng;
|
|
4
|
+
exports.ulidTimePrefix = ulidTimePrefix;
|
|
3
5
|
exports.createUlidFactory = createUlidFactory;
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
4
7
|
const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
5
8
|
const ENCODING_LEN = 32;
|
|
6
9
|
const TIME_CHARS = 10;
|
|
7
10
|
const RANDOM_CHARS = 16;
|
|
11
|
+
/** Bytes drawn per refill of the {@link secureRng} pool: 16 ids per syscall. */
|
|
12
|
+
const RNG_POOL_BYTES = 256;
|
|
13
|
+
/**
|
|
14
|
+
* A CSPRNG-backed `rng` seam: uniform values in `[0, 1)` from `crypto.randomBytes`,
|
|
15
|
+
* drawn from a refilled pool so a burst of ids costs one syscall per 256
|
|
16
|
+
* digits rather than one per digit. `Math.random` is fine for uniqueness and
|
|
17
|
+
* ordering but is not a cryptographically secure source, which security
|
|
18
|
+
* baselines flag in identifier generation; the ULID spec recommends a CSPRNG.
|
|
19
|
+
*/
|
|
20
|
+
function secureRng() {
|
|
21
|
+
let pool = Buffer.alloc(0);
|
|
22
|
+
let offset = 0;
|
|
23
|
+
return () => {
|
|
24
|
+
if (offset >= pool.length) {
|
|
25
|
+
pool = (0, node_crypto_1.randomBytes)(RNG_POOL_BYTES);
|
|
26
|
+
offset = 0;
|
|
27
|
+
}
|
|
28
|
+
const byte = pool[offset];
|
|
29
|
+
offset += 1;
|
|
30
|
+
return byte / 256;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
8
33
|
function encodeTime(timeMs) {
|
|
9
34
|
let remaining = Math.floor(timeMs);
|
|
10
35
|
let out = '';
|
|
@@ -14,6 +39,14 @@ function encodeTime(timeMs) {
|
|
|
14
39
|
}
|
|
15
40
|
return out;
|
|
16
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* The 10 time characters every ULID generated at `timeMs` starts with. Used
|
|
44
|
+
* as a sort-key bound: every id from that millisecond onwards sorts at or
|
|
45
|
+
* after it, every earlier id before it.
|
|
46
|
+
*/
|
|
47
|
+
function ulidTimePrefix(timeMs) {
|
|
48
|
+
return encodeTime(timeMs);
|
|
49
|
+
}
|
|
17
50
|
function randomDigits(rng) {
|
|
18
51
|
const digits = [];
|
|
19
52
|
for (let i = 0; i < RANDOM_CHARS; i++) {
|
|
@@ -38,9 +71,9 @@ function incrementDigits(digits) {
|
|
|
38
71
|
* even when the clock regresses or the same-millisecond random space overflows:
|
|
39
72
|
* any non-advancing clock reuses the last timestamp and increments the random
|
|
40
73
|
* component, carrying into the timestamp on overflow. `now`/`rng` are seams for
|
|
41
|
-
* deterministic tests.
|
|
74
|
+
* deterministic tests; the default `rng` is {@link secureRng}.
|
|
42
75
|
*/
|
|
43
|
-
function createUlidFactory(now = Date.now, rng =
|
|
76
|
+
function createUlidFactory(now = Date.now, rng = secureRng()) {
|
|
44
77
|
let lastTime = -1;
|
|
45
78
|
let lastRandom = [];
|
|
46
79
|
return () => {
|
|
@@ -62,4 +95,3 @@ function createUlidFactory(now = Date.now, rng = Math.random) {
|
|
|
62
95
|
return encodeTime(lastTime) + lastRandom.map((digit) => ENCODING[digit]).join('');
|
|
63
96
|
};
|
|
64
97
|
}
|
|
65
|
-
//# sourceMappingURL=ulid.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BaseAdapterOptions, CodecOptions } from '../options';
|
|
2
|
+
/**
|
|
3
|
+
* Validate the options every adapter shares, at construction. Each failure is
|
|
4
|
+
* a {@link ValidationError} whose `context.field` names the offending option,
|
|
5
|
+
* so a misconfiguration surfaces where it was written instead of as a raw AWS
|
|
6
|
+
* error on the first request.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateBaseAdapterOptions(options: BaseAdapterOptions & CodecOptions): void;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateBaseAdapterOptions = validateBaseAdapterOptions;
|
|
4
|
+
const config_1 = require("../codec/s3/config");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const errors_1 = require("../errors/errors");
|
|
7
|
+
const primitives_1 = require("./primitives");
|
|
8
|
+
const ttl_1 = require("./ttl");
|
|
9
|
+
/** DynamoDB's table-name rule: 3–255 characters from `[A-Za-z0-9_.-]`. */
|
|
10
|
+
const TABLE_NAME_PATTERN = /^[A-Za-z0-9_.-]{3,255}$/;
|
|
11
|
+
/** Server-side encryption algorithms S3 accepts for `PutObject`. */
|
|
12
|
+
const SSE_ALGORITHMS = ['AES256', 'aws:kms', 'aws:kms:dsse'];
|
|
13
|
+
function validateTableName(tableName) {
|
|
14
|
+
if (typeof tableName !== 'string' || !TABLE_NAME_PATTERN.test(tableName)) {
|
|
15
|
+
throw new errors_1.ValidationError('tableName must be 3-255 characters from [A-Za-z0-9_.-], as DynamoDB requires', 'tableName');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* An injected `client` is used as-is, so a `clientConfig` or `createClient`
|
|
20
|
+
* given alongside it would be silently ignored — including a `region` the
|
|
21
|
+
* caller believes is in effect. Reject the combination instead.
|
|
22
|
+
*/
|
|
23
|
+
function validateClientChoice(options) {
|
|
24
|
+
if (options.client &&
|
|
25
|
+
(options.clientConfig !== undefined || options.createClient !== undefined)) {
|
|
26
|
+
throw new errors_1.ValidationError('provide either `client` or `clientConfig`/`createClient`, not both: an injected client ' +
|
|
27
|
+
'is used as-is and the configuration would be silently ignored', 'client');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function validateRetryPolicy(policy) {
|
|
31
|
+
if (policy.maxAttempts !== undefined) {
|
|
32
|
+
(0, primitives_1.validateInteger)(policy.maxAttempts, 'retry.maxAttempts', { min: 1, max: constants_1.MAX_RETRY_ATTEMPTS });
|
|
33
|
+
}
|
|
34
|
+
if (policy.baseDelayMs !== undefined) {
|
|
35
|
+
(0, primitives_1.validateInteger)(policy.baseDelayMs, 'retry.baseDelayMs', { min: 1 });
|
|
36
|
+
}
|
|
37
|
+
if (policy.maxDelayMs !== undefined) {
|
|
38
|
+
(0, primitives_1.validateInteger)(policy.maxDelayMs, 'retry.maxDelayMs', { min: policy.baseDelayMs ?? 1 });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function validateCompression(config) {
|
|
42
|
+
if (typeof config.enabled !== 'boolean') {
|
|
43
|
+
throw new errors_1.ValidationError('compression.enabled must be a boolean', 'compression.enabled');
|
|
44
|
+
}
|
|
45
|
+
if (config.level !== undefined) {
|
|
46
|
+
(0, primitives_1.validateInteger)(config.level, 'compression.level', { min: 0, max: 9 });
|
|
47
|
+
}
|
|
48
|
+
if (config.minSizeBytes !== undefined) {
|
|
49
|
+
(0, primitives_1.validateInteger)(config.minSizeBytes, 'compression.minSizeBytes', { min: 0 });
|
|
50
|
+
}
|
|
51
|
+
if (config.maxDecompressedBytes !== undefined) {
|
|
52
|
+
(0, primitives_1.validateInteger)(config.maxDecompressedBytes, 'compression.maxDecompressedBytes', { min: 1 });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function validateS3(config) {
|
|
56
|
+
(0, primitives_1.validateNonEmptyString)(config.bucketName, 's3.bucketName');
|
|
57
|
+
if (config.thresholdBytes !== undefined) {
|
|
58
|
+
(0, primitives_1.validateInteger)(config.thresholdBytes, 's3.thresholdBytes', {
|
|
59
|
+
min: 1,
|
|
60
|
+
max: constants_1.MAX_INLINE_PAYLOAD_BYTES,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (config.keyPrefix !== undefined)
|
|
64
|
+
(0, config_1.assertScopedKeyPrefix)(config.keyPrefix);
|
|
65
|
+
if (config.maxDownloadBytes !== undefined) {
|
|
66
|
+
(0, primitives_1.validateInteger)(config.maxDownloadBytes, 's3.maxDownloadBytes', { min: 1 });
|
|
67
|
+
}
|
|
68
|
+
if (config.serverSideEncryption !== undefined &&
|
|
69
|
+
!SSE_ALGORITHMS.includes(config.serverSideEncryption)) {
|
|
70
|
+
throw new errors_1.ValidationError(`s3.serverSideEncryption must be one of ${SSE_ALGORITHMS.join(', ')}`, 's3.serverSideEncryption');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Validate the options every adapter shares, at construction. Each failure is
|
|
75
|
+
* a {@link ValidationError} whose `context.field` names the offending option,
|
|
76
|
+
* so a misconfiguration surfaces where it was written instead of as a raw AWS
|
|
77
|
+
* error on the first request.
|
|
78
|
+
*/
|
|
79
|
+
function validateBaseAdapterOptions(options) {
|
|
80
|
+
validateTableName(options.tableName);
|
|
81
|
+
validateClientChoice(options);
|
|
82
|
+
if (options.ttl !== undefined)
|
|
83
|
+
(0, ttl_1.resolveTtlSeconds)(options.ttl);
|
|
84
|
+
if (options.retry !== undefined)
|
|
85
|
+
validateRetryPolicy(options.retry);
|
|
86
|
+
if (options.compression !== undefined)
|
|
87
|
+
validateCompression(options.compression);
|
|
88
|
+
if (options.s3 !== undefined)
|
|
89
|
+
validateS3(options.s3);
|
|
90
|
+
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Throw {@link ValidationError} unless `value` is a string with at least one
|
|
3
|
+
* non-whitespace character: a blank identifier is never intended and would
|
|
4
|
+
* otherwise become an invisible, un-greppable DynamoDB key.
|
|
5
|
+
*/
|
|
3
6
|
export declare function validateNonEmptyString(value: string, field: string): void;
|
|
7
|
+
/** Throw {@link ValidationError} if `value` exceeds `maxBytes` when encoded as UTF-8. */
|
|
8
|
+
export declare function assertMaxBytes(value: string, field: string, maxBytes: number): void;
|
|
4
9
|
/** Throw {@link ValidationError} unless `value` is an integer within bounds. */
|
|
5
10
|
export declare function validateInteger(value: number, field: string, bounds?: {
|
|
6
11
|
min?: number;
|
|
@@ -14,12 +19,11 @@ export declare function assertNoControlChars(value: string, field: string): void
|
|
|
14
19
|
export declare function assertNoSeparator(value: string, separator: string, field: string): void;
|
|
15
20
|
/**
|
|
16
21
|
* Validate a caller-supplied identifier that reaches a DynamoDB key: non-empty,
|
|
17
|
-
* free of the reserved `separator`, and free of
|
|
18
|
-
* rule matters even though DynamoDB itself
|
|
19
|
-
* identifier is echoed into logs, so an
|
|
20
|
-
* log/terminal-injection surface for any app that
|
|
22
|
+
* at most `maxBytes` of UTF-8, free of the reserved `separator`, and free of
|
|
23
|
+
* control characters. The last rule matters even though DynamoDB itself
|
|
24
|
+
* accepts control characters — an identifier is echoed into logs, so an
|
|
25
|
+
* unvalidated ANSI escape is a log/terminal-injection surface for any app that
|
|
26
|
+
* writes these values out. The length check runs before the character scans so
|
|
27
|
+
* an oversized value is rejected without being walked.
|
|
21
28
|
*/
|
|
22
|
-
export declare function validateIdentifier(value: string, separator: string, field: string): void;
|
|
23
|
-
/** Throw {@link ValidationError} if nested-array depth exceeds `maxDepth`. */
|
|
24
|
-
export declare function validateArrayMaxDepth(value: Redactable[], field: string, maxDepth: number): void;
|
|
25
|
-
//# sourceMappingURL=primitives.d.ts.map
|
|
29
|
+
export declare function validateIdentifier(value: string, separator: string, field: string, maxBytes: number): void;
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateNonEmptyString = validateNonEmptyString;
|
|
4
|
+
exports.assertMaxBytes = assertMaxBytes;
|
|
4
5
|
exports.validateInteger = validateInteger;
|
|
5
6
|
exports.validateNonEmptyArray = validateNonEmptyArray;
|
|
6
7
|
exports.assertNoControlChars = assertNoControlChars;
|
|
7
8
|
exports.assertNoSeparator = assertNoSeparator;
|
|
8
9
|
exports.validateIdentifier = validateIdentifier;
|
|
9
|
-
exports.validateArrayMaxDepth = validateArrayMaxDepth;
|
|
10
10
|
const errors_1 = require("../errors/errors");
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Throw {@link ValidationError} unless `value` is a string with at least one
|
|
13
|
+
* non-whitespace character: a blank identifier is never intended and would
|
|
14
|
+
* otherwise become an invisible, un-greppable DynamoDB key.
|
|
15
|
+
*/
|
|
12
16
|
function validateNonEmptyString(value, field) {
|
|
13
|
-
if (typeof value !== 'string' || value.length === 0) {
|
|
14
|
-
throw new errors_1.ValidationError(`${field} must be a non-empty string`, field);
|
|
17
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
18
|
+
throw new errors_1.ValidationError(`${field} must be a non-empty string (whitespace-only counts as empty)`, field);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Throw {@link ValidationError} if `value` exceeds `maxBytes` when encoded as UTF-8. */
|
|
22
|
+
function assertMaxBytes(value, field, maxBytes) {
|
|
23
|
+
const bytes = Buffer.byteLength(value, 'utf8');
|
|
24
|
+
if (bytes > maxBytes) {
|
|
25
|
+
throw new errors_1.ValidationError(`${field} must be at most ${maxBytes} bytes of UTF-8 (received ${bytes})`, field);
|
|
15
26
|
}
|
|
16
27
|
}
|
|
17
28
|
/** Throw {@link ValidationError} unless `value` is an integer within bounds. */
|
|
@@ -56,29 +67,16 @@ function assertNoSeparator(value, separator, field) {
|
|
|
56
67
|
}
|
|
57
68
|
/**
|
|
58
69
|
* Validate a caller-supplied identifier that reaches a DynamoDB key: non-empty,
|
|
59
|
-
* free of the reserved `separator`, and free of
|
|
60
|
-
* rule matters even though DynamoDB itself
|
|
61
|
-
* identifier is echoed into logs, so an
|
|
62
|
-
* log/terminal-injection surface for any app that
|
|
70
|
+
* at most `maxBytes` of UTF-8, free of the reserved `separator`, and free of
|
|
71
|
+
* control characters. The last rule matters even though DynamoDB itself
|
|
72
|
+
* accepts control characters — an identifier is echoed into logs, so an
|
|
73
|
+
* unvalidated ANSI escape is a log/terminal-injection surface for any app that
|
|
74
|
+
* writes these values out. The length check runs before the character scans so
|
|
75
|
+
* an oversized value is rejected without being walked.
|
|
63
76
|
*/
|
|
64
|
-
function validateIdentifier(value, separator, field) {
|
|
77
|
+
function validateIdentifier(value, separator, field, maxBytes) {
|
|
65
78
|
validateNonEmptyString(value, field);
|
|
79
|
+
assertMaxBytes(value, field, maxBytes);
|
|
66
80
|
assertNoSeparator(value, separator, field);
|
|
67
81
|
assertNoControlChars(value, field);
|
|
68
82
|
}
|
|
69
|
-
/** Throw {@link ValidationError} if nested-array depth exceeds `maxDepth`. */
|
|
70
|
-
function validateArrayMaxDepth(value, field, maxDepth) {
|
|
71
|
-
const depthOf = (node, depth) => {
|
|
72
|
-
if (!Array.isArray(node)) {
|
|
73
|
-
return depth;
|
|
74
|
-
}
|
|
75
|
-
if (depth > maxDepth) {
|
|
76
|
-
return depth;
|
|
77
|
-
}
|
|
78
|
-
return node.reduce((max, child) => Math.max(max, depthOf(child, depth + 1)), depth);
|
|
79
|
-
};
|
|
80
|
-
if (depthOf(value, 0) > maxDepth) {
|
|
81
|
-
throw new errors_1.ValidationError(`${field} exceeds maximum array depth of ${maxDepth}`, field);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
//# sourceMappingURL=primitives.js.map
|
|
@@ -4,7 +4,11 @@ export type TtlOption = {
|
|
|
4
4
|
} | {
|
|
5
5
|
seconds: number;
|
|
6
6
|
};
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Validate a {@link TtlOption} and resolve it to a positive number of seconds.
|
|
9
|
+
* Both forms share the same five-year cap, and an object carrying both keys is
|
|
10
|
+
* rejected instead of being resolved by whichever key happens to be checked first.
|
|
11
|
+
*/
|
|
8
12
|
export declare function resolveTtlSeconds(ttl: TtlOption): number;
|
|
9
13
|
/**
|
|
10
14
|
* Resolve a {@link TtlOption} into a DynamoDB TTL attribute value: the Unix
|
|
@@ -13,9 +17,12 @@ export declare function resolveTtlSeconds(ttl: TtlOption): number;
|
|
|
13
17
|
* @param now - Clock seam returning epoch milliseconds. Defaults to `Date.now`.
|
|
14
18
|
*/
|
|
15
19
|
export declare function calculateTtlTimestamp(ttl: TtlOption, now?: () => number): number;
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Days for the S3 lifecycle rule that backs a TTL: the TTL rounded up to whole
|
|
22
|
+
* days plus {@link S3_LIFECYCLE_SWEEP_MARGIN_DAYS}. S3 expires an object at the
|
|
23
|
+
* first midnight UTC at least that many days after creation, while DynamoDB
|
|
24
|
+
* can keep the row up to ~48 h past its `ttl`; without the margin an
|
|
25
|
+
* `{ days: N }` TTL expired the object on day N exactly, stranding a live row
|
|
26
|
+
* that pointed at a deleted payload until the sweep caught up.
|
|
27
|
+
*/
|
|
28
|
+
export declare function lifecycleExpirationDays(ttl: TtlOption): number;
|
|
@@ -2,17 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveTtlSeconds = resolveTtlSeconds;
|
|
4
4
|
exports.calculateTtlTimestamp = calculateTtlTimestamp;
|
|
5
|
-
exports.
|
|
5
|
+
exports.lifecycleExpirationDays = lifecycleExpirationDays;
|
|
6
6
|
const constants_1 = require("../constants");
|
|
7
|
+
const errors_1 = require("../errors/errors");
|
|
7
8
|
const primitives_1 = require("./primitives");
|
|
8
9
|
const SECONDS_PER_DAY = 24 * 60 * 60;
|
|
9
|
-
/**
|
|
10
|
+
/** Positive integer no greater than `max`, with a message that names what the cap means. */
|
|
11
|
+
function validateWithinCap(value, field, max) {
|
|
12
|
+
(0, primitives_1.validateInteger)(value, field, { min: 1 });
|
|
13
|
+
if (value > max) {
|
|
14
|
+
throw new errors_1.ValidationError(`${field} must be <= ${max} (five years)`, field);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validate a {@link TtlOption} and resolve it to a positive number of seconds.
|
|
19
|
+
* Both forms share the same five-year cap, and an object carrying both keys is
|
|
20
|
+
* rejected instead of being resolved by whichever key happens to be checked first.
|
|
21
|
+
*/
|
|
10
22
|
function resolveTtlSeconds(ttl) {
|
|
23
|
+
if ('days' in ttl && 'seconds' in ttl) {
|
|
24
|
+
throw new errors_1.ValidationError('ttl must specify either ttl.days or ttl.seconds, not both', 'ttl');
|
|
25
|
+
}
|
|
11
26
|
if ('days' in ttl) {
|
|
12
|
-
(
|
|
27
|
+
validateWithinCap(ttl.days, 'ttl.days', constants_1.MAX_TTL_DAYS);
|
|
13
28
|
return ttl.days * SECONDS_PER_DAY;
|
|
14
29
|
}
|
|
15
|
-
(
|
|
30
|
+
validateWithinCap(ttl.seconds, 'ttl.seconds', constants_1.MAX_TTL_SECONDS);
|
|
16
31
|
return ttl.seconds;
|
|
17
32
|
}
|
|
18
33
|
/**
|
|
@@ -24,11 +39,14 @@ function resolveTtlSeconds(ttl) {
|
|
|
24
39
|
function calculateTtlTimestamp(ttl, now = Date.now) {
|
|
25
40
|
return Math.floor(now() / 1000) + resolveTtlSeconds(ttl);
|
|
26
41
|
}
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Days for the S3 lifecycle rule that backs a TTL: the TTL rounded up to whole
|
|
44
|
+
* days plus {@link S3_LIFECYCLE_SWEEP_MARGIN_DAYS}. S3 expires an object at the
|
|
45
|
+
* first midnight UTC at least that many days after creation, while DynamoDB
|
|
46
|
+
* can keep the row up to ~48 h past its `ttl`; without the margin an
|
|
47
|
+
* `{ days: N }` TTL expired the object on day N exactly, stranding a live row
|
|
48
|
+
* that pointed at a deleted payload until the sweep caught up.
|
|
49
|
+
*/
|
|
50
|
+
function lifecycleExpirationDays(ttl) {
|
|
51
|
+
return Math.ceil(resolveTtlSeconds(ttl) / SECONDS_PER_DAY) + constants_1.S3_LIFECYCLE_SWEEP_MARGIN_DAYS;
|
|
33
52
|
}
|
|
34
|
-
//# sourceMappingURL=ttl.js.map
|