exisjs 0.6.1 → 0.7.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 +9 -3
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +2 -8
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +33 -44
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/exports.d.ts.map +1 -1
- package/dist/cli/commands/exports.js +5 -32
- package/dist/cli/commands/exports.js.map +1 -1
- package/dist/cli/commands/generate.d.ts +2 -13
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +27 -60
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +4 -4
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +2 -6
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/index.js +11 -23
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/routes.d.ts.map +1 -1
- package/dist/cli/routes.js +20 -8
- package/dist/cli/routes.js.map +1 -1
- package/dist/config/config.d.ts +2 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +7 -5
- package/dist/config/config.js.map +1 -1
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +3 -2
- package/dist/config/env.js.map +1 -1
- package/dist/config/types.d.ts +7 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/decorators/constants.d.ts +9 -2
- package/dist/decorators/constants.d.ts.map +1 -1
- package/dist/decorators/constants.js +3 -2
- package/dist/decorators/constants.js.map +1 -1
- package/dist/decorators/core/metadata.d.ts +31 -0
- package/dist/decorators/core/metadata.d.ts.map +1 -1
- package/dist/decorators/core/metadata.js +110 -1
- package/dist/decorators/core/metadata.js.map +1 -1
- package/dist/decorators/core.d.ts +19 -4
- package/dist/decorators/core.d.ts.map +1 -1
- package/dist/decorators/core.js +29 -4
- package/dist/decorators/core.js.map +1 -1
- package/dist/decorators/middleware.d.ts +17 -17
- package/dist/decorators/middleware.d.ts.map +1 -1
- package/dist/decorators/middleware.js +111 -208
- package/dist/decorators/middleware.js.map +1 -1
- package/dist/decorators/params.d.ts +54 -12
- package/dist/decorators/params.d.ts.map +1 -1
- package/dist/decorators/params.js +40 -20
- package/dist/decorators/params.js.map +1 -1
- package/dist/decorators/routing.d.ts +0 -2
- package/dist/decorators/routing.d.ts.map +1 -1
- package/dist/decorators/routing.js +3 -4
- package/dist/decorators/routing.js.map +1 -1
- package/dist/di/container.d.ts +5 -1
- package/dist/di/container.d.ts.map +1 -1
- package/dist/di/container.js +56 -8
- package/dist/di/container.js.map +1 -1
- package/dist/di/decorators.d.ts +30 -0
- package/dist/di/decorators.d.ts.map +1 -0
- package/dist/di/decorators.js +59 -0
- package/dist/di/decorators.js.map +1 -0
- package/dist/di/index.d.ts +1 -0
- package/dist/di/index.d.ts.map +1 -1
- package/dist/di/index.js +4 -1
- package/dist/di/index.js.map +1 -1
- package/dist/docs/ARCHITECTURE.md +46 -285
- package/dist/docs/BENCHMARKS.md +5 -5
- package/dist/docs/README.md +8 -11
- package/dist/docs/content/boundaries.mdx +151 -0
- package/dist/docs/content/cli/commands.mdx +66 -104
- package/dist/docs/content/cli/overview.mdx +37 -47
- package/dist/docs/content/cli/usage.mdx +29 -15
- package/dist/docs/content/decorators.mdx +142 -81
- package/dist/docs/content/installation.mdx +20 -1
- package/dist/docs/content/middleware.mdx +65 -291
- package/dist/docs/content/modules.mdx +22 -1
- package/dist/docs/content/providers.mdx +33 -1
- package/dist/docs/content/security.mdx +44 -246
- package/dist/docs/content/structure.mdx +227 -100
- package/dist/docs/content/validation.mdx +0 -17
- package/dist/docs/reference/decorators.mdx +34 -216
- package/dist/docs/reference/di.mdx +35 -11
- package/dist/docs/reference/logger.mdx +100 -0
- package/dist/docs/reference/middleware.mdx +41 -217
- package/dist/docs/reference/router.mdx +9 -9
- package/dist/docs/reference/validator.mdx +2 -5
- package/dist/error/errors.d.ts.map +1 -1
- package/dist/error/errors.js +19 -5
- package/dist/error/errors.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/start-server.js +10 -0
- package/dist/lib/start-server.js.map +1 -1
- package/dist/logger/index.d.ts +81 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +142 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/middleware/dedupe.d.ts +1 -1
- package/dist/middleware/dedupe.js +1 -1
- package/dist/middleware/middleware.d.ts +3 -5
- package/dist/middleware/middleware.d.ts.map +1 -1
- package/dist/middleware/middleware.js +2 -6
- package/dist/middleware/middleware.js.map +1 -1
- package/dist/middleware/rate-limit.d.ts +0 -2
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +2 -14
- package/dist/middleware/rate-limit.js.map +1 -1
- package/dist/module/index.d.ts +2 -0
- package/dist/module/index.d.ts.map +1 -1
- package/dist/module/index.js +3 -1
- package/dist/module/index.js.map +1 -1
- package/dist/plugin/manager.d.ts +1 -1
- package/dist/plugin/manager.d.ts.map +1 -1
- package/dist/plugin/manager.js +47 -0
- package/dist/plugin/manager.js.map +1 -1
- package/dist/router/{gateway.d.ts → boundary.d.ts} +21 -13
- package/dist/router/boundary.d.ts.map +1 -0
- package/dist/router/boundary.js +11 -0
- package/dist/router/boundary.js.map +1 -0
- package/dist/router/controller-registrar.d.ts.map +1 -1
- package/dist/router/controller-registrar.js +33 -6
- package/dist/router/controller-registrar.js.map +1 -1
- package/dist/router/index.d.ts +3 -6
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +3 -7
- package/dist/router/index.js.map +1 -1
- package/dist/router/route-builder.d.ts +0 -28
- package/dist/router/route-builder.d.ts.map +1 -1
- package/dist/router/route-builder.js +2 -5
- package/dist/router/route-builder.js.map +1 -1
- package/dist/router/route-scanner.d.ts +1 -2
- package/dist/router/route-scanner.d.ts.map +1 -1
- package/dist/router/route-scanner.js +225 -203
- package/dist/router/route-scanner.js.map +1 -1
- package/dist/router/router.d.ts +4 -6
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +36 -72
- package/dist/router/router.js.map +1 -1
- package/dist/router/types.d.ts +2 -6
- package/dist/router/types.d.ts.map +1 -1
- package/dist/server/{bun-adapter.d.ts → adapters/bun-adapter.d.ts} +1 -1
- package/dist/server/adapters/bun-adapter.d.ts.map +1 -0
- package/dist/server/{bun-adapter.js → adapters/bun-adapter.js} +2 -24
- package/dist/server/adapters/bun-adapter.js.map +1 -0
- package/dist/server/{uws-adapter.d.ts → adapters/uws-adapter.d.ts} +1 -1
- package/dist/server/adapters/uws-adapter.d.ts.map +1 -0
- package/dist/server/{uws-adapter.js → adapters/uws-adapter.js} +1 -28
- package/dist/server/adapters/uws-adapter.js.map +1 -0
- package/dist/server/app.d.ts +10 -31
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +20 -135
- package/dist/server/app.js.map +1 -1
- package/dist/server/bootstrapper.d.ts +4 -15
- package/dist/server/bootstrapper.d.ts.map +1 -1
- package/dist/server/bootstrapper.js +30 -229
- package/dist/server/bootstrapper.js.map +1 -1
- package/dist/server/define.d.ts +2 -2
- package/dist/server/define.d.ts.map +1 -1
- package/dist/server/define.js +3 -3
- package/dist/server/define.js.map +1 -1
- package/dist/server/engines/bun-engine.d.ts +16 -0
- package/dist/server/engines/bun-engine.d.ts.map +1 -0
- package/dist/server/engines/bun-engine.js +41 -0
- package/dist/server/engines/bun-engine.js.map +1 -0
- package/dist/server/engines/engine.d.ts +16 -0
- package/dist/server/engines/engine.d.ts.map +1 -0
- package/dist/{queue/types.js → server/engines/engine.js} +1 -1
- package/dist/server/engines/engine.js.map +1 -0
- package/dist/server/engines/node-engine.d.ts +22 -0
- package/dist/server/engines/node-engine.d.ts.map +1 -0
- package/dist/server/engines/node-engine.js +130 -0
- package/dist/server/engines/node-engine.js.map +1 -0
- package/dist/server/engines/uws-engine.d.ts +16 -0
- package/dist/server/engines/uws-engine.d.ts.map +1 -0
- package/dist/server/engines/uws-engine.js +48 -0
- package/dist/server/engines/uws-engine.js.map +1 -0
- package/dist/server/request-handler.d.ts +0 -1
- package/dist/server/request-handler.d.ts.map +1 -1
- package/dist/server/request-handler.js +74 -48
- package/dist/server/request-handler.js.map +1 -1
- package/dist/server/request.d.ts +0 -8
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +0 -16
- package/dist/server/request.js.map +1 -1
- package/dist/server/response.d.ts.map +1 -1
- package/dist/server/response.js +2 -1
- package/dist/server/response.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +0 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/time.d.ts +6 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +15 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/validator/index.d.ts +1 -7
- package/dist/validator/index.d.ts.map +1 -1
- package/dist/validator/index.js +1 -5
- package/dist/validator/index.js.map +1 -1
- package/dist/validator/tex-types.d.ts +15 -2
- package/dist/validator/tex-types.d.ts.map +1 -1
- package/dist/validator/tex-types.js +8 -0
- package/dist/validator/tex-types.js.map +1 -1
- package/dist/validator/tex.d.ts.map +1 -1
- package/dist/validator/tex.js +21 -2
- package/dist/validator/tex.js.map +1 -1
- package/package.json +9 -151
- package/dist/adapters/aws-lambda.d.ts +0 -21
- package/dist/adapters/aws-lambda.d.ts.map +0 -1
- package/dist/adapters/aws-lambda.js +0 -125
- package/dist/adapters/aws-lambda.js.map +0 -1
- package/dist/adapters/bun.d.ts +0 -9
- package/dist/adapters/bun.d.ts.map +0 -1
- package/dist/adapters/bun.js +0 -23
- package/dist/adapters/bun.js.map +0 -1
- package/dist/adapters/cloudflare.d.ts +0 -10
- package/dist/adapters/cloudflare.d.ts.map +0 -1
- package/dist/adapters/cloudflare.js +0 -22
- package/dist/adapters/cloudflare.js.map +0 -1
- package/dist/adapters/deno.d.ts +0 -7
- package/dist/adapters/deno.d.ts.map +0 -1
- package/dist/adapters/deno.js +0 -21
- package/dist/adapters/deno.js.map +0 -1
- package/dist/adapters/fastly.d.ts +0 -6
- package/dist/adapters/fastly.d.ts.map +0 -1
- package/dist/adapters/fastly.js +0 -20
- package/dist/adapters/fastly.js.map +0 -1
- package/dist/adapters/fetch.d.ts +0 -30
- package/dist/adapters/fetch.d.ts.map +0 -1
- package/dist/adapters/fetch.js +0 -119
- package/dist/adapters/fetch.js.map +0 -1
- package/dist/adapters/index.d.ts +0 -9
- package/dist/adapters/index.d.ts.map +0 -1
- package/dist/adapters/index.js +0 -28
- package/dist/adapters/index.js.map +0 -1
- package/dist/adapters/netlify.d.ts +0 -8
- package/dist/adapters/netlify.d.ts.map +0 -1
- package/dist/adapters/netlify.js +0 -20
- package/dist/adapters/netlify.js.map +0 -1
- package/dist/adapters/vercel.d.ts +0 -17
- package/dist/adapters/vercel.d.ts.map +0 -1
- package/dist/adapters/vercel.js +0 -23
- package/dist/adapters/vercel.js.map +0 -1
- package/dist/auth/index.d.ts +0 -8
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js +0 -49
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/jwt.d.ts +0 -20
- package/dist/auth/jwt.d.ts.map +0 -1
- package/dist/auth/jwt.js +0 -59
- package/dist/auth/jwt.js.map +0 -1
- package/dist/auth/oauth/core.d.ts +0 -96
- package/dist/auth/oauth/core.d.ts.map +0 -1
- package/dist/auth/oauth/core.js +0 -203
- package/dist/auth/oauth/core.js.map +0 -1
- package/dist/auth/oauth/index.d.ts +0 -45
- package/dist/auth/oauth/index.d.ts.map +0 -1
- package/dist/auth/oauth/index.js +0 -64
- package/dist/auth/oauth/index.js.map +0 -1
- package/dist/auth/oauth/middleware.d.ts +0 -63
- package/dist/auth/oauth/middleware.d.ts.map +0 -1
- package/dist/auth/oauth/middleware.js +0 -164
- package/dist/auth/oauth/middleware.js.map +0 -1
- package/dist/auth/oauth/providers/custom.d.ts +0 -41
- package/dist/auth/oauth/providers/custom.d.ts.map +0 -1
- package/dist/auth/oauth/providers/custom.js +0 -204
- package/dist/auth/oauth/providers/custom.js.map +0 -1
- package/dist/auth/oauth/providers/discord.d.ts +0 -23
- package/dist/auth/oauth/providers/discord.d.ts.map +0 -1
- package/dist/auth/oauth/providers/discord.js +0 -130
- package/dist/auth/oauth/providers/discord.js.map +0 -1
- package/dist/auth/oauth/providers/facebook.d.ts +0 -28
- package/dist/auth/oauth/providers/facebook.d.ts.map +0 -1
- package/dist/auth/oauth/providers/facebook.js +0 -124
- package/dist/auth/oauth/providers/facebook.js.map +0 -1
- package/dist/auth/oauth/providers/github.d.ts +0 -25
- package/dist/auth/oauth/providers/github.d.ts.map +0 -1
- package/dist/auth/oauth/providers/github.js +0 -132
- package/dist/auth/oauth/providers/github.js.map +0 -1
- package/dist/auth/oauth/providers/google.d.ts +0 -23
- package/dist/auth/oauth/providers/google.d.ts.map +0 -1
- package/dist/auth/oauth/providers/google.js +0 -134
- package/dist/auth/oauth/providers/google.js.map +0 -1
- package/dist/auth/oauth/providers/microsoft.d.ts +0 -28
- package/dist/auth/oauth/providers/microsoft.d.ts.map +0 -1
- package/dist/auth/oauth/providers/microsoft.js +0 -136
- package/dist/auth/oauth/providers/microsoft.js.map +0 -1
- package/dist/auth/oauth/types.d.ts +0 -158
- package/dist/auth/oauth/types.d.ts.map +0 -1
- package/dist/auth/oauth/types.js +0 -4
- package/dist/auth/oauth/types.js.map +0 -1
- package/dist/auth/password.d.ts +0 -25
- package/dist/auth/password.d.ts.map +0 -1
- package/dist/auth/password.js +0 -93
- package/dist/auth/password.js.map +0 -1
- package/dist/auth/rbac.d.ts +0 -10
- package/dist/auth/rbac.d.ts.map +0 -1
- package/dist/auth/rbac.js +0 -34
- package/dist/auth/rbac.js.map +0 -1
- package/dist/auth/session.d.ts +0 -26
- package/dist/auth/session.d.ts.map +0 -1
- package/dist/auth/session.js +0 -134
- package/dist/auth/session.js.map +0 -1
- package/dist/cache/index.d.ts +0 -4
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/index.js +0 -25
- package/dist/cache/index.js.map +0 -1
- package/dist/cache/store.d.ts +0 -58
- package/dist/cache/store.d.ts.map +0 -1
- package/dist/cache/store.js +0 -298
- package/dist/cache/store.js.map +0 -1
- package/dist/cron/parser.d.ts +0 -2
- package/dist/cron/parser.d.ts.map +0 -1
- package/dist/cron/parser.js +0 -52
- package/dist/cron/parser.js.map +0 -1
- package/dist/cron/scheduler.d.ts +0 -23
- package/dist/cron/scheduler.d.ts.map +0 -1
- package/dist/cron/scheduler.js +0 -114
- package/dist/cron/scheduler.js.map +0 -1
- package/dist/database/adapters/mongodb.d.ts +0 -58
- package/dist/database/adapters/mongodb.d.ts.map +0 -1
- package/dist/database/adapters/mongodb.js +0 -264
- package/dist/database/adapters/mongodb.js.map +0 -1
- package/dist/database/adapters/mysql.d.ts +0 -27
- package/dist/database/adapters/mysql.d.ts.map +0 -1
- package/dist/database/adapters/mysql.js +0 -188
- package/dist/database/adapters/mysql.js.map +0 -1
- package/dist/database/adapters/postgres.d.ts +0 -28
- package/dist/database/adapters/postgres.d.ts.map +0 -1
- package/dist/database/adapters/postgres.js +0 -174
- package/dist/database/adapters/postgres.js.map +0 -1
- package/dist/database/adapters/sqlite.d.ts +0 -27
- package/dist/database/adapters/sqlite.d.ts.map +0 -1
- package/dist/database/adapters/sqlite.js +0 -149
- package/dist/database/adapters/sqlite.js.map +0 -1
- package/dist/database/index.d.ts +0 -42
- package/dist/database/index.d.ts.map +0 -1
- package/dist/database/index.js +0 -58
- package/dist/database/index.js.map +0 -1
- package/dist/database/manager.d.ts +0 -141
- package/dist/database/manager.d.ts.map +0 -1
- package/dist/database/manager.js +0 -337
- package/dist/database/manager.js.map +0 -1
- package/dist/database/migration.d.ts +0 -57
- package/dist/database/migration.d.ts.map +0 -1
- package/dist/database/migration.js +0 -329
- package/dist/database/migration.js.map +0 -1
- package/dist/database/query-builder.d.ts +0 -95
- package/dist/database/query-builder.d.ts.map +0 -1
- package/dist/database/query-builder.js +0 -404
- package/dist/database/query-builder.js.map +0 -1
- package/dist/database/sql/index.d.ts +0 -18
- package/dist/database/sql/index.d.ts.map +0 -1
- package/dist/database/sql/index.js +0 -74
- package/dist/database/sql/index.js.map +0 -1
- package/dist/database/sql/schema.d.ts +0 -38
- package/dist/database/sql/schema.d.ts.map +0 -1
- package/dist/database/sql/schema.js +0 -80
- package/dist/database/sql/schema.js.map +0 -1
- package/dist/database/synchronizer.d.ts +0 -12
- package/dist/database/synchronizer.d.ts.map +0 -1
- package/dist/database/synchronizer.js +0 -82
- package/dist/database/synchronizer.js.map +0 -1
- package/dist/database/types.d.ts +0 -184
- package/dist/database/types.d.ts.map +0 -1
- package/dist/database/types.js +0 -4
- package/dist/database/types.js.map +0 -1
- package/dist/dataloader/dataloader.d.ts +0 -23
- package/dist/dataloader/dataloader.d.ts.map +0 -1
- package/dist/dataloader/dataloader.js +0 -98
- package/dist/dataloader/dataloader.js.map +0 -1
- package/dist/dataloader/index.d.ts +0 -3
- package/dist/dataloader/index.d.ts.map +0 -1
- package/dist/dataloader/index.js +0 -19
- package/dist/dataloader/index.js.map +0 -1
- package/dist/dataloader/registry.d.ts +0 -17
- package/dist/dataloader/registry.d.ts.map +0 -1
- package/dist/dataloader/registry.js +0 -47
- package/dist/dataloader/registry.js.map +0 -1
- package/dist/dev/dep-graph.d.ts +0 -2
- package/dist/dev/dep-graph.d.ts.map +0 -1
- package/dist/dev/dep-graph.js +0 -111
- package/dist/dev/dep-graph.js.map +0 -1
- package/dist/dev/hot-reload.d.ts +0 -30
- package/dist/dev/hot-reload.d.ts.map +0 -1
- package/dist/dev/hot-reload.js +0 -262
- package/dist/dev/hot-reload.js.map +0 -1
- package/dist/docs/content/adapters.mdx +0 -199
- package/dist/docs/content/cache.mdx +0 -239
- package/dist/docs/content/circuit-breaker.mdx +0 -130
- package/dist/docs/content/cron.mdx +0 -109
- package/dist/docs/content/database.mdx +0 -278
- package/dist/docs/content/gateways.mdx +0 -376
- package/dist/docs/content/oauth.mdx +0 -179
- package/dist/docs/content/queues.mdx +0 -177
- package/dist/docs/content/rpc.mdx +0 -146
- package/dist/docs/content/sse.mdx +0 -159
- package/dist/docs/content/websockets.mdx +0 -289
- package/dist/docs/integrations/README.md +0 -23
- package/dist/docs/integrations/jwt.mdx +0 -151
- package/dist/docs/integrations/mongo.mdx +0 -183
- package/dist/docs/integrations/observability.mdx +0 -125
- package/dist/docs/integrations/openai.mdx +0 -108
- package/dist/docs/integrations/postgres.mdx +0 -190
- package/dist/docs/integrations/posthog.mdx +0 -122
- package/dist/docs/integrations/redis.mdx +0 -141
- package/dist/docs/integrations/resend.mdx +0 -117
- package/dist/docs/integrations/s3.mdx +0 -122
- package/dist/docs/integrations/swagger.mdx +0 -113
- package/dist/docs/reference/adapters.mdx +0 -130
- package/dist/docs/reference/auth.mdx +0 -183
- package/dist/docs/reference/cache.mdx +0 -132
- package/dist/docs/reference/circuit-breaker.mdx +0 -71
- package/dist/docs/reference/queue.mdx +0 -155
- package/dist/docs/reference/storage.mdx +0 -116
- package/dist/docs/reference/swagger.mdx +0 -132
- package/dist/integrations/drizzle.d.ts +0 -10
- package/dist/integrations/drizzle.d.ts.map +0 -1
- package/dist/integrations/drizzle.js +0 -34
- package/dist/integrations/drizzle.js.map +0 -1
- package/dist/integrations/jwt.d.ts +0 -12
- package/dist/integrations/jwt.d.ts.map +0 -1
- package/dist/integrations/jwt.js +0 -29
- package/dist/integrations/jwt.js.map +0 -1
- package/dist/integrations/mongodb.d.ts +0 -13
- package/dist/integrations/mongodb.d.ts.map +0 -1
- package/dist/integrations/mongodb.js +0 -48
- package/dist/integrations/mongodb.js.map +0 -1
- package/dist/integrations/mongoose.d.ts +0 -13
- package/dist/integrations/mongoose.d.ts.map +0 -1
- package/dist/integrations/mongoose.js +0 -84
- package/dist/integrations/mongoose.js.map +0 -1
- package/dist/integrations/openai.d.ts +0 -12
- package/dist/integrations/openai.d.ts.map +0 -1
- package/dist/integrations/openai.js +0 -47
- package/dist/integrations/openai.js.map +0 -1
- package/dist/integrations/postgres.d.ts +0 -13
- package/dist/integrations/postgres.d.ts.map +0 -1
- package/dist/integrations/postgres.js +0 -55
- package/dist/integrations/postgres.js.map +0 -1
- package/dist/integrations/posthog.d.ts +0 -13
- package/dist/integrations/posthog.d.ts.map +0 -1
- package/dist/integrations/posthog.js +0 -49
- package/dist/integrations/posthog.js.map +0 -1
- package/dist/integrations/prisma.d.ts +0 -10
- package/dist/integrations/prisma.d.ts.map +0 -1
- package/dist/integrations/prisma.js +0 -39
- package/dist/integrations/prisma.js.map +0 -1
- package/dist/integrations/redis.d.ts +0 -12
- package/dist/integrations/redis.d.ts.map +0 -1
- package/dist/integrations/redis.js +0 -48
- package/dist/integrations/redis.js.map +0 -1
- package/dist/integrations/resend.d.ts +0 -12
- package/dist/integrations/resend.d.ts.map +0 -1
- package/dist/integrations/resend.js +0 -47
- package/dist/integrations/resend.js.map +0 -1
- package/dist/integrations/s3.d.ts +0 -15
- package/dist/integrations/s3.d.ts.map +0 -1
- package/dist/integrations/s3.js +0 -60
- package/dist/integrations/s3.js.map +0 -1
- package/dist/integrations/supabase.d.ts +0 -13
- package/dist/integrations/supabase.d.ts.map +0 -1
- package/dist/integrations/supabase.js +0 -51
- package/dist/integrations/supabase.js.map +0 -1
- package/dist/middleware/cache.d.ts +0 -21
- package/dist/middleware/cache.d.ts.map +0 -1
- package/dist/middleware/cache.js +0 -156
- package/dist/middleware/cache.js.map +0 -1
- package/dist/observability/health.d.ts +0 -23
- package/dist/observability/health.d.ts.map +0 -1
- package/dist/observability/health.js +0 -49
- package/dist/observability/health.js.map +0 -1
- package/dist/observability/index.d.ts +0 -4
- package/dist/observability/index.d.ts.map +0 -1
- package/dist/observability/index.js +0 -10
- package/dist/observability/index.js.map +0 -1
- package/dist/observability/metrics.d.ts +0 -6
- package/dist/observability/metrics.d.ts.map +0 -1
- package/dist/observability/metrics.js +0 -60
- package/dist/observability/metrics.js.map +0 -1
- package/dist/observability/otel.d.ts +0 -27
- package/dist/observability/otel.d.ts.map +0 -1
- package/dist/observability/otel.js +0 -45
- package/dist/observability/otel.js.map +0 -1
- package/dist/observability/prometheus.d.ts +0 -30
- package/dist/observability/prometheus.d.ts.map +0 -1
- package/dist/observability/prometheus.js +0 -31
- package/dist/observability/prometheus.js.map +0 -1
- package/dist/queue/client.d.ts +0 -13
- package/dist/queue/client.d.ts.map +0 -1
- package/dist/queue/client.js +0 -83
- package/dist/queue/client.js.map +0 -1
- package/dist/queue/drivers/MemoryDriver.d.ts +0 -21
- package/dist/queue/drivers/MemoryDriver.d.ts.map +0 -1
- package/dist/queue/drivers/MemoryDriver.js +0 -176
- package/dist/queue/drivers/MemoryDriver.js.map +0 -1
- package/dist/queue/drivers/RedisDriver.d.ts +0 -19
- package/dist/queue/drivers/RedisDriver.d.ts.map +0 -1
- package/dist/queue/drivers/RedisDriver.js +0 -130
- package/dist/queue/drivers/RedisDriver.js.map +0 -1
- package/dist/queue/index.d.ts +0 -18
- package/dist/queue/index.d.ts.map +0 -1
- package/dist/queue/index.js +0 -37
- package/dist/queue/index.js.map +0 -1
- package/dist/queue/manager.d.ts +0 -18
- package/dist/queue/manager.d.ts.map +0 -1
- package/dist/queue/manager.js +0 -59
- package/dist/queue/manager.js.map +0 -1
- package/dist/queue/types.d.ts +0 -55
- package/dist/queue/types.d.ts.map +0 -1
- package/dist/queue/types.js.map +0 -1
- package/dist/queue/worker.d.ts +0 -18
- package/dist/queue/worker.d.ts.map +0 -1
- package/dist/queue/worker.js +0 -176
- package/dist/queue/worker.js.map +0 -1
- package/dist/router/gateway.d.ts.map +0 -1
- package/dist/router/gateway.js +0 -11
- package/dist/router/gateway.js.map +0 -1
- package/dist/server/bun-adapter.d.ts.map +0 -1
- package/dist/server/bun-adapter.js.map +0 -1
- package/dist/server/sse.d.ts +0 -16
- package/dist/server/sse.d.ts.map +0 -1
- package/dist/server/sse.js +0 -51
- package/dist/server/sse.js.map +0 -1
- package/dist/server/uws-adapter.d.ts.map +0 -1
- package/dist/server/uws-adapter.js.map +0 -1
- package/dist/storage/index.d.ts +0 -15
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js +0 -7
- package/dist/storage/index.js.map +0 -1
- package/dist/swagger/index.d.ts +0 -9
- package/dist/swagger/index.d.ts.map +0 -1
- package/dist/swagger/index.js +0 -165
- package/dist/swagger/index.js.map +0 -1
- package/dist/threads/pool.d.ts +0 -14
- package/dist/threads/pool.d.ts.map +0 -1
- package/dist/threads/pool.js +0 -93
- package/dist/threads/pool.js.map +0 -1
- package/dist/threads/worker-runner.d.ts +0 -2
- package/dist/threads/worker-runner.d.ts.map +0 -1
- package/dist/threads/worker-runner.js +0 -71
- package/dist/threads/worker-runner.js.map +0 -1
- package/dist/validator/validator.d.ts +0 -360
- package/dist/validator/validator.d.ts.map +0 -1
- package/dist/validator/validator.js +0 -931
- package/dist/validator/validator.js.map +0 -1
- package/dist/websocket/orchestrator.d.ts +0 -11
- package/dist/websocket/orchestrator.d.ts.map +0 -1
- package/dist/websocket/orchestrator.js +0 -238
- package/dist/websocket/orchestrator.js.map +0 -1
- package/dist/websocket/server.d.ts +0 -66
- package/dist/websocket/server.d.ts.map +0 -1
- package/dist/websocket/server.js +0 -158
- package/dist/websocket/server.js.map +0 -1
- package/dist/websocket/socket.d.ts +0 -119
- package/dist/websocket/socket.d.ts.map +0 -1
- package/dist/websocket/socket.js +0 -242
- package/dist/websocket/socket.js.map +0 -1
|
@@ -5,9 +5,9 @@ nextTitle: "Modules & Plugins"
|
|
|
5
5
|
|
|
6
6
|
# Middleware
|
|
7
7
|
|
|
8
|
-
ExisJS comes with a collection of built-in middleware out of the box.
|
|
8
|
+
ExisJS comes with a collection of built-in middleware out of the box.
|
|
9
9
|
|
|
10
|
-
ExisJS provides first-party implementations for features like CORS, Request Logging, Backpressure, and Deduplication.
|
|
10
|
+
ExisJS provides first-party implementations for features like CORS, Request Logging, Backpressure, In-Memory Rate Limiting, Idempotency, and Deduplication.
|
|
11
11
|
|
|
12
12
|
All middleware can be imported directly from the `exisjs/middleware` package.
|
|
13
13
|
|
|
@@ -17,58 +17,41 @@ All middleware can be imported directly from the `exisjs/middleware` package.
|
|
|
17
17
|
|
|
18
18
|
ExisJS gives you granular control over where your middleware executes:
|
|
19
19
|
|
|
20
|
-
1. **Globally (`server.ts`)**: Applies to every request hitting your server.
|
|
21
|
-
2. **Folder-Scoped (`
|
|
20
|
+
1. **Globally (`server.ts`)**: Applies to every request hitting your server via `app.use()`.
|
|
21
|
+
2. **Folder-Scoped (`boundary.ts`)**: Applies to routes inside that folder and all subfolders automatically.
|
|
22
22
|
3. **Route-Scoped (`route.ts`)**: Applies only to a specific endpoint.
|
|
23
23
|
|
|
24
|
-
```typescript filename="src/http/admin/
|
|
25
|
-
import {
|
|
24
|
+
```typescript filename="src/http/admin/boundary.ts"
|
|
25
|
+
import { defineBoundary } from 'exisjs/router'
|
|
26
|
+
import type { Request, Response, Next } from 'exisjs/router'
|
|
26
27
|
import { requestLogger } from 'exisjs/middleware'
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
]
|
|
33
|
-
})
|
|
29
|
+
export const config = defineBoundary({})
|
|
30
|
+
|
|
31
|
+
// Auto-detected chain step for /admin/*
|
|
32
|
+
export const logger = requestLogger({ level: 'debug' })
|
|
34
33
|
```
|
|
35
34
|
|
|
36
35
|
### Middleware vs Inline Execution
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
If you try to call an authentication function *inline* inside the handler, the `user` variable will be `undefined` because destructuring occurs at the moment the handler is invoked—before the inline function has a chance to execute!
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
// ❌ BAD: Destructuring happens before requireAuth mutates the request
|
|
44
|
-
create: route.post('/', {
|
|
45
|
-
async handle({ user, req }) {
|
|
46
|
-
requireAuth(req);
|
|
47
|
-
console.log(user); // undefined
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
// ✅ GOOD: Middleware runs first, so `user` is fully populated and strongly typed
|
|
52
|
-
create: route.post('/', {
|
|
53
|
-
middleware: [requireAuth],
|
|
54
|
-
async handle({ user }) {
|
|
55
|
-
console.log(user); // Populated and typed
|
|
56
|
-
}
|
|
57
|
-
})
|
|
58
|
-
```
|
|
37
|
+
Middleware executes **before** your route handler. If you are using custom typed contexts to destructure variables (e.g., `async handle({ user })`), you must use middleware to populate `req.user`.
|
|
59
38
|
|
|
60
39
|
#### Functional Paradigm
|
|
61
40
|
|
|
62
41
|
```typescript filename="src/http/route.ts"
|
|
63
42
|
import { controller, route } from 'exisjs/router'
|
|
64
43
|
import { validate } from 'exisjs/middleware'
|
|
44
|
+
import { tex } from 'exisjs/validator'
|
|
45
|
+
|
|
46
|
+
const mySchema = {
|
|
47
|
+
body: tex.object({ name: tex.string() })
|
|
48
|
+
}
|
|
65
49
|
|
|
66
50
|
export default controller({
|
|
67
|
-
// This middleware ONLY runs for this specific endpoint
|
|
68
51
|
create: route.post('/', {
|
|
69
52
|
middlewares: [validate(mySchema)],
|
|
70
|
-
handle(req
|
|
71
|
-
return { ok: true }
|
|
53
|
+
handle({ req }) {
|
|
54
|
+
return { ok: true, name: req.body.name }
|
|
72
55
|
}
|
|
73
56
|
})
|
|
74
57
|
})
|
|
@@ -79,10 +62,14 @@ export default controller({
|
|
|
79
62
|
```typescript filename="src/http/route.ts"
|
|
80
63
|
import { Controller, Post, Use } from 'exisjs/decorators'
|
|
81
64
|
import { validate } from 'exisjs/middleware'
|
|
65
|
+
import { tex } from 'exisjs/validator'
|
|
66
|
+
|
|
67
|
+
const mySchema = {
|
|
68
|
+
body: tex.object({ name: tex.string() })
|
|
69
|
+
}
|
|
82
70
|
|
|
83
71
|
@Controller()
|
|
84
72
|
export default class MyController {
|
|
85
|
-
// This middleware ONLY runs for this specific endpoint
|
|
86
73
|
@Use(validate(mySchema))
|
|
87
74
|
@Post('/')
|
|
88
75
|
async create() {
|
|
@@ -95,9 +82,9 @@ export default class MyController {
|
|
|
95
82
|
|
|
96
83
|
## 1. CORS
|
|
97
84
|
|
|
98
|
-
The `cors` middleware handles Cross-Origin Resource Sharing.
|
|
85
|
+
The `cors` middleware handles Cross-Origin Resource Sharing.
|
|
99
86
|
|
|
100
|
-
The recommended practice in ExisJS is to configure CORS globally in your **`exis.config.ts`** file
|
|
87
|
+
The recommended practice in ExisJS is to configure CORS globally in your **`exis.config.ts`** file or per-folder in `boundary.ts`.
|
|
101
88
|
|
|
102
89
|
```typescript filename="exis.config.ts"
|
|
103
90
|
import { defineConfig } from 'exisjs/config'
|
|
@@ -108,65 +95,30 @@ export default async () => defineConfig({
|
|
|
108
95
|
methods: ['GET', 'POST', 'OPTIONS'],
|
|
109
96
|
credentials: true,
|
|
110
97
|
maxAge: 86400,
|
|
111
|
-
preflightContinue: true // Set this to true if you want OPTIONS requests to hit your custom route.options() handlers!
|
|
112
98
|
}
|
|
113
99
|
})
|
|
114
100
|
```
|
|
115
101
|
|
|
116
|
-
By default, ExisJS intercepts `OPTIONS` requests at the middleware level and responds with a `204 No Content` (and the appropriate CORS headers) to save server resources. However, if you need to run custom logic on preflight requests—such as hitting a specific `route.options('/', ...)` handler or a `@Options()` decorated controller method—you can set `preflightContinue: true`.
|
|
117
|
-
|
|
118
|
-
You can also configure CORS locally per-route by passing it to your controller config or gateway.
|
|
119
|
-
|
|
120
102
|
---
|
|
121
103
|
|
|
122
104
|
## 2. Request Logger
|
|
123
105
|
|
|
124
|
-
ExisJS uses
|
|
106
|
+
ExisJS uses Pino under the hood. The `requestLogger` injects a request-scoped logger instance (`req.log`) and times response cycles automatically.
|
|
125
107
|
|
|
126
108
|
```typescript filename="src/http/server.ts"
|
|
127
109
|
import { requestLogger } from 'exisjs/middleware'
|
|
128
110
|
|
|
129
111
|
app.use(requestLogger({
|
|
130
112
|
level: 'debug',
|
|
131
|
-
pretty: true
|
|
113
|
+
pretty: true
|
|
132
114
|
}))
|
|
133
115
|
```
|
|
134
116
|
|
|
135
|
-
#### Functional Paradigm
|
|
136
|
-
|
|
137
|
-
```typescript filename="src/http/route.ts"
|
|
138
|
-
import { controller, route } from 'exisjs/router'
|
|
139
|
-
|
|
140
|
-
export default controller({
|
|
141
|
-
index: route.get('/', {
|
|
142
|
-
handle(req, res) {
|
|
143
|
-
req.log.info({ userId: 123 }, "User hit the index route")
|
|
144
|
-
return { ok: true }
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
#### Class-Based (OOP) Paradigm
|
|
151
|
-
|
|
152
|
-
```typescript filename="src/http/route.ts"
|
|
153
|
-
import { Controller, Get, Req } from 'exisjs/decorators'
|
|
154
|
-
|
|
155
|
-
@Controller()
|
|
156
|
-
export default class MyController {
|
|
157
|
-
@Get('/')
|
|
158
|
-
async index(@Req() req: any) {
|
|
159
|
-
req.log.info({ userId: 123 }, "User hit the index route")
|
|
160
|
-
return { ok: true }
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
117
|
---
|
|
166
118
|
|
|
167
119
|
## 3. Request ID
|
|
168
120
|
|
|
169
|
-
Injects a unique `X-Request-Id` into every incoming request and outgoing response header.
|
|
121
|
+
Injects a unique `X-Request-Id` into every incoming request and outgoing response header. Supports distributed tracing headers (`traceparent`, `x-b3-traceid`).
|
|
170
122
|
|
|
171
123
|
```typescript filename="src/http/server.ts"
|
|
172
124
|
import { requestId } from 'exisjs/middleware'
|
|
@@ -174,192 +126,37 @@ import { requestId } from 'exisjs/middleware'
|
|
|
174
126
|
app.use(requestId())
|
|
175
127
|
```
|
|
176
128
|
|
|
177
|
-
#### Functional Paradigm
|
|
178
|
-
|
|
179
|
-
```typescript filename="src/http/route.ts"
|
|
180
|
-
import { controller, route } from 'exisjs/router'
|
|
181
|
-
|
|
182
|
-
export default controller({
|
|
183
|
-
index: route.get('/', {
|
|
184
|
-
handle(req, res) {
|
|
185
|
-
console.log("Trace ID:", req.requestId)
|
|
186
|
-
return { ok: true }
|
|
187
|
-
}
|
|
188
|
-
})
|
|
189
|
-
})
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
#### Class-Based (OOP) Paradigm
|
|
193
|
-
|
|
194
|
-
```typescript filename="src/http/route.ts"
|
|
195
|
-
import { Controller, Get, Req } from 'exisjs/decorators'
|
|
196
|
-
|
|
197
|
-
@Controller()
|
|
198
|
-
export default class MyController {
|
|
199
|
-
@Get('/')
|
|
200
|
-
async index(@Req() req: any) {
|
|
201
|
-
console.log("Trace ID:", req.requestId)
|
|
202
|
-
return { ok: true }
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
## 4. Static File Serving
|
|
210
|
-
|
|
211
|
-
A static file server that resolves MIME types, streams files, and provides Cache-Control configuration out of the box.
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
import { serveStatic } from 'exisjs/middleware'
|
|
215
|
-
import path from 'node:path'
|
|
216
|
-
|
|
217
|
-
app.use('/public', serveStatic(path.join(process.cwd(), 'public'), {
|
|
218
|
-
maxAge: 31536000 // Cache for 1 year
|
|
219
|
-
}))
|
|
220
|
-
```
|
|
221
|
-
|
|
222
129
|
---
|
|
223
130
|
|
|
224
|
-
##
|
|
225
|
-
|
|
226
|
-
ExisJS bundles several security middlewares. (We will cover these in the Security documentation, but here is a preview):
|
|
131
|
+
## 4. Rate Limiting (In-Memory / Native Off-Heap)
|
|
227
132
|
|
|
228
|
-
-
|
|
229
|
-
- **`hpp()`**: Prevents HTTP Parameter Pollution attacks.
|
|
230
|
-
- **`dbSanitize()`**: A universal scraper that protects against NoSQL injection patterns (`$where` and other malicious operators).
|
|
231
|
-
- **`timeout(ms)`**: Kills requests that hang longer than a specified duration.
|
|
232
|
-
- **`ipFilter()`**: Restricts access based on IP Whitelists/Blacklists.
|
|
133
|
+
ExisJS provides high-performance rate limiting powered by Rust native memory:
|
|
233
134
|
|
|
234
|
-
```typescript
|
|
235
|
-
import {
|
|
236
|
-
|
|
237
|
-
app.use(helmet())
|
|
238
|
-
app.use(dbSanitize({ mongo: true }))
|
|
239
|
-
app.use(timeout(5000)) // 5 second timeout
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
---
|
|
135
|
+
```typescript filename="src/http/boundary.ts"
|
|
136
|
+
import { rateLimit } from 'exisjs/middleware'
|
|
243
137
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
- **`cache()`**: An in-memory route caching engine. Requires a `keyGenerator` to prevent data leaks.
|
|
249
|
-
- **`dedupe()`**: Request deduplication (In-flight request collapsing). If 1,000 users hit a heavy `/stats` route at the exact same millisecond, ExisJS will only compute it **once**, and send the same response to all 1,000 users simultaneously. Requires a `keyGenerator`.
|
|
250
|
-
- **`backpressure()`**: Protects your server from traffic spikes by shedding load or queuing requests when the Node.js Event Loop lags.
|
|
251
|
-
|
|
252
|
-
> [!WARNING]
|
|
253
|
-
> **Authentication Leak Hazard**: When using `cache()` or `dedupe()` on authenticated routes, you **must** include the user's ID or session token in your `keyGenerator`. Failing to do so will result in User B receiving a cached/deduped response generated for User A.
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## 7. Interceptors & Error Filters
|
|
258
|
-
|
|
259
|
-
As covered in our [Error Handling](/docs/errors) guide, you can centrally mutate responses or catch specific Exception classes using `intercept()` and `catchError()`.
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
import { intercept, catchError } from 'exisjs/middleware'
|
|
263
|
-
|
|
264
|
-
// Wrap all responses in { data: ... }
|
|
265
|
-
app.use(intercept((data) => ({ data })))
|
|
266
|
-
|
|
267
|
-
// Catch specific errors
|
|
268
|
-
app.use(catchError(DatabaseError, (err, req, res) => {
|
|
269
|
-
res.status(503).json({ error: 'Database Offline' })
|
|
270
|
-
}))
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
---
|
|
274
|
-
|
|
275
|
-
## 8. Schema Validation
|
|
276
|
-
|
|
277
|
-
ExisJS includes a validation engine. You can validate `body`, `query`, or `params` directly at the middleware layer. If validation fails, it automatically rejects the request with a structured HTTP 400 JSON response.
|
|
278
|
-
|
|
279
|
-
#### Functional Paradigm
|
|
280
|
-
|
|
281
|
-
```typescript filename="src/http/users/route.ts"
|
|
282
|
-
import { controller, route } from 'exisjs/router'
|
|
283
|
-
import { validate } from 'exisjs/middleware'
|
|
284
|
-
import { tex } from 'exisjs/validator'
|
|
285
|
-
|
|
286
|
-
const createUserSchema = {
|
|
287
|
-
body: tex.object({
|
|
288
|
-
email: tex.email(),
|
|
289
|
-
age: tex.number({ min: 18 })
|
|
290
|
-
})
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export default controller({
|
|
294
|
-
// Automatically rejects invalid payloads with 400 Bad Request
|
|
295
|
-
create: route.post('/', {
|
|
296
|
-
middlewares: [validate(createUserSchema)],
|
|
297
|
-
handle(req, res) {
|
|
298
|
-
// req.body is fully validated, but we also type-cast it safely
|
|
299
|
-
const body = req.body as { email: string, age: number }
|
|
300
|
-
|
|
301
|
-
return { success: true, email: body.email }
|
|
302
|
-
}
|
|
303
|
-
})
|
|
138
|
+
export const limiter = rateLimit({
|
|
139
|
+
windowMs: 60000,
|
|
140
|
+
max: 100,
|
|
304
141
|
})
|
|
305
142
|
```
|
|
306
143
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
```typescript filename="src/http/users/route.ts"
|
|
310
|
-
import { Controller, Post, Use, Body } from 'exisjs/decorators'
|
|
311
|
-
import { validate } from 'exisjs/middleware'
|
|
312
|
-
import { tex } from 'exisjs/validator'
|
|
313
|
-
|
|
314
|
-
const createUserSchema = {
|
|
315
|
-
body: tex.object({
|
|
316
|
-
email: tex.email(),
|
|
317
|
-
age: tex.number({ min: 18 })
|
|
318
|
-
})
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
@Controller()
|
|
322
|
-
export default class UsersController {
|
|
323
|
-
// Automatically rejects invalid payloads with 400 Bad Request
|
|
324
|
-
@Use(validate(createUserSchema))
|
|
325
|
-
@Post('/')
|
|
326
|
-
async create(@Body() body: { email: string, age: number }) {
|
|
327
|
-
return { success: true, email: body.email }
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
```
|
|
144
|
+
> [!NOTE]
|
|
145
|
+
> Core rate limiting runs completely off-heap in-memory. For Redis-backed distributed rate limiting across clusters, use `@exisjs/cache`.
|
|
331
146
|
|
|
332
147
|
---
|
|
333
148
|
|
|
334
|
-
##
|
|
335
|
-
|
|
336
|
-
Idempotency ensures that retrying an identical request multiple times (e.g., due to network timeouts) will not result in duplicate operations on the server. ExisJS provides a Redis-backed (or in-memory) idempotency engine.
|
|
337
|
-
|
|
338
|
-
#### Functional Paradigm
|
|
339
|
-
|
|
340
|
-
```typescript
|
|
341
|
-
import { controller, route } from 'exisjs/router'
|
|
342
|
-
import { IdempotentMiddleware } from 'exisjs/middleware'
|
|
343
|
-
|
|
344
|
-
export default controller({
|
|
345
|
-
checkout: route.post('/checkout', {
|
|
346
|
-
middlewares: [IdempotentMiddleware({ ttl: 86400, headerName: 'Idempotency-Key' })],
|
|
347
|
-
handle(req, res) {
|
|
348
|
-
return { success: true }
|
|
349
|
-
}
|
|
350
|
-
})
|
|
351
|
-
})
|
|
352
|
-
```
|
|
149
|
+
## 5. Idempotency (In-Memory / Native Off-Heap)
|
|
353
150
|
|
|
354
|
-
|
|
151
|
+
Idempotency caches responses based on the `Idempotency-Key` header, preventing duplicate mutations:
|
|
355
152
|
|
|
356
|
-
```typescript
|
|
153
|
+
```typescript filename="src/http/checkout/route.ts"
|
|
357
154
|
import { Controller, Post, Idempotent } from 'exisjs/decorators'
|
|
358
155
|
|
|
359
|
-
@Controller()
|
|
156
|
+
@Controller('/checkout')
|
|
360
157
|
export default class CheckoutController {
|
|
361
|
-
@Idempotent({
|
|
362
|
-
@Post('/
|
|
158
|
+
@Idempotent({ ttlMs: 86400000 })
|
|
159
|
+
@Post('/')
|
|
363
160
|
async checkout() {
|
|
364
161
|
return { success: true }
|
|
365
162
|
}
|
|
@@ -368,74 +165,51 @@ export default class CheckoutController {
|
|
|
368
165
|
|
|
369
166
|
---
|
|
370
167
|
|
|
371
|
-
##
|
|
168
|
+
## 6. Request Deduplication (`dedupe`)
|
|
372
169
|
|
|
373
|
-
|
|
170
|
+
If multiple clients request the exact same resource concurrently, `dedupe` collapses identical in-flight requests into a single operation:
|
|
374
171
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
172
|
+
```typescript filename="src/http/stats/route.ts"
|
|
378
173
|
import { controller, route } from 'exisjs/router'
|
|
379
|
-
import {
|
|
174
|
+
import { dedupe } from 'exisjs/middleware'
|
|
380
175
|
|
|
381
176
|
export default controller({
|
|
382
|
-
|
|
383
|
-
middlewares: [
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
keyGenerator: (req) => req.url // Critical: Define how cache keys are built
|
|
387
|
-
})
|
|
388
|
-
],
|
|
389
|
-
handle(req, res) {
|
|
390
|
-
return { success: true, books: [] }
|
|
177
|
+
getStats: route.get('/', {
|
|
178
|
+
middlewares: [dedupe({ ttlMs: 5000 })],
|
|
179
|
+
async handle() {
|
|
180
|
+
return { activeUsers: 1000 }
|
|
391
181
|
}
|
|
392
182
|
})
|
|
393
183
|
})
|
|
394
184
|
```
|
|
395
185
|
|
|
396
|
-
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 7. Static File Serving
|
|
189
|
+
|
|
190
|
+
A static file server that resolves MIME types and streams files:
|
|
397
191
|
|
|
398
192
|
```typescript
|
|
399
|
-
import {
|
|
193
|
+
import { serveStatic } from 'exisjs/middleware'
|
|
194
|
+
import path from 'node:path'
|
|
400
195
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
@Get('/popular')
|
|
405
|
-
async getPopular() {
|
|
406
|
-
return { success: true, books: [] }
|
|
407
|
-
}
|
|
408
|
-
}
|
|
196
|
+
app.use('/public', serveStatic(path.join(process.cwd(), 'public'), {
|
|
197
|
+
maxAge: 31536000
|
|
198
|
+
}))
|
|
409
199
|
```
|
|
410
200
|
|
|
411
201
|
---
|
|
412
202
|
|
|
413
|
-
##
|
|
414
|
-
|
|
415
|
-
ExisJS includes a stream-based Compression middleware. It natively hooks into the `uWebSockets` core and compresses JSON, streams, and text on-the-fly, reducing your outbound network bandwidth.
|
|
203
|
+
## 8. Compression (Gzip / Brotli / Deflate)
|
|
416
204
|
|
|
417
|
-
|
|
205
|
+
Stream-based compression middleware supporting Gzip, Deflate, and Brotli:
|
|
418
206
|
|
|
419
207
|
```typescript filename="exis.config.ts"
|
|
420
208
|
import type { ExisConfig } from 'exisjs/config'
|
|
421
209
|
|
|
422
210
|
const config: ExisConfig = {
|
|
423
|
-
|
|
424
|
-
compression: true,
|
|
211
|
+
compression: true,
|
|
425
212
|
}
|
|
426
213
|
|
|
427
214
|
export default config
|
|
428
215
|
```
|
|
429
|
-
|
|
430
|
-
If you prefer to manually apply it to specific routes or gateways instead of globally, you can import it:
|
|
431
|
-
|
|
432
|
-
```typescript filename="src/http/api/gateway.ts"
|
|
433
|
-
import { defineGateway } from 'exisjs/router'
|
|
434
|
-
import { compress } from 'exisjs/middleware'
|
|
435
|
-
|
|
436
|
-
export default defineGateway({
|
|
437
|
-
middlewares: [
|
|
438
|
-
compress() // Only compress responses within this Gateway
|
|
439
|
-
]
|
|
440
|
-
})
|
|
441
|
-
```
|
|
@@ -74,7 +74,28 @@ export default exis({
|
|
|
74
74
|
})
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### Class-Based (OOP) Paradigm (`@Module`)
|
|
80
|
+
|
|
81
|
+
For applications following the OOP paradigm, you can define modules using the `@Module` class decorator:
|
|
82
|
+
|
|
83
|
+
```typescript filename="src/modules/auth.module.ts"
|
|
84
|
+
import { Module } from 'exisjs/module'
|
|
85
|
+
import { AuthService } from './auth.service'
|
|
86
|
+
import { AuthController } from './auth.controller'
|
|
87
|
+
import { DatabaseModule } from './database.module'
|
|
88
|
+
|
|
89
|
+
@Module({
|
|
90
|
+
imports: [DatabaseModule],
|
|
91
|
+
controllers: [AuthController],
|
|
92
|
+
providers: [AuthService],
|
|
93
|
+
exports: [AuthService]
|
|
94
|
+
})
|
|
95
|
+
export class AuthModule {}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You can then register it into your server:
|
|
78
99
|
|
|
79
100
|
```typescript filename="src/http/server.ts"
|
|
80
101
|
import { Server } from 'exisjs/decorators'
|
|
@@ -134,14 +134,46 @@ import { UsersService } from './users/service'
|
|
|
134
134
|
export default class RootServer {}
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
+
### Constructor Injection (`@Inject` and `@Optional`)
|
|
138
|
+
|
|
139
|
+
In addition to property-level `inject()`, ExisJS provides full OOP constructor parameter injection with `@Inject(token)` and `@Optional()`:
|
|
140
|
+
|
|
141
|
+
```typescript filename="src/http/users/route.ts"
|
|
142
|
+
import { Controller, Get, Param, Inject, Optional } from 'exisjs/decorators'
|
|
143
|
+
import { UsersService } from './service'
|
|
144
|
+
|
|
145
|
+
@Controller('/users')
|
|
146
|
+
export default class UsersController {
|
|
147
|
+
constructor(
|
|
148
|
+
private usersService: UsersService,
|
|
149
|
+
@Inject('DATABASE_URL') private dbUrl: string,
|
|
150
|
+
@Optional() @Inject('METRICS') private metrics?: any
|
|
151
|
+
) {}
|
|
152
|
+
|
|
153
|
+
@Get('/:id')
|
|
154
|
+
async getUser(@Param('id') id: string) {
|
|
155
|
+
return this.usersService.findAll()
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
137
160
|
## Injection Scopes
|
|
138
161
|
|
|
139
162
|
For people coming from different programming language backgrounds, it might be unexpected to learn that in ExisJS, almost everything is shared across incoming requests. We have a connection pool to the database, singleton services with global state, etc. This is because Node.js doesn't follow the request/response Multi-Threaded Stateless Model.
|
|
140
163
|
|
|
141
|
-
However, there are
|
|
164
|
+
However, there are use-cases when request-based or transient lifetime is desired. ExisJS supports three provider scopes in the `@Injectable()` decorator and `app.provide()`:
|
|
142
165
|
|
|
143
166
|
- **Singleton (Default)**: A single instance of the provider is shared across the entire application.
|
|
144
167
|
- **Request**: A new instance of the provider is created exclusively for each incoming request, and garbage collected afterward.
|
|
168
|
+
- **Transient**: A brand-new instance is created every single time the dependency is requested/injected.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
@Injectable({ scope: 'transient' })
|
|
172
|
+
export class OperationContext {
|
|
173
|
+
public readonly id = crypto.randomUUID()
|
|
174
|
+
}
|
|
175
|
+
```
|
|
145
176
|
|
|
146
177
|
> [!WARNING]
|
|
147
178
|
> **Request Scope Constraints**: A provider marked as `scope: 'request'` **must** be resolved within the lifecycle of an active HTTP request. If you try to `inject()` or resolve a request-scoped provider during application startup, inside a background queue worker, or from a cron job, the container will throw a runtime error.
|
|
179
|
+
|