webapp-factory 0.1.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 +145 -0
- package/dist/access-control/adapters/in-memory-relations.d.ts +7 -0
- package/dist/access-control/adapters/in-memory-relations.d.ts.map +1 -0
- package/dist/access-control/adapters/in-memory-relations.js +6 -0
- package/dist/access-control/adapters/in-memory-relations.js.map +1 -0
- package/dist/access-control/core/enforcement.d.ts +13 -0
- package/dist/access-control/core/enforcement.d.ts.map +1 -0
- package/dist/access-control/core/enforcement.js +38 -0
- package/dist/access-control/core/enforcement.js.map +1 -0
- package/dist/access-control/core/errors.d.ts +30 -0
- package/dist/access-control/core/errors.d.ts.map +1 -0
- package/dist/access-control/core/errors.js +46 -0
- package/dist/access-control/core/errors.js.map +1 -0
- package/dist/access-control/core/pdp.d.ts +14 -0
- package/dist/access-control/core/pdp.d.ts.map +1 -0
- package/dist/access-control/core/pdp.js +79 -0
- package/dist/access-control/core/pdp.js.map +1 -0
- package/dist/access-control/core/ports.d.ts +68 -0
- package/dist/access-control/core/ports.d.ts.map +1 -0
- package/dist/access-control/core/ports.js +6 -0
- package/dist/access-control/core/ports.js.map +1 -0
- package/dist/access-control/core/rbac.d.ts +10 -0
- package/dist/access-control/core/rbac.d.ts.map +1 -0
- package/dist/access-control/core/rbac.js +78 -0
- package/dist/access-control/core/rbac.js.map +1 -0
- package/dist/access-control/core/rebac.d.ts +15 -0
- package/dist/access-control/core/rebac.d.ts.map +1 -0
- package/dist/access-control/core/rebac.js +48 -0
- package/dist/access-control/core/rebac.js.map +1 -0
- package/dist/access-control/index.d.ts +15 -0
- package/dist/access-control/index.d.ts.map +1 -0
- package/dist/access-control/index.js +20 -0
- package/dist/access-control/index.js.map +1 -0
- package/dist/access-control/nestjs/access-control.module.d.ts +34 -0
- package/dist/access-control/nestjs/access-control.module.d.ts.map +1 -0
- package/dist/access-control/nestjs/access-control.module.js +80 -0
- package/dist/access-control/nestjs/access-control.module.js.map +1 -0
- package/dist/audit/adapters/in-memory-store.d.ts +3 -0
- package/dist/audit/adapters/in-memory-store.d.ts.map +1 -0
- package/dist/audit/adapters/in-memory-store.js +66 -0
- package/dist/audit/adapters/in-memory-store.js.map +1 -0
- package/dist/audit/adapters/pg-store.d.ts +22 -0
- package/dist/audit/adapters/pg-store.d.ts.map +1 -0
- package/dist/audit/adapters/pg-store.js +119 -0
- package/dist/audit/adapters/pg-store.js.map +1 -0
- package/dist/audit/core/audit-log.d.ts +41 -0
- package/dist/audit/core/audit-log.d.ts.map +1 -0
- package/dist/audit/core/audit-log.js +78 -0
- package/dist/audit/core/audit-log.js.map +1 -0
- package/dist/audit/core/errors.d.ts +22 -0
- package/dist/audit/core/errors.d.ts.map +1 -0
- package/dist/audit/core/errors.js +35 -0
- package/dist/audit/core/errors.js.map +1 -0
- package/dist/audit/core/hash.d.ts +9 -0
- package/dist/audit/core/hash.d.ts.map +1 -0
- package/dist/audit/core/hash.js +45 -0
- package/dist/audit/core/hash.js.map +1 -0
- package/dist/audit/core/ports.d.ts +68 -0
- package/dist/audit/core/ports.d.ts.map +1 -0
- package/dist/audit/core/ports.js +6 -0
- package/dist/audit/core/ports.js.map +1 -0
- package/dist/audit/index.d.ts +13 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +16 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/auth/adapters/argon2id-hasher.d.ts +15 -0
- package/dist/auth/adapters/argon2id-hasher.d.ts.map +1 -0
- package/dist/auth/adapters/argon2id-hasher.js +61 -0
- package/dist/auth/adapters/argon2id-hasher.js.map +1 -0
- package/dist/auth/adapters/in-memory-stores.d.ts +14 -0
- package/dist/auth/adapters/in-memory-stores.d.ts.map +1 -0
- package/dist/auth/adapters/in-memory-stores.js +78 -0
- package/dist/auth/adapters/in-memory-stores.js.map +1 -0
- package/dist/auth/core/auth-service.d.ts +40 -0
- package/dist/auth/core/auth-service.d.ts.map +1 -0
- package/dist/auth/core/auth-service.js +106 -0
- package/dist/auth/core/auth-service.js.map +1 -0
- package/dist/auth/core/credentials.d.ts +15 -0
- package/dist/auth/core/credentials.d.ts.map +1 -0
- package/dist/auth/core/credentials.js +15 -0
- package/dist/auth/core/credentials.js.map +1 -0
- package/dist/auth/core/crypto-util.d.ts +7 -0
- package/dist/auth/core/crypto-util.d.ts.map +1 -0
- package/dist/auth/core/crypto-util.js +15 -0
- package/dist/auth/core/crypto-util.js.map +1 -0
- package/dist/auth/core/errors.d.ts +33 -0
- package/dist/auth/core/errors.d.ts.map +1 -0
- package/dist/auth/core/errors.js +48 -0
- package/dist/auth/core/errors.js.map +1 -0
- package/dist/auth/core/jwt.d.ts +5 -0
- package/dist/auth/core/jwt.d.ts.map +1 -0
- package/dist/auth/core/jwt.js +40 -0
- package/dist/auth/core/jwt.js.map +1 -0
- package/dist/auth/core/ports.d.ts +95 -0
- package/dist/auth/core/ports.d.ts.map +1 -0
- package/dist/auth/core/ports.js +7 -0
- package/dist/auth/core/ports.js.map +1 -0
- package/dist/auth/core/single-use.d.ts +10 -0
- package/dist/auth/core/single-use.d.ts.map +1 -0
- package/dist/auth/core/single-use.js +47 -0
- package/dist/auth/core/single-use.js.map +1 -0
- package/dist/auth/core/tokens.d.ts +14 -0
- package/dist/auth/core/tokens.d.ts.map +1 -0
- package/dist/auth/core/tokens.js +85 -0
- package/dist/auth/core/tokens.js.map +1 -0
- package/dist/auth/index.d.ts +18 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +22 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/nestjs/auth.module.d.ts +17 -0
- package/dist/auth/nestjs/auth.module.d.ts.map +1 -0
- package/dist/auth/nestjs/auth.module.js +18 -0
- package/dist/auth/nestjs/auth.module.js.map +1 -0
- package/dist/cache/adapters/in-memory-store.d.ts +6 -0
- package/dist/cache/adapters/in-memory-store.d.ts.map +1 -0
- package/dist/cache/adapters/in-memory-store.js +65 -0
- package/dist/cache/adapters/in-memory-store.js.map +1 -0
- package/dist/cache/adapters/redis-store.d.ts +32 -0
- package/dist/cache/adapters/redis-store.d.ts.map +1 -0
- package/dist/cache/adapters/redis-store.js +59 -0
- package/dist/cache/adapters/redis-store.js.map +1 -0
- package/dist/cache/core/cache.d.ts +31 -0
- package/dist/cache/core/cache.d.ts.map +1 -0
- package/dist/cache/core/cache.js +89 -0
- package/dist/cache/core/cache.js.map +1 -0
- package/dist/cache/core/errors.d.ts +17 -0
- package/dist/cache/core/errors.d.ts.map +1 -0
- package/dist/cache/core/errors.js +27 -0
- package/dist/cache/core/errors.js.map +1 -0
- package/dist/cache/core/lock.d.ts +21 -0
- package/dist/cache/core/lock.d.ts.map +1 -0
- package/dist/cache/core/lock.js +47 -0
- package/dist/cache/core/lock.js.map +1 -0
- package/dist/cache/core/ports.d.ts +33 -0
- package/dist/cache/core/ports.d.ts.map +1 -0
- package/dist/cache/core/ports.js +6 -0
- package/dist/cache/core/ports.js.map +1 -0
- package/dist/cache/core/pubsub.d.ts +14 -0
- package/dist/cache/core/pubsub.d.ts.map +1 -0
- package/dist/cache/core/pubsub.js +13 -0
- package/dist/cache/core/pubsub.js.map +1 -0
- package/dist/cache/core/serializer.d.ts +4 -0
- package/dist/cache/core/serializer.d.ts.map +1 -0
- package/dist/cache/core/serializer.js +6 -0
- package/dist/cache/core/serializer.js.map +1 -0
- package/dist/cache/index.d.ts +14 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +19 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/config/adapters/reporters.d.ts +17 -0
- package/dist/config/adapters/reporters.d.ts.map +1 -0
- package/dist/config/adapters/reporters.js +35 -0
- package/dist/config/adapters/reporters.js.map +1 -0
- package/dist/config/adapters/secret-resolvers.d.ts +21 -0
- package/dist/config/adapters/secret-resolvers.d.ts.map +1 -0
- package/dist/config/adapters/secret-resolvers.js +60 -0
- package/dist/config/adapters/secret-resolvers.js.map +1 -0
- package/dist/config/adapters/zod-schema.d.ts +20 -0
- package/dist/config/adapters/zod-schema.d.ts.map +1 -0
- package/dist/config/adapters/zod-schema.js +35 -0
- package/dist/config/adapters/zod-schema.js.map +1 -0
- package/dist/config/core/env-loader.d.ts +47 -0
- package/dist/config/core/env-loader.d.ts.map +1 -0
- package/dist/config/core/env-loader.js +155 -0
- package/dist/config/core/env-loader.js.map +1 -0
- package/dist/config/core/errors.d.ts +34 -0
- package/dist/config/core/errors.d.ts.map +1 -0
- package/dist/config/core/errors.js +49 -0
- package/dist/config/core/errors.js.map +1 -0
- package/dist/config/core/freeze.d.ts +7 -0
- package/dist/config/core/freeze.d.ts.map +1 -0
- package/dist/config/core/freeze.js +20 -0
- package/dist/config/core/freeze.js.map +1 -0
- package/dist/config/core/load-config.d.ts +43 -0
- package/dist/config/core/load-config.d.ts.map +1 -0
- package/dist/config/core/load-config.js +74 -0
- package/dist/config/core/load-config.js.map +1 -0
- package/dist/config/core/merge.d.ts +19 -0
- package/dist/config/core/merge.d.ts.map +1 -0
- package/dist/config/core/merge.js +31 -0
- package/dist/config/core/merge.js.map +1 -0
- package/dist/config/core/ports.d.ts +58 -0
- package/dist/config/core/ports.d.ts.map +1 -0
- package/dist/config/core/ports.js +2 -0
- package/dist/config/core/ports.js.map +1 -0
- package/dist/config/core/secret-resolver.d.ts +16 -0
- package/dist/config/core/secret-resolver.d.ts.map +1 -0
- package/dist/config/core/secret-resolver.js +73 -0
- package/dist/config/core/secret-resolver.js.map +1 -0
- package/dist/config/core/secret.d.ts +21 -0
- package/dist/config/core/secret.d.ts.map +1 -0
- package/dist/config/core/secret.js +40 -0
- package/dist/config/core/secret.js.map +1 -0
- package/dist/config/index.d.ts +16 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +23 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/nestjs/config-kit.module.d.ts +37 -0
- package/dist/config/nestjs/config-kit.module.d.ts.map +1 -0
- package/dist/config/nestjs/config-kit.module.js +24 -0
- package/dist/config/nestjs/config-kit.module.js.map +1 -0
- package/dist/http/adapters/zod-schema.d.ts +11 -0
- package/dist/http/adapters/zod-schema.d.ts.map +1 -0
- package/dist/http/adapters/zod-schema.js +74 -0
- package/dist/http/adapters/zod-schema.js.map +1 -0
- package/dist/http/core/context.d.ts +25 -0
- package/dist/http/core/context.d.ts.map +1 -0
- package/dist/http/core/context.js +60 -0
- package/dist/http/core/context.js.map +1 -0
- package/dist/http/core/errors.d.ts +41 -0
- package/dist/http/core/errors.d.ts.map +1 -0
- package/dist/http/core/errors.js +99 -0
- package/dist/http/core/errors.js.map +1 -0
- package/dist/http/core/kernel.d.ts +54 -0
- package/dist/http/core/kernel.d.ts.map +1 -0
- package/dist/http/core/kernel.js +122 -0
- package/dist/http/core/kernel.js.map +1 -0
- package/dist/http/core/openapi.d.ts +37 -0
- package/dist/http/core/openapi.d.ts.map +1 -0
- package/dist/http/core/openapi.js +99 -0
- package/dist/http/core/openapi.js.map +1 -0
- package/dist/http/core/pagination.d.ts +17 -0
- package/dist/http/core/pagination.d.ts.map +1 -0
- package/dist/http/core/pagination.js +108 -0
- package/dist/http/core/pagination.js.map +1 -0
- package/dist/http/core/ports.d.ts +106 -0
- package/dist/http/core/ports.d.ts.map +1 -0
- package/dist/http/core/ports.js +6 -0
- package/dist/http/core/ports.js.map +1 -0
- package/dist/http/core/redaction.d.ts +8 -0
- package/dist/http/core/redaction.d.ts.map +1 -0
- package/dist/http/core/redaction.js +45 -0
- package/dist/http/core/redaction.js.map +1 -0
- package/dist/http/core/router.d.ts +37 -0
- package/dist/http/core/router.d.ts.map +1 -0
- package/dist/http/core/router.js +120 -0
- package/dist/http/core/router.js.map +1 -0
- package/dist/http/core/security.d.ts +43 -0
- package/dist/http/core/security.d.ts.map +1 -0
- package/dist/http/core/security.js +66 -0
- package/dist/http/core/security.js.map +1 -0
- package/dist/http/core/validation.d.ts +9 -0
- package/dist/http/core/validation.d.ts.map +1 -0
- package/dist/http/core/validation.js +36 -0
- package/dist/http/core/validation.js.map +1 -0
- package/dist/http/index.d.ts +20 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +29 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/nestjs/http-kernel.module.d.ts +37 -0
- package/dist/http/nestjs/http-kernel.module.d.ts.map +1 -0
- package/dist/http/nestjs/http-kernel.module.js +77 -0
- package/dist/http/nestjs/http-kernel.module.js.map +1 -0
- package/dist/http/nodejs/http-adapter.d.ts +11 -0
- package/dist/http/nodejs/http-adapter.d.ts.map +1 -0
- package/dist/http/nodejs/http-adapter.js +60 -0
- package/dist/http/nodejs/http-adapter.js.map +1 -0
- package/dist/i18n/core/catalog.d.ts +23 -0
- package/dist/i18n/core/catalog.d.ts.map +1 -0
- package/dist/i18n/core/catalog.js +31 -0
- package/dist/i18n/core/catalog.js.map +1 -0
- package/dist/i18n/core/errors.d.ts +14 -0
- package/dist/i18n/core/errors.d.ts.map +1 -0
- package/dist/i18n/core/errors.js +22 -0
- package/dist/i18n/core/errors.js.map +1 -0
- package/dist/i18n/core/i18n.d.ts +20 -0
- package/dist/i18n/core/i18n.d.ts.map +1 -0
- package/dist/i18n/core/i18n.js +48 -0
- package/dist/i18n/core/i18n.js.map +1 -0
- package/dist/i18n/core/message.d.ts +8 -0
- package/dist/i18n/core/message.d.ts.map +1 -0
- package/dist/i18n/core/message.js +38 -0
- package/dist/i18n/core/message.js.map +1 -0
- package/dist/i18n/core/negotiate.d.ts +13 -0
- package/dist/i18n/core/negotiate.d.ts.map +1 -0
- package/dist/i18n/core/negotiate.js +46 -0
- package/dist/i18n/core/negotiate.js.map +1 -0
- package/dist/i18n/core/ports.d.ts +35 -0
- package/dist/i18n/core/ports.d.ts.map +1 -0
- package/dist/i18n/core/ports.js +6 -0
- package/dist/i18n/core/ports.js.map +1 -0
- package/dist/i18n/index.d.ts +14 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +18 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/nestjs/i18n.module.d.ts +16 -0
- package/dist/i18n/nestjs/i18n.module.d.ts.map +1 -0
- package/dist/i18n/nestjs/i18n.module.js +17 -0
- package/dist/i18n/nestjs/i18n.module.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/adapters/in-memory-idempotency.d.ts +9 -0
- package/dist/jobs/adapters/in-memory-idempotency.d.ts.map +1 -0
- package/dist/jobs/adapters/in-memory-idempotency.js +34 -0
- package/dist/jobs/adapters/in-memory-idempotency.js.map +1 -0
- package/dist/jobs/adapters/in-memory-queue-store.d.ts +7 -0
- package/dist/jobs/adapters/in-memory-queue-store.d.ts.map +1 -0
- package/dist/jobs/adapters/in-memory-queue-store.js +70 -0
- package/dist/jobs/adapters/in-memory-queue-store.js.map +1 -0
- package/dist/jobs/adapters/redis-queue-store.d.ts +28 -0
- package/dist/jobs/adapters/redis-queue-store.d.ts.map +1 -0
- package/dist/jobs/adapters/redis-queue-store.js +86 -0
- package/dist/jobs/adapters/redis-queue-store.js.map +1 -0
- package/dist/jobs/core/backoff.d.ts +15 -0
- package/dist/jobs/core/backoff.d.ts.map +1 -0
- package/dist/jobs/core/backoff.js +20 -0
- package/dist/jobs/core/backoff.js.map +1 -0
- package/dist/jobs/core/cron.d.ts +13 -0
- package/dist/jobs/core/cron.d.ts.map +1 -0
- package/dist/jobs/core/cron.js +101 -0
- package/dist/jobs/core/cron.js.map +1 -0
- package/dist/jobs/core/errors.d.ts +18 -0
- package/dist/jobs/core/errors.d.ts.map +1 -0
- package/dist/jobs/core/errors.js +30 -0
- package/dist/jobs/core/errors.js.map +1 -0
- package/dist/jobs/core/ports.d.ts +80 -0
- package/dist/jobs/core/ports.d.ts.map +1 -0
- package/dist/jobs/core/ports.js +6 -0
- package/dist/jobs/core/ports.js.map +1 -0
- package/dist/jobs/core/queue.d.ts +16 -0
- package/dist/jobs/core/queue.d.ts.map +1 -0
- package/dist/jobs/core/queue.js +29 -0
- package/dist/jobs/core/queue.js.map +1 -0
- package/dist/jobs/core/registry.d.ts +4 -0
- package/dist/jobs/core/registry.d.ts.map +1 -0
- package/dist/jobs/core/registry.js +11 -0
- package/dist/jobs/core/registry.js.map +1 -0
- package/dist/jobs/core/scheduler.d.ts +30 -0
- package/dist/jobs/core/scheduler.d.ts.map +1 -0
- package/dist/jobs/core/scheduler.js +53 -0
- package/dist/jobs/core/scheduler.js.map +1 -0
- package/dist/jobs/core/serializer.d.ts +3 -0
- package/dist/jobs/core/serializer.d.ts.map +1 -0
- package/dist/jobs/core/serializer.js +5 -0
- package/dist/jobs/core/serializer.js.map +1 -0
- package/dist/jobs/core/worker.d.ts +28 -0
- package/dist/jobs/core/worker.d.ts.map +1 -0
- package/dist/jobs/core/worker.js +118 -0
- package/dist/jobs/core/worker.js.map +1 -0
- package/dist/jobs/index.d.ts +18 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +23 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/mailer/adapters/dev-inbox.d.ts +17 -0
- package/dist/mailer/adapters/dev-inbox.d.ts.map +1 -0
- package/dist/mailer/adapters/dev-inbox.js +29 -0
- package/dist/mailer/adapters/dev-inbox.js.map +1 -0
- package/dist/mailer/adapters/i18n-renderer.d.ts +13 -0
- package/dist/mailer/adapters/i18n-renderer.d.ts.map +1 -0
- package/dist/mailer/adapters/i18n-renderer.js +27 -0
- package/dist/mailer/adapters/i18n-renderer.js.map +1 -0
- package/dist/mailer/adapters/in-memory-templates.d.ts +6 -0
- package/dist/mailer/adapters/in-memory-templates.d.ts.map +1 -0
- package/dist/mailer/adapters/in-memory-templates.js +6 -0
- package/dist/mailer/adapters/in-memory-templates.js.map +1 -0
- package/dist/mailer/adapters/transports.d.ts +19 -0
- package/dist/mailer/adapters/transports.d.ts.map +1 -0
- package/dist/mailer/adapters/transports.js +38 -0
- package/dist/mailer/adapters/transports.js.map +1 -0
- package/dist/mailer/core/errors.d.ts +23 -0
- package/dist/mailer/core/errors.d.ts.map +1 -0
- package/dist/mailer/core/errors.js +40 -0
- package/dist/mailer/core/errors.js.map +1 -0
- package/dist/mailer/core/failover.d.ts +3 -0
- package/dist/mailer/core/failover.d.ts.map +1 -0
- package/dist/mailer/core/failover.js +30 -0
- package/dist/mailer/core/failover.js.map +1 -0
- package/dist/mailer/core/mailer.d.ts +25 -0
- package/dist/mailer/core/mailer.d.ts.map +1 -0
- package/dist/mailer/core/mailer.js +61 -0
- package/dist/mailer/core/mailer.js.map +1 -0
- package/dist/mailer/core/ports.d.ts +54 -0
- package/dist/mailer/core/ports.d.ts.map +1 -0
- package/dist/mailer/core/ports.js +6 -0
- package/dist/mailer/core/ports.js.map +1 -0
- package/dist/mailer/core/render.d.ts +4 -0
- package/dist/mailer/core/render.d.ts.map +1 -0
- package/dist/mailer/core/render.js +29 -0
- package/dist/mailer/core/render.js.map +1 -0
- package/dist/mailer/index.d.ts +17 -0
- package/dist/mailer/index.d.ts.map +1 -0
- package/dist/mailer/index.js +21 -0
- package/dist/mailer/index.js.map +1 -0
- package/dist/mailer/nestjs/mailer.module.d.ts +17 -0
- package/dist/mailer/nestjs/mailer.module.d.ts.map +1 -0
- package/dist/mailer/nestjs/mailer.module.js +15 -0
- package/dist/mailer/nestjs/mailer.module.js.map +1 -0
- package/dist/observability/core/context.d.ts +9 -0
- package/dist/observability/core/context.d.ts.map +1 -0
- package/dist/observability/core/context.js +15 -0
- package/dist/observability/core/context.js.map +1 -0
- package/dist/observability/core/health.d.ts +40 -0
- package/dist/observability/core/health.d.ts.map +1 -0
- package/dist/observability/core/health.js +51 -0
- package/dist/observability/core/health.js.map +1 -0
- package/dist/observability/core/logger.d.ts +22 -0
- package/dist/observability/core/logger.d.ts.map +1 -0
- package/dist/observability/core/logger.js +45 -0
- package/dist/observability/core/logger.js.map +1 -0
- package/dist/observability/core/metrics.d.ts +63 -0
- package/dist/observability/core/metrics.d.ts.map +1 -0
- package/dist/observability/core/metrics.js +172 -0
- package/dist/observability/core/metrics.js.map +1 -0
- package/dist/observability/core/redaction.d.ts +10 -0
- package/dist/observability/core/redaction.d.ts.map +1 -0
- package/dist/observability/core/redaction.js +48 -0
- package/dist/observability/core/redaction.js.map +1 -0
- package/dist/observability/core/tracing.d.ts +52 -0
- package/dist/observability/core/tracing.d.ts.map +1 -0
- package/dist/observability/core/tracing.js +88 -0
- package/dist/observability/core/tracing.js.map +1 -0
- package/dist/observability/index.d.ts +14 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +19 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/nestjs/observability.module.d.ts +35 -0
- package/dist/observability/nestjs/observability.module.d.ts.map +1 -0
- package/dist/observability/nestjs/observability.module.js +87 -0
- package/dist/observability/nestjs/observability.module.js.map +1 -0
- package/dist/persistence/adapters/in-memory-driver.d.ts +18 -0
- package/dist/persistence/adapters/in-memory-driver.d.ts.map +1 -0
- package/dist/persistence/adapters/in-memory-driver.js +229 -0
- package/dist/persistence/adapters/in-memory-driver.js.map +1 -0
- package/dist/persistence/adapters/pg-driver.d.ts +21 -0
- package/dist/persistence/adapters/pg-driver.d.ts.map +1 -0
- package/dist/persistence/adapters/pg-driver.js +42 -0
- package/dist/persistence/adapters/pg-driver.js.map +1 -0
- package/dist/persistence/adapters/testcontainer-harness.d.ts +37 -0
- package/dist/persistence/adapters/testcontainer-harness.d.ts.map +1 -0
- package/dist/persistence/adapters/testcontainer-harness.js +79 -0
- package/dist/persistence/adapters/testcontainer-harness.js.map +1 -0
- package/dist/persistence/core/errors.d.ts +36 -0
- package/dist/persistence/core/errors.d.ts.map +1 -0
- package/dist/persistence/core/errors.js +58 -0
- package/dist/persistence/core/errors.js.map +1 -0
- package/dist/persistence/core/migrations.d.ts +16 -0
- package/dist/persistence/core/migrations.d.ts.map +1 -0
- package/dist/persistence/core/migrations.js +95 -0
- package/dist/persistence/core/migrations.js.map +1 -0
- package/dist/persistence/core/pool.d.ts +4 -0
- package/dist/persistence/core/pool.d.ts.map +1 -0
- package/dist/persistence/core/pool.js +180 -0
- package/dist/persistence/core/pool.js.map +1 -0
- package/dist/persistence/core/ports.d.ts +91 -0
- package/dist/persistence/core/ports.d.ts.map +1 -0
- package/dist/persistence/core/ports.js +6 -0
- package/dist/persistence/core/ports.js.map +1 -0
- package/dist/persistence/core/repository.d.ts +18 -0
- package/dist/persistence/core/repository.d.ts.map +1 -0
- package/dist/persistence/core/repository.js +113 -0
- package/dist/persistence/core/repository.js.map +1 -0
- package/dist/persistence/core/sql.d.ts +13 -0
- package/dist/persistence/core/sql.d.ts.map +1 -0
- package/dist/persistence/core/sql.js +35 -0
- package/dist/persistence/core/sql.js.map +1 -0
- package/dist/persistence/index.d.ts +14 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +22 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/pg.d.ts +7 -0
- package/dist/persistence/pg.d.ts.map +1 -0
- package/dist/persistence/pg.js +7 -0
- package/dist/persistence/pg.js.map +1 -0
- package/dist/privacy/adapters/audit-sink.d.ts +19 -0
- package/dist/privacy/adapters/audit-sink.d.ts.map +1 -0
- package/dist/privacy/adapters/audit-sink.js +13 -0
- package/dist/privacy/adapters/audit-sink.js.map +1 -0
- package/dist/privacy/adapters/in-memory-consent-store.d.ts +7 -0
- package/dist/privacy/adapters/in-memory-consent-store.d.ts.map +1 -0
- package/dist/privacy/adapters/in-memory-consent-store.js +18 -0
- package/dist/privacy/adapters/in-memory-consent-store.js.map +1 -0
- package/dist/privacy/adapters/pg-consent-store.d.ts +26 -0
- package/dist/privacy/adapters/pg-consent-store.d.ts.map +1 -0
- package/dist/privacy/adapters/pg-consent-store.js +43 -0
- package/dist/privacy/adapters/pg-consent-store.js.map +1 -0
- package/dist/privacy/core/consent.d.ts +35 -0
- package/dist/privacy/core/consent.d.ts.map +1 -0
- package/dist/privacy/core/consent.js +49 -0
- package/dist/privacy/core/consent.js.map +1 -0
- package/dist/privacy/core/erasure.d.ts +22 -0
- package/dist/privacy/core/erasure.d.ts.map +1 -0
- package/dist/privacy/core/erasure.js +35 -0
- package/dist/privacy/core/erasure.js.map +1 -0
- package/dist/privacy/core/errors.d.ts +18 -0
- package/dist/privacy/core/errors.d.ts.map +1 -0
- package/dist/privacy/core/errors.js +30 -0
- package/dist/privacy/core/errors.js.map +1 -0
- package/dist/privacy/core/export.d.ts +20 -0
- package/dist/privacy/core/export.d.ts.map +1 -0
- package/dist/privacy/core/export.js +30 -0
- package/dist/privacy/core/export.js.map +1 -0
- package/dist/privacy/core/ports.d.ts +48 -0
- package/dist/privacy/core/ports.d.ts.map +1 -0
- package/dist/privacy/core/ports.js +6 -0
- package/dist/privacy/core/ports.js.map +1 -0
- package/dist/privacy/core/registry.d.ts +17 -0
- package/dist/privacy/core/registry.d.ts.map +1 -0
- package/dist/privacy/core/registry.js +31 -0
- package/dist/privacy/core/registry.js.map +1 -0
- package/dist/privacy/index.d.ts +16 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +21 -0
- package/dist/privacy/index.js.map +1 -0
- package/dist/rate-limit/adapters/in-memory-store.d.ts +7 -0
- package/dist/rate-limit/adapters/in-memory-store.d.ts.map +1 -0
- package/dist/rate-limit/adapters/in-memory-store.js +50 -0
- package/dist/rate-limit/adapters/in-memory-store.js.map +1 -0
- package/dist/rate-limit/adapters/redis-store.d.ts +11 -0
- package/dist/rate-limit/adapters/redis-store.d.ts.map +1 -0
- package/dist/rate-limit/adapters/redis-store.js +93 -0
- package/dist/rate-limit/adapters/redis-store.js.map +1 -0
- package/dist/rate-limit/core/enforcer.d.ts +23 -0
- package/dist/rate-limit/core/enforcer.d.ts.map +1 -0
- package/dist/rate-limit/core/enforcer.js +27 -0
- package/dist/rate-limit/core/enforcer.js.map +1 -0
- package/dist/rate-limit/core/errors.d.ts +19 -0
- package/dist/rate-limit/core/errors.d.ts.map +1 -0
- package/dist/rate-limit/core/errors.js +32 -0
- package/dist/rate-limit/core/errors.js.map +1 -0
- package/dist/rate-limit/core/ports.d.ts +50 -0
- package/dist/rate-limit/core/ports.d.ts.map +1 -0
- package/dist/rate-limit/core/ports.js +6 -0
- package/dist/rate-limit/core/ports.js.map +1 -0
- package/dist/rate-limit/core/sliding-window.d.ts +9 -0
- package/dist/rate-limit/core/sliding-window.d.ts.map +1 -0
- package/dist/rate-limit/core/sliding-window.js +24 -0
- package/dist/rate-limit/core/sliding-window.js.map +1 -0
- package/dist/rate-limit/core/token-bucket.d.ts +9 -0
- package/dist/rate-limit/core/token-bucket.d.ts.map +1 -0
- package/dist/rate-limit/core/token-bucket.js +24 -0
- package/dist/rate-limit/core/token-bucket.js.map +1 -0
- package/dist/rate-limit/index.d.ts +15 -0
- package/dist/rate-limit/index.d.ts.map +1 -0
- package/dist/rate-limit/index.js +19 -0
- package/dist/rate-limit/index.js.map +1 -0
- package/dist/rate-limit/nestjs/rate-limit.module.d.ts +25 -0
- package/dist/rate-limit/nestjs/rate-limit.module.d.ts.map +1 -0
- package/dist/rate-limit/nestjs/rate-limit.module.js +63 -0
- package/dist/rate-limit/nestjs/rate-limit.module.js.map +1 -0
- package/dist/rate-limit/nodejs/middleware.d.ts +16 -0
- package/dist/rate-limit/nodejs/middleware.d.ts.map +1 -0
- package/dist/rate-limit/nodejs/middleware.js +26 -0
- package/dist/rate-limit/nodejs/middleware.js.map +1 -0
- package/dist/test-kit/adapters/infra-bootstrap.d.ts +40 -0
- package/dist/test-kit/adapters/infra-bootstrap.d.ts.map +1 -0
- package/dist/test-kit/adapters/infra-bootstrap.js +64 -0
- package/dist/test-kit/adapters/infra-bootstrap.js.map +1 -0
- package/dist/test-kit/core/contract.d.ts +49 -0
- package/dist/test-kit/core/contract.d.ts.map +1 -0
- package/dist/test-kit/core/contract.js +52 -0
- package/dist/test-kit/core/contract.js.map +1 -0
- package/dist/test-kit/core/errors.d.ts +12 -0
- package/dist/test-kit/core/errors.d.ts.map +1 -0
- package/dist/test-kit/core/errors.js +19 -0
- package/dist/test-kit/core/errors.js.map +1 -0
- package/dist/test-kit/core/factories.d.ts +24 -0
- package/dist/test-kit/core/factories.d.ts.map +1 -0
- package/dist/test-kit/core/factories.js +57 -0
- package/dist/test-kit/core/factories.js.map +1 -0
- package/dist/test-kit/core/http-client.d.ts +46 -0
- package/dist/test-kit/core/http-client.d.ts.map +1 -0
- package/dist/test-kit/core/http-client.js +63 -0
- package/dist/test-kit/core/http-client.js.map +1 -0
- package/dist/test-kit/index.d.ts +10 -0
- package/dist/test-kit/index.d.ts.map +1 -0
- package/dist/test-kit/index.js +14 -0
- package/dist/test-kit/index.js.map +1 -0
- package/dist/test-kit/infra.d.ts +6 -0
- package/dist/test-kit/infra.d.ts.map +1 -0
- package/dist/test-kit/infra.js +6 -0
- package/dist/test-kit/infra.js.map +1 -0
- package/package.json +170 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export async function enforceRateLimit(key, options) {
|
|
2
|
+
try {
|
|
3
|
+
const result = await options.limiter.consume(key, options.cost);
|
|
4
|
+
const headers = rateLimitHeaders(result);
|
|
5
|
+
if (result.allowed) {
|
|
6
|
+
return { allowed: true, status: 200, headers, result };
|
|
7
|
+
}
|
|
8
|
+
headers['Retry-After'] = String(Math.max(1, Math.ceil(result.retryAfterMs / 1000)));
|
|
9
|
+
return { allowed: false, status: 429, headers, result };
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Store onbereikbaar → fail-beleid (geen details lekken).
|
|
13
|
+
if ((options.failPolicy ?? 'closed') === 'open') {
|
|
14
|
+
return { allowed: true, status: 200, headers: {} };
|
|
15
|
+
}
|
|
16
|
+
return { allowed: false, status: 503, headers: { 'Retry-After': '1' } };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Bouwt de informatieve `X-RateLimit-*`-headers uit een resultaat. */
|
|
20
|
+
export function rateLimitHeaders(result) {
|
|
21
|
+
return {
|
|
22
|
+
'X-RateLimit-Limit': String(result.limit),
|
|
23
|
+
'X-RateLimit-Remaining': String(Math.max(0, result.remaining)),
|
|
24
|
+
'X-RateLimit-Reset': String(Math.max(0, Math.ceil(result.resetMs / 1000))),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=enforcer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforcer.js","sourceRoot":"","sources":["../../../src/rate-limit/core/enforcer.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAW,EAAE,OAAuB;IACzE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACzD,CAAC;QACD,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;QAC1D,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,QAAQ,CAAC,KAAK,MAAM,EAAE,CAAC;YAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACrD,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC;IAC1E,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,MAAuB;IACtD,OAAO;QACL,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QACzC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9D,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC;KAC3E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Foutentaxonomie voor rate-limit. Config-fouten benoemen de ongeldige waarde; store-fouten lekken
|
|
3
|
+
* nooit een connectiestring of secret.
|
|
4
|
+
*/
|
|
5
|
+
export declare class RateLimitError extends Error {
|
|
6
|
+
readonly code: string;
|
|
7
|
+
constructor(message: string, code: string);
|
|
8
|
+
}
|
|
9
|
+
/** Ongeldige/ontbrekende limiet-config (US-0601/US-0602 AC3). Faalt fail-fast, nooit "onbeperkt". */
|
|
10
|
+
export declare class RateLimitConfigError extends RateLimitError {
|
|
11
|
+
constructor(field: string, value: unknown);
|
|
12
|
+
}
|
|
13
|
+
/** Store tijdelijk onbereikbaar (US-0603/US-0604 AC3). Bevat geen connectie-/secret-details. */
|
|
14
|
+
export declare class StoreUnavailableError extends RateLimitError {
|
|
15
|
+
constructor();
|
|
16
|
+
}
|
|
17
|
+
/** Bewaakt dat een numerieke config-waarde positief is; gooit anders {@link RateLimitConfigError}. */
|
|
18
|
+
export declare function assertPositive(field: string, value: number): void;
|
|
19
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/core/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAM1C;AAED,qGAAqG;AACrG,qBAAa,oBAAqB,SAAQ,cAAc;gBAC1C,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAG1C;AAED,gGAAgG;AAChG,qBAAa,qBAAsB,SAAQ,cAAc;;CAIxD;AAED,sGAAsG;AACtG,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIjE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Foutentaxonomie voor rate-limit. Config-fouten benoemen de ongeldige waarde; store-fouten lekken
|
|
3
|
+
* nooit een connectiestring of secret.
|
|
4
|
+
*/
|
|
5
|
+
export class RateLimitError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
constructor(message, code) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = new.target.name;
|
|
10
|
+
this.code = code;
|
|
11
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** Ongeldige/ontbrekende limiet-config (US-0601/US-0602 AC3). Faalt fail-fast, nooit "onbeperkt". */
|
|
15
|
+
export class RateLimitConfigError extends RateLimitError {
|
|
16
|
+
constructor(field, value) {
|
|
17
|
+
super(`Ongeldige rate-limit-config: "${field}" moet positief zijn (kreeg ${String(value)})`, 'RATE_LIMIT_CONFIG');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Store tijdelijk onbereikbaar (US-0603/US-0604 AC3). Bevat geen connectie-/secret-details. */
|
|
21
|
+
export class StoreUnavailableError extends RateLimitError {
|
|
22
|
+
constructor() {
|
|
23
|
+
super('Rate-limit-store is niet bereikbaar', 'STORE_UNAVAILABLE');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Bewaakt dat een numerieke config-waarde positief is; gooit anders {@link RateLimitConfigError}. */
|
|
27
|
+
export function assertPositive(field, value) {
|
|
28
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
|
|
29
|
+
throw new RateLimitConfigError(field, value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/rate-limit/core/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,IAAI,CAAS;IACtB,YAAY,OAAe,EAAE,IAAY;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAED,qGAAqG;AACrG,MAAM,OAAO,oBAAqB,SAAQ,cAAc;IACtD,YAAY,KAAa,EAAE,KAAc;QACvC,KAAK,CAAC,iCAAiC,KAAK,+BAA+B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IACpH,CAAC;CACF;AAED,gGAAgG;AAChG,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IACvD;QACE,KAAK,CAAC,qCAAqC,EAAE,mBAAmB,CAAC,CAAC;IACpE,CAAC;CACF;AAED,sGAAsG;AACtG,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,KAAa;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poorten & types voor de rate-limit-kit. Limieten per route, de store-adapter en de sleutel-afleiding
|
|
3
|
+
* worden geïnjecteerd; de kit bevat geen domeinkennis.
|
|
4
|
+
*/
|
|
5
|
+
export type Clock = () => number;
|
|
6
|
+
/** Uitkomst van een rate-limit-evaluatie. */
|
|
7
|
+
export interface RateLimitResult {
|
|
8
|
+
allowed: boolean;
|
|
9
|
+
limit: number;
|
|
10
|
+
/** Resterende capaciteit/requests (afgerond naar beneden). */
|
|
11
|
+
remaining: number;
|
|
12
|
+
/** ms tot de teller reset / de bucket weer vol is. */
|
|
13
|
+
resetMs: number;
|
|
14
|
+
/** ms tot de volgende request is toegestaan (0 als toegestaan). */
|
|
15
|
+
retryAfterMs: number;
|
|
16
|
+
}
|
|
17
|
+
/** Resultaat van een atomaire store-operatie (zonder `limit`; de limiter vult die aan). */
|
|
18
|
+
export interface StoreResult {
|
|
19
|
+
allowed: boolean;
|
|
20
|
+
remaining: number;
|
|
21
|
+
resetMs: number;
|
|
22
|
+
retryAfterMs: number;
|
|
23
|
+
}
|
|
24
|
+
export interface TokenBucketParams {
|
|
25
|
+
capacity: number;
|
|
26
|
+
/** Tokens die per milliseconde worden bijgevuld. */
|
|
27
|
+
refillPerMs: number;
|
|
28
|
+
cost: number;
|
|
29
|
+
nowMs: number;
|
|
30
|
+
}
|
|
31
|
+
export interface SlidingWindowParams {
|
|
32
|
+
limit: number;
|
|
33
|
+
windowMs: number;
|
|
34
|
+
cost: number;
|
|
35
|
+
nowMs: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Store-abstractie (US-0603): voert de atomaire teller-/bucket-operaties uit. Adapters: in-memory
|
|
39
|
+
* (single-instance) en Redis (gedistribueerd, atomair via Lua).
|
|
40
|
+
*/
|
|
41
|
+
export interface RateLimitStore {
|
|
42
|
+
consumeTokenBucket(key: string, params: TokenBucketParams): Promise<StoreResult>;
|
|
43
|
+
consumeSlidingWindow(key: string, params: SlidingWindowParams): Promise<StoreResult>;
|
|
44
|
+
}
|
|
45
|
+
/** Een geconfigureerde limiter over een store; deelbaar over algoritmen (US-0601/US-0602). */
|
|
46
|
+
export interface RateLimiter {
|
|
47
|
+
readonly limit: number;
|
|
48
|
+
consume(key: string, cost?: number): Promise<RateLimitResult>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/core/ports.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC;AAEjC,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,2FAA2F;AAC3F,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACjF,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACtF;AAED,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../../../src/rate-limit/core/ports.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Clock, RateLimitStore, RateLimiter } from './ports.js';
|
|
2
|
+
export interface SlidingWindowConfig {
|
|
3
|
+
/** Maximaal aantal requests binnen het venster. */
|
|
4
|
+
limit: number;
|
|
5
|
+
/** Venstergrootte in seconden. */
|
|
6
|
+
windowSeconds: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function slidingWindowLimiter(config: SlidingWindowConfig, store: RateLimitStore, clock?: Clock): RateLimiter;
|
|
9
|
+
//# sourceMappingURL=sliding-window.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sliding-window.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/core/sliding-window.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,cAAc,EACrB,KAAK,GAAE,KAAgB,GACtB,WAAW,CAiBb"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* US-0602 — Sliding-window-limiter (voortschrijdend venster via gewogen teller). Vermijdt de
|
|
3
|
+
* grens-burst van een vast venster. Config-validatie fail-fast; atomaire telling via de
|
|
4
|
+
* {@link RateLimitStore}-poort — dezelfde store-abstractie als token-bucket.
|
|
5
|
+
*/
|
|
6
|
+
import { assertPositive } from './errors.js';
|
|
7
|
+
export function slidingWindowLimiter(config, store, clock = Date.now) {
|
|
8
|
+
assertPositive('limit', config.limit);
|
|
9
|
+
assertPositive('windowSeconds', config.windowSeconds);
|
|
10
|
+
const windowMs = config.windowSeconds * 1000;
|
|
11
|
+
return {
|
|
12
|
+
limit: config.limit,
|
|
13
|
+
async consume(key, cost = 1) {
|
|
14
|
+
const result = await store.consumeSlidingWindow(key, {
|
|
15
|
+
limit: config.limit,
|
|
16
|
+
windowMs,
|
|
17
|
+
cost,
|
|
18
|
+
nowMs: clock(),
|
|
19
|
+
});
|
|
20
|
+
return { ...result, limit: config.limit };
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=sliding-window.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sliding-window.js","sourceRoot":"","sources":["../../../src/rate-limit/core/sliding-window.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAU7C,MAAM,UAAU,oBAAoB,CAClC,MAA2B,EAC3B,KAAqB,EACrB,QAAe,IAAI,CAAC,GAAG;IAEvB,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,cAAc,CAAC,eAAe,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC;IAE7C,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,oBAAoB,CAAC,GAAG,EAAE;gBACnD,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,QAAQ;gBACR,IAAI;gBACJ,KAAK,EAAE,KAAK,EAAE;aACf,CAAC,CAAC;YACH,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Clock, RateLimitStore, RateLimiter } from './ports.js';
|
|
2
|
+
export interface TokenBucketConfig {
|
|
3
|
+
/** Maximale burst-capaciteit (tokens). */
|
|
4
|
+
capacity: number;
|
|
5
|
+
/** Bijvul-rate in tokens per seconde. */
|
|
6
|
+
refillPerSecond: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function tokenBucketLimiter(config: TokenBucketConfig, store: RateLimitStore, clock?: Clock): RateLimiter;
|
|
9
|
+
//# sourceMappingURL=token-bucket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-bucket.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/core/token-bucket.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,cAAc,EACrB,KAAK,GAAE,KAAgB,GACtB,WAAW,CAiBb"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* US-0601 — Token-bucket-limiter. Per sleutel een bucket met burst-capaciteit die met een
|
|
3
|
+
* configureerbare rate wordt bijgevuld. Config-validatie fail-fast (nooit stil terugvallen op
|
|
4
|
+
* "onbeperkt toestaan"); de atomaire state loopt via de {@link RateLimitStore}-poort.
|
|
5
|
+
*/
|
|
6
|
+
import { assertPositive } from './errors.js';
|
|
7
|
+
export function tokenBucketLimiter(config, store, clock = Date.now) {
|
|
8
|
+
assertPositive('capacity', config.capacity);
|
|
9
|
+
assertPositive('refillPerSecond', config.refillPerSecond);
|
|
10
|
+
const refillPerMs = config.refillPerSecond / 1000;
|
|
11
|
+
return {
|
|
12
|
+
limit: config.capacity,
|
|
13
|
+
async consume(key, cost = 1) {
|
|
14
|
+
const result = await store.consumeTokenBucket(key, {
|
|
15
|
+
capacity: config.capacity,
|
|
16
|
+
refillPerMs,
|
|
17
|
+
cost,
|
|
18
|
+
nowMs: clock(),
|
|
19
|
+
});
|
|
20
|
+
return { ...result, limit: config.capacity };
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=token-bucket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-bucket.js","sourceRoot":"","sources":["../../../src/rate-limit/core/token-bucket.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAU7C,MAAM,UAAU,kBAAkB,CAChC,MAAyB,EACzB,KAAqB,EACrB,QAAe,IAAI,CAAC,GAAG;IAEvB,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,cAAc,CAAC,iBAAiB,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC;IAElD,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,QAAQ;QACtB,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,kBAAkB,CAAC,GAAG,EAAE;gBACjD,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,WAAW;gBACX,IAAI;gBACJ,KAAK,EAAE,KAAK,EAAE;aACf,CAAC,CAAC;YACH,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `rate-limit` kit — domein-loze throttling: token-bucket + sliding-window over een pluggable atomaire
|
|
3
|
+
* store (in-memory + Redis), met enforcement-middleware en standaard-headers. Pure core + adapters.
|
|
4
|
+
*
|
|
5
|
+
* De NestJS-guard zit onder `webapp-factory/backend-foundation/rate-limit/nestjs`.
|
|
6
|
+
*/
|
|
7
|
+
export { tokenBucketLimiter, type TokenBucketConfig } from './core/token-bucket.js';
|
|
8
|
+
export { slidingWindowLimiter, type SlidingWindowConfig } from './core/sliding-window.js';
|
|
9
|
+
export { enforceRateLimit, rateLimitHeaders, type RateLimitDecision, type EnforceOptions, } from './core/enforcer.js';
|
|
10
|
+
export type { Clock, RateLimiter, RateLimitResult, RateLimitStore, StoreResult, TokenBucketParams, SlidingWindowParams, } from './core/ports.js';
|
|
11
|
+
export { RateLimitError, RateLimitConfigError, StoreUnavailableError, } from './core/errors.js';
|
|
12
|
+
export { inMemoryRateLimitStore } from './adapters/in-memory-store.js';
|
|
13
|
+
export { redisRateLimitStore, type RedisLike, type RedisRateLimitStoreOptions, } from './adapters/redis-store.js';
|
|
14
|
+
export { rateLimitMiddleware, type RateLimitMiddlewareOptions } from './nodejs/middleware.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rate-limit/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG1F,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EACL,mBAAmB,EACnB,KAAK,SAAS,EACd,KAAK,0BAA0B,GAChC,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `rate-limit` kit — domein-loze throttling: token-bucket + sliding-window over een pluggable atomaire
|
|
3
|
+
* store (in-memory + Redis), met enforcement-middleware en standaard-headers. Pure core + adapters.
|
|
4
|
+
*
|
|
5
|
+
* De NestJS-guard zit onder `webapp-factory/backend-foundation/rate-limit/nestjs`.
|
|
6
|
+
*/
|
|
7
|
+
// Algoritmen (US-0601/US-0602)
|
|
8
|
+
export { tokenBucketLimiter } from './core/token-bucket.js';
|
|
9
|
+
export { slidingWindowLimiter } from './core/sliding-window.js';
|
|
10
|
+
// Enforcement + headers (US-0604)
|
|
11
|
+
export { enforceRateLimit, rateLimitHeaders, } from './core/enforcer.js';
|
|
12
|
+
// Fouten
|
|
13
|
+
export { RateLimitError, RateLimitConfigError, StoreUnavailableError, } from './core/errors.js';
|
|
14
|
+
// Adapters (dep-vrij; de Redis-store gebruikt een structurele `RedisLike`-client)
|
|
15
|
+
export { inMemoryRateLimitStore } from './adapters/in-memory-store.js';
|
|
16
|
+
export { redisRateLimitStore, } from './adapters/redis-store.js';
|
|
17
|
+
// Node/express-middleware (US-0604)
|
|
18
|
+
export { rateLimitMiddleware } from './nodejs/middleware.js';
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rate-limit/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,+BAA+B;AAC/B,OAAO,EAAE,kBAAkB,EAA0B,MAAM,wBAAwB,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAA4B,MAAM,0BAA0B,CAAC;AAE1F,kCAAkC;AAClC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,GAGjB,MAAM,oBAAoB,CAAC;AAa5B,SAAS;AACT,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,kFAAkF;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EACL,mBAAmB,GAGpB,MAAM,2BAA2B,CAAC;AAEnC,oCAAoC;AACpC,OAAO,EAAE,mBAAmB,EAAmC,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NestJS-adapter voor US-0604: een `RateLimitGuard` die per request de limiter evalueert, de
|
|
3
|
+
* `X-RateLimit-*`-headers zet en bij weigering een `429` (met `Retry-After`) gooit. De pure
|
|
4
|
+
* enforcement-logica zit in de core. `@nestjs/common` is een optionele peer-dependency.
|
|
5
|
+
*/
|
|
6
|
+
import { type CanActivate, type DynamicModule, type ExecutionContext } from '@nestjs/common';
|
|
7
|
+
import type { RateLimiter } from '../core/ports.js';
|
|
8
|
+
export declare const RATE_LIMIT_OPTIONS: unique symbol;
|
|
9
|
+
export interface RateLimitGuardOptions {
|
|
10
|
+
limiter: RateLimiter;
|
|
11
|
+
/** Leidt de sleutel af uit het request (bv. IP of user-id). */
|
|
12
|
+
getKey: (request: unknown) => string;
|
|
13
|
+
failPolicy?: 'open' | 'closed';
|
|
14
|
+
cost?: number;
|
|
15
|
+
global?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare class RateLimitGuard implements CanActivate {
|
|
18
|
+
private readonly options;
|
|
19
|
+
constructor(options: RateLimitGuardOptions);
|
|
20
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
21
|
+
}
|
|
22
|
+
export declare class RateLimitModule {
|
|
23
|
+
static forRoot(options: RateLimitGuardOptions): DynamicModule;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=rate-limit.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.module.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/nestjs/rate-limit.module.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EAEtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,eAAO,MAAM,kBAAkB,eAAmC,CAAC;AAMnE,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,WAAW,CAAC;IACrB,+DAA+D;IAC/D,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qBACa,cAAe,YAAW,WAAW;IACR,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,qBAAqB;IAEjF,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAsB/D;AAED,qBAAa,eAAe;IAC1B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,aAAa;CAY9D"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* NestJS-adapter voor US-0604: een `RateLimitGuard` die per request de limiter evalueert, de
|
|
15
|
+
* `X-RateLimit-*`-headers zet en bij weigering een `429` (met `Retry-After`) gooit. De pure
|
|
16
|
+
* enforcement-logica zit in de core. `@nestjs/common` is een optionele peer-dependency.
|
|
17
|
+
*/
|
|
18
|
+
import { HttpException, Inject, Injectable, } from '@nestjs/common';
|
|
19
|
+
import { enforceRateLimit } from '../core/enforcer.js';
|
|
20
|
+
export const RATE_LIMIT_OPTIONS = Symbol.for('rate-limit.options');
|
|
21
|
+
let RateLimitGuard = class RateLimitGuard {
|
|
22
|
+
options;
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.options = options;
|
|
25
|
+
}
|
|
26
|
+
async canActivate(context) {
|
|
27
|
+
const request = context.switchToHttp().getRequest();
|
|
28
|
+
const response = context.switchToHttp().getResponse();
|
|
29
|
+
const decision = await enforceRateLimit(this.options.getKey(request), {
|
|
30
|
+
limiter: this.options.limiter,
|
|
31
|
+
...(this.options.failPolicy ? { failPolicy: this.options.failPolicy } : {}),
|
|
32
|
+
...(this.options.cost !== undefined ? { cost: this.options.cost } : {}),
|
|
33
|
+
});
|
|
34
|
+
for (const [header, value] of Object.entries(decision.headers)) {
|
|
35
|
+
response.header(header, value);
|
|
36
|
+
}
|
|
37
|
+
if (!decision.allowed) {
|
|
38
|
+
throw new HttpException({ error: { code: 'RATE_LIMITED', message: 'Too Many Requests' } }, decision.status);
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
RateLimitGuard = __decorate([
|
|
44
|
+
Injectable(),
|
|
45
|
+
__param(0, Inject(RATE_LIMIT_OPTIONS)),
|
|
46
|
+
__metadata("design:paramtypes", [Object])
|
|
47
|
+
], RateLimitGuard);
|
|
48
|
+
export { RateLimitGuard };
|
|
49
|
+
export class RateLimitModule {
|
|
50
|
+
static forRoot(options) {
|
|
51
|
+
const providers = [
|
|
52
|
+
{ provide: RATE_LIMIT_OPTIONS, useValue: options },
|
|
53
|
+
RateLimitGuard,
|
|
54
|
+
];
|
|
55
|
+
return {
|
|
56
|
+
module: RateLimitModule,
|
|
57
|
+
global: options.global ?? true,
|
|
58
|
+
providers,
|
|
59
|
+
exports: [RateLimitGuard, RATE_LIMIT_OPTIONS],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=rate-limit.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.module.js","sourceRoot":"","sources":["../../../src/rate-limit/nestjs/rate-limit.module.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;;;GAIG;AACH,OAAO,EACL,aAAa,EACb,MAAM,EACN,UAAU,GAKX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AAgB5D,IAAM,cAAc,GAApB,MAAM,cAAc;IACgC;IAAzD,YAAyD,OAA8B;QAA9B,YAAO,GAAP,OAAO,CAAuB;IAAG,CAAC;IAE3F,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC;QAC7D,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,WAAW,EAAgB,CAAC;QAEpE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;YACpE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxE,CAAC,CAAC;QAEH,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/D,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,IAAI,aAAa,CACrB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,mBAAmB,EAAE,EAAE,EACjE,QAAQ,CAAC,MAAM,CAChB,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAzBY,cAAc;IAD1B,UAAU,EAAE;IAEE,WAAA,MAAM,CAAC,kBAAkB,CAAC,CAAA;;GAD5B,cAAc,CAyB1B;;AAED,MAAM,OAAO,eAAe;IAC1B,MAAM,CAAC,OAAO,CAAC,OAA8B;QAC3C,MAAM,SAAS,GAAe;YAC5B,EAAE,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,OAAO,EAAE;YAClD,cAAc;SACf,CAAC;QACF,OAAO;YACL,MAAM,EAAE,eAAe;YACvB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI;YAC9B,SAAS;YACT,OAAO,EAAE,CAAC,cAAc,EAAE,kBAAkB,CAAC;SAC9C,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* US-0604 — Node/connect/express-compatibele rate-limit-middleware. Bepaalt de sleutel via een
|
|
3
|
+
* callback, evalueert de limiter en zet de standaard-headers; bij weigering `429` + `Retry-After`.
|
|
4
|
+
* Werkt ook in een Nest-express-app via `app.use(...)`.
|
|
5
|
+
*/
|
|
6
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
7
|
+
import type { RateLimiter } from '../core/ports.js';
|
|
8
|
+
export interface RateLimitMiddlewareOptions {
|
|
9
|
+
limiter: RateLimiter;
|
|
10
|
+
/** Leidt de rate-limit-sleutel af uit het request (bv. IP of user-id). */
|
|
11
|
+
keyOf: (req: IncomingMessage) => string;
|
|
12
|
+
failPolicy?: 'open' | 'closed';
|
|
13
|
+
cost?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function rateLimitMiddleware(options: RateLimitMiddlewareOptions): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
|
|
16
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/rate-limit/nodejs/middleware.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,WAAW,CAAC;IACrB,0EAA0E;IAC1E,KAAK,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,IACvD,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,MAAM,IAAI,KAAG,OAAO,CAAC,IAAI,CAAC,CA2B1F"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { enforceRateLimit } from '../core/enforcer.js';
|
|
2
|
+
export function rateLimitMiddleware(options) {
|
|
3
|
+
return async (req, res, next) => {
|
|
4
|
+
const decision = await enforceRateLimit(options.keyOf(req), {
|
|
5
|
+
limiter: options.limiter,
|
|
6
|
+
...(options.failPolicy ? { failPolicy: options.failPolicy } : {}),
|
|
7
|
+
...(options.cost !== undefined ? { cost: options.cost } : {}),
|
|
8
|
+
});
|
|
9
|
+
for (const [header, value] of Object.entries(decision.headers)) {
|
|
10
|
+
res.setHeader(header, value);
|
|
11
|
+
}
|
|
12
|
+
if (decision.allowed) {
|
|
13
|
+
next();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
res.statusCode = decision.status;
|
|
17
|
+
res.setHeader('Content-Type', 'application/json');
|
|
18
|
+
res.end(JSON.stringify({
|
|
19
|
+
error: {
|
|
20
|
+
code: decision.status === 429 ? 'RATE_LIMITED' : 'STORE_UNAVAILABLE',
|
|
21
|
+
message: decision.status === 429 ? 'Too Many Requests' : 'Service Unavailable',
|
|
22
|
+
},
|
|
23
|
+
}));
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/rate-limit/nodejs/middleware.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAWvD,MAAM,UAAU,mBAAmB,CAAC,OAAmC;IACrE,OAAO,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAE,IAAgB,EAAiB,EAAE;QAC1F,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC1D,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAC;QAEH,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/D,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,GAAG,CAAC,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;QACjC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAClD,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,mBAAmB;gBACpE,OAAO,EAAE,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qBAAqB;aAC/E;SACF,CAAC,CACH,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* US-1401 — Testcontainers-bootstrap (Postgres/Redis). Bouwt voort op de persistence-kit-harness voor
|
|
3
|
+
* Postgres en start een wegwerp-Redis via testcontainers. Levert connectie-handles + `reset()` (schone
|
|
4
|
+
* staat tussen tests, zonder herstart) en `stop()` (gegarandeerde opruiming, ook bij een fout tijdens de
|
|
5
|
+
* bootstrap). Container-selectie/images komen uit geïnjecteerde config; geen domeinaannames.
|
|
6
|
+
*
|
|
7
|
+
* `testcontainers` wordt lui geladen; import van deze module vereist Docker pas bij `bootstrapTestInfra`.
|
|
8
|
+
*/
|
|
9
|
+
import { type TestDatabase } from '../../persistence/pg.js';
|
|
10
|
+
import type { Migration } from '../../persistence/index.js';
|
|
11
|
+
export interface PostgresInfraOptions {
|
|
12
|
+
migrations?: Migration[];
|
|
13
|
+
/** Tabellen die `reset()` leegmaakt tussen tests. */
|
|
14
|
+
managedTables?: string[];
|
|
15
|
+
image?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface RedisInfraOptions {
|
|
18
|
+
image?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface TestInfraOptions {
|
|
21
|
+
postgres?: PostgresInfraOptions;
|
|
22
|
+
redis?: RedisInfraOptions;
|
|
23
|
+
}
|
|
24
|
+
export interface RedisHandle {
|
|
25
|
+
uri: string;
|
|
26
|
+
host: string;
|
|
27
|
+
port: number;
|
|
28
|
+
/** FLUSHALL — schone staat tussen tests. */
|
|
29
|
+
reset(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export interface TestInfra {
|
|
32
|
+
postgres?: TestDatabase;
|
|
33
|
+
redis?: RedisHandle;
|
|
34
|
+
/** Zet alle ingeschakelde stores terug naar de basisstaat (US-1401 AC2). */
|
|
35
|
+
reset(): Promise<void>;
|
|
36
|
+
/** Stopt en ruimt alle containers op (US-1401 AC3). */
|
|
37
|
+
stop(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export declare function bootstrapTestInfra(options?: TestInfraOptions): Promise<TestInfra>;
|
|
40
|
+
//# sourceMappingURL=infra-bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infra-bootstrap.d.ts","sourceRoot":"","sources":["../../../src/test-kit/adapters/infra-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAA+C,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACzG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,4EAA4E;IAC5E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,uDAAuD;IACvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CAuD3F"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* US-1401 — Testcontainers-bootstrap (Postgres/Redis). Bouwt voort op de persistence-kit-harness voor
|
|
3
|
+
* Postgres en start een wegwerp-Redis via testcontainers. Levert connectie-handles + `reset()` (schone
|
|
4
|
+
* staat tussen tests, zonder herstart) en `stop()` (gegarandeerde opruiming, ook bij een fout tijdens de
|
|
5
|
+
* bootstrap). Container-selectie/images komen uit geïnjecteerde config; geen domeinaannames.
|
|
6
|
+
*
|
|
7
|
+
* `testcontainers` wordt lui geladen; import van deze module vereist Docker pas bij `bootstrapTestInfra`.
|
|
8
|
+
*/
|
|
9
|
+
import { startTestDatabase, postgresContainerFactory } from '../../persistence/pg.js';
|
|
10
|
+
export async function bootstrapTestInfra(options = {}) {
|
|
11
|
+
const stops = [];
|
|
12
|
+
let postgres;
|
|
13
|
+
let redis;
|
|
14
|
+
try {
|
|
15
|
+
if (options.postgres) {
|
|
16
|
+
postgres = await startTestDatabase({
|
|
17
|
+
migrations: options.postgres.migrations ?? [],
|
|
18
|
+
...(options.postgres.managedTables ? { managedTables: options.postgres.managedTables } : {}),
|
|
19
|
+
...(options.postgres.image ? { containerFactory: postgresContainerFactory({ image: options.postgres.image }) } : {}),
|
|
20
|
+
});
|
|
21
|
+
const db = postgres;
|
|
22
|
+
stops.push(() => db.stop());
|
|
23
|
+
}
|
|
24
|
+
if (options.redis) {
|
|
25
|
+
const { GenericContainer, Wait } = await import('testcontainers');
|
|
26
|
+
const container = await new GenericContainer(options.redis.image ?? 'redis:7-alpine')
|
|
27
|
+
.withExposedPorts(6379)
|
|
28
|
+
.withWaitStrategy(Wait.forLogMessage(/Ready to accept connections/))
|
|
29
|
+
.start();
|
|
30
|
+
stops.push(async () => {
|
|
31
|
+
await container.stop();
|
|
32
|
+
});
|
|
33
|
+
const host = container.getHost();
|
|
34
|
+
const port = container.getMappedPort(6379);
|
|
35
|
+
redis = {
|
|
36
|
+
uri: `redis://${host}:${port}`,
|
|
37
|
+
host,
|
|
38
|
+
port,
|
|
39
|
+
reset: async () => {
|
|
40
|
+
await container.exec(['redis-cli', 'FLUSHALL']);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
// Geen halve/lekkende containers achterlaten (AC3).
|
|
47
|
+
for (const stop of stops.reverse())
|
|
48
|
+
await stop().catch(() => undefined);
|
|
49
|
+
throw new Error(`test-kit infra-bootstrap mislukt (is de Docker-daemon bereikbaar?): ${error instanceof Error ? error.message : String(error)}`);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
...(postgres ? { postgres } : {}),
|
|
53
|
+
...(redis ? { redis } : {}),
|
|
54
|
+
reset: async () => {
|
|
55
|
+
await postgres?.reset();
|
|
56
|
+
await redis?.reset();
|
|
57
|
+
},
|
|
58
|
+
stop: async () => {
|
|
59
|
+
for (const stop of stops.reverse())
|
|
60
|
+
await stop().catch(() => undefined);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=infra-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infra-bootstrap.js","sourceRoot":"","sources":["../../../src/test-kit/adapters/infra-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAqB,MAAM,yBAAyB,CAAC;AAoCzG,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAA4B,EAAE;IACrE,MAAM,KAAK,GAA+B,EAAE,CAAC;IAC7C,IAAI,QAAkC,CAAC;IACvC,IAAI,KAA8B,CAAC;IAEnC,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,QAAQ,GAAG,MAAM,iBAAiB,CAAC;gBACjC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE;gBAC7C,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5F,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,wBAAwB,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrH,CAAC,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAClE,MAAM,SAAS,GAAG,MAAM,IAAI,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,gBAAgB,CAAC;iBAClF,gBAAgB,CAAC,IAAI,CAAC;iBACtB,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,6BAA6B,CAAC,CAAC;iBACnE,KAAK,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBACpB,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;YACzB,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAC3C,KAAK,GAAG;gBACN,GAAG,EAAE,WAAW,IAAI,IAAI,IAAI,EAAE;gBAC9B,IAAI;gBACJ,IAAI;gBACJ,KAAK,EAAE,KAAK,IAAI,EAAE;oBAChB,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;gBAClD,CAAC;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oDAAoD;QACpD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,EAAE;YAAE,MAAM,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACxE,MAAM,IAAI,KAAK,CACb,uEAAuE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAChI,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,QAAQ,EAAE,KAAK,EAAE,CAAC;YACxB,MAAM,KAAK,EAAE,KAAK,EAAE,CAAC;QACvB,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,EAAE;gBAAE,MAAM,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* US-1404 — Contract-test-harness. Verifieert dat een provider een geïnjecteerd contract nakomt: per
|
|
3
|
+
* interactie status + body (subset-match: extra velden toegestaan, ontbrekende/afwijkende velden falen).
|
|
4
|
+
* Afwijkingen worden precies gerapporteerd (pad + verwacht vs. werkelijk). Contracten zijn geïnjecteerde
|
|
5
|
+
* data; de provider-koppeling is een adapter (bv. de HTTP-test-client).
|
|
6
|
+
*/
|
|
7
|
+
export type ContractMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
8
|
+
export interface Contract {
|
|
9
|
+
name?: string;
|
|
10
|
+
request: {
|
|
11
|
+
method: ContractMethod;
|
|
12
|
+
path: string;
|
|
13
|
+
body?: unknown;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
token?: string;
|
|
16
|
+
};
|
|
17
|
+
expect: {
|
|
18
|
+
status: number;
|
|
19
|
+
/** Verwachte (deel)body; extra velden in de response zijn toegestaan. */
|
|
20
|
+
body?: unknown;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface Deviation {
|
|
24
|
+
path: string;
|
|
25
|
+
expected: unknown;
|
|
26
|
+
actual: unknown;
|
|
27
|
+
}
|
|
28
|
+
export interface ContractResult {
|
|
29
|
+
name: string;
|
|
30
|
+
verified: boolean;
|
|
31
|
+
deviations: Deviation[];
|
|
32
|
+
}
|
|
33
|
+
export interface ContractReport {
|
|
34
|
+
verified: boolean;
|
|
35
|
+
results: ContractResult[];
|
|
36
|
+
}
|
|
37
|
+
/** Structureel provider-contract (de HTTP-test-client voldoet hieraan via `request`). */
|
|
38
|
+
export interface ContractProvider {
|
|
39
|
+
request(method: string, path: string, options?: {
|
|
40
|
+
body?: unknown;
|
|
41
|
+
headers?: Record<string, string>;
|
|
42
|
+
token?: string;
|
|
43
|
+
}): Promise<{
|
|
44
|
+
status: number;
|
|
45
|
+
body: unknown;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
export declare function verifyContracts(provider: ContractProvider, contracts: Contract[]): Promise<ContractReport>;
|
|
49
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/test-kit/core/contract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEzE,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QACP,MAAM,EAAE,cAAc,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,yEAAyE;QACzE,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,yFAAyF;AACzF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CACL,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7E,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC/C;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,QAAQ,EAAE,GACpB,OAAO,CAAC,cAAc,CAAC,CAoBzB"}
|