exisjs 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +3 -2
- package/dist/config/config.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 +2 -2
- package/dist/decorators/constants.d.ts.map +1 -1
- package/dist/decorators/constants.js +2 -2
- package/dist/decorators/constants.js.map +1 -1
- package/dist/decorators/core.d.ts +4 -3
- package/dist/decorators/core.d.ts.map +1 -1
- package/dist/decorators/core.js +7 -4
- package/dist/decorators/core.js.map +1 -1
- package/dist/decorators/middleware.d.ts +0 -10
- package/dist/decorators/middleware.d.ts.map +1 -1
- package/dist/decorators/middleware.js +0 -25
- package/dist/decorators/middleware.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 +1 -3
- package/dist/decorators/routing.js.map +1 -1
- package/dist/di/inject.d.ts +1 -2
- package/dist/di/inject.d.ts.map +1 -1
- package/dist/di/inject.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 +107 -80
- package/dist/docs/content/installation.mdx +20 -1
- package/dist/docs/content/middleware.mdx +65 -291
- 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 +24 -217
- package/dist/docs/reference/middleware.mdx +41 -217
- package/dist/docs/reference/validator.mdx +2 -5
- package/dist/error/errors.d.ts.map +1 -1
- package/dist/error/errors.js +16 -0
- package/dist/error/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- 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/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/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 +0 -4
- 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 +216 -193
- 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 +9 -30
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +19 -134
- 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/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
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "OAuth Provider System"
|
|
3
|
-
description: "ExisJS includes a fully-featured, built-in OAuth 2.0 and OpenID Connect system with native providers for Google, GitHub, Microsoft, Discord, and Facebook."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# OAuth Provider System
|
|
7
|
-
|
|
8
|
-
Implementing secure, compliant OAuth flows is notoriously difficult. ExisJS solves this by providing a unified, built-in OAuth system. It handles PKCE (Proof Key for Code Exchange), state generation for CSRF protection, and normalizes user profiles automatically.
|
|
9
|
-
|
|
10
|
-
<Info title="Functional vs OOP">
|
|
11
|
-
ExisJS natively supports both a **Functional Paradigm** and a **Class-Based OOP Paradigm** (for dependency injection and decorators). The OAuth middleware helpers can easily be used in either paradigm.
|
|
12
|
-
</Info>
|
|
13
|
-
|
|
14
|
-
## Configuration
|
|
15
|
-
|
|
16
|
-
Configure your providers globally using the `OAuthManager`. You typically do this once in your application entry point (`server.ts`).
|
|
17
|
-
|
|
18
|
-
```typescript filename="src/http/server.ts"
|
|
19
|
-
import { exis } from 'exisjs'
|
|
20
|
-
import { OAuth } from 'exisjs/auth'
|
|
21
|
-
|
|
22
|
-
export default exis({
|
|
23
|
-
async onStart(app) {
|
|
24
|
-
OAuth.configure({
|
|
25
|
-
google: {
|
|
26
|
-
clientId: process.env.GOOGLE_CLIENT_ID!,
|
|
27
|
-
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
|
28
|
-
redirectUri: 'http://localhost:3000/auth/google/callback',
|
|
29
|
-
},
|
|
30
|
-
github: {
|
|
31
|
-
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
32
|
-
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
33
|
-
redirectUri: 'http://localhost:3000/auth/github/callback',
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Routing & Middleware
|
|
41
|
-
|
|
42
|
-
ExisJS provides Express-style middleware (`oauthRedirect` and `oauthCallback`) that makes securing your routes trivial. It securely stores state/PKCE verifiers in sessions or signed cookies.
|
|
43
|
-
|
|
44
|
-
Here is how you handle the login flow using both paradigms.
|
|
45
|
-
|
|
46
|
-
#### Functional Paradigm
|
|
47
|
-
In functional routes, you wrap your handlers using standard middleware chaining techniques.
|
|
48
|
-
|
|
49
|
-
```typescript filename="src/http/auth/route.ts"
|
|
50
|
-
import { controller, route } from 'exisjs/router'
|
|
51
|
-
import { oauthRedirect, oauthCallback } from 'exisjs/auth'
|
|
52
|
-
|
|
53
|
-
export default controller({
|
|
54
|
-
// 1. Redirect user to Google
|
|
55
|
-
login: route.get('/google', {
|
|
56
|
-
middlewares: [oauthRedirect('google')],
|
|
57
|
-
handle() {
|
|
58
|
-
// Never reached, the middleware handles the redirect
|
|
59
|
-
}
|
|
60
|
-
}),
|
|
61
|
-
|
|
62
|
-
// 2. Handle the callback from Google
|
|
63
|
-
callback: route.get('/google/callback', {
|
|
64
|
-
middlewares: [
|
|
65
|
-
oauthCallback('google', {
|
|
66
|
-
onSuccess: async (req, res, profile, tokens) => {
|
|
67
|
-
// profile contains the normalized user data
|
|
68
|
-
console.log(profile.email, profile.name)
|
|
69
|
-
|
|
70
|
-
// Log the user into your system
|
|
71
|
-
req.session.userId = profile.id
|
|
72
|
-
res.redirect('/dashboard')
|
|
73
|
-
},
|
|
74
|
-
onError: async (req, res, error) => {
|
|
75
|
-
res.redirect(`/login?error=${encodeURIComponent(error.message)}`)
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
],
|
|
79
|
-
handle() {
|
|
80
|
-
// Handled by the onSuccess callback above
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
#### Class-Based (OOP) Paradigm
|
|
87
|
-
In OOP routes, you can use the `@Use()` decorator to apply the exact same middleware helpers.
|
|
88
|
-
|
|
89
|
-
```typescript filename="src/http/auth/route.ts"
|
|
90
|
-
import { Controller, Get, Use } from 'exisjs/decorators'
|
|
91
|
-
import { oauthRedirect, oauthCallback } from 'exisjs/auth'
|
|
92
|
-
|
|
93
|
-
@Controller()
|
|
94
|
-
export default class AuthController {
|
|
95
|
-
|
|
96
|
-
// 1. Redirect user to Google
|
|
97
|
-
@Get('/google')
|
|
98
|
-
@Use(oauthRedirect('google'))
|
|
99
|
-
login() {
|
|
100
|
-
// Never reached, the middleware handles the redirect
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// 2. Handle the callback from Google
|
|
104
|
-
@Get('/google/callback')
|
|
105
|
-
@Use(
|
|
106
|
-
oauthCallback('google', {
|
|
107
|
-
onSuccess: async (req, res, profile, tokens) => {
|
|
108
|
-
// Log the user into your system
|
|
109
|
-
req.session.userId = profile.id
|
|
110
|
-
res.redirect('/dashboard')
|
|
111
|
-
},
|
|
112
|
-
onError: async (req, res, error) => {
|
|
113
|
-
res.redirect(`/login?error=${encodeURIComponent(error.message)}`)
|
|
114
|
-
}
|
|
115
|
-
})
|
|
116
|
-
)
|
|
117
|
-
callback() {
|
|
118
|
-
// Handled by the onSuccess callback above
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Route Guards
|
|
124
|
-
|
|
125
|
-
Once authenticated, use the built-in `requireAuth` middleware to protect your endpoints.
|
|
126
|
-
|
|
127
|
-
#### Functional Paradigm
|
|
128
|
-
```typescript filename="src/http/dashboard/route.ts"
|
|
129
|
-
import { controller, route } from 'exisjs/router'
|
|
130
|
-
import { requireAuth } from 'exisjs/auth'
|
|
131
|
-
|
|
132
|
-
export default controller({
|
|
133
|
-
view: route.get('/', {
|
|
134
|
-
middlewares: [requireAuth({ redirectTo: '/login' })],
|
|
135
|
-
handle({ req }) {
|
|
136
|
-
return { message: 'Welcome to the secure dashboard!' }
|
|
137
|
-
}
|
|
138
|
-
})
|
|
139
|
-
})
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
#### Class-Based (OOP) Paradigm
|
|
143
|
-
```typescript filename="src/http/dashboard/route.ts"
|
|
144
|
-
import { Controller, Get, Use } from 'exisjs/decorators'
|
|
145
|
-
import { requireAuth } from 'exisjs/auth'
|
|
146
|
-
|
|
147
|
-
@Controller()
|
|
148
|
-
@Use(requireAuth({ redirectTo: '/login' })) // Protects the whole controller!
|
|
149
|
-
export default class DashboardController {
|
|
150
|
-
@Get('/')
|
|
151
|
-
view() {
|
|
152
|
-
return { message: 'Welcome to the secure dashboard!' }
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## Creating Custom Providers
|
|
158
|
-
|
|
159
|
-
If you need to connect to an internal identity provider or a service not included by default, use the generic custom provider adapter anywhere in your `server.ts` configuration:
|
|
160
|
-
|
|
161
|
-
```typescript
|
|
162
|
-
OAuth.custom({
|
|
163
|
-
name: 'keycloak',
|
|
164
|
-
authUrl: 'https://keycloak.example.com/auth',
|
|
165
|
-
tokenUrl: 'https://keycloak.example.com/token',
|
|
166
|
-
userInfoUrl: 'https://keycloak.example.com/userinfo',
|
|
167
|
-
clientId: process.env.KC_CLIENT_ID!,
|
|
168
|
-
clientSecret: process.env.KC_CLIENT_SECRET!,
|
|
169
|
-
redirectUri: 'http://localhost:3000/auth/keycloak/callback',
|
|
170
|
-
scopes: ['openid', 'profile', 'email'],
|
|
171
|
-
|
|
172
|
-
// Optionally map the raw response to standard profile fields
|
|
173
|
-
mapProfile: (raw) => ({
|
|
174
|
-
id: raw.sub,
|
|
175
|
-
email: raw.email,
|
|
176
|
-
name: raw.preferred_username,
|
|
177
|
-
}),
|
|
178
|
-
})
|
|
179
|
-
```
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
nextUrl: "/docs/cron"
|
|
3
|
-
nextTitle: "Cron Jobs"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Job Queues
|
|
7
|
-
|
|
8
|
-
ExisJS provides a built-in Job Queue system designed to handle background processing, delayed tasks, and high-concurrency workloads.
|
|
9
|
-
|
|
10
|
-
Key features include:
|
|
11
|
-
- **Native Worker Threads**: File-based jobs are processed in isolated Node.js Worker Threads (`ThreadPool`) so heavy tasks do not block the main HTTP event loop.
|
|
12
|
-
- **Type-Safe Payloads**: Built-in schema validation for queue payloads.
|
|
13
|
-
- **Driver Agnostic**: Swap between `memory` (for dev) and `redis` (for production) without changing business logic.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 1. Configuration
|
|
18
|
-
|
|
19
|
-
You can configure the Queue engine globally in your main `exis.config.ts` or directly in the `exis({ ... })` initializer.
|
|
20
|
-
|
|
21
|
-
```typescript filename="exis.config.ts"
|
|
22
|
-
export default {
|
|
23
|
-
queue: {
|
|
24
|
-
driver: process.env.NODE_ENV === 'production' ? 'redis' : 'memory',
|
|
25
|
-
redisUrl: process.env.REDIS_URL,
|
|
26
|
-
concurrency: 5,
|
|
27
|
-
maxQueue: 10000,
|
|
28
|
-
prefix: 'myapp:jobs'
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### Configuration Properties
|
|
34
|
-
|
|
35
|
-
Here are all the properties you can pass to the `queue` configuration object:
|
|
36
|
-
|
|
37
|
-
- **`driver`**: (`'redis' | 'memory'`) The backend storage engine for the queue. Defaults to `'memory'`.
|
|
38
|
-
- **`redisUrl`**: (`string`) The connection string for your Redis instance if using the redis driver.
|
|
39
|
-
- **`redis`**: (`Redis`) An already instantiated `ioredis` client instance.
|
|
40
|
-
- **`concurrency`** (or **`maxConcurrent`**): (`number`) The maximum number of jobs the worker will process concurrently in the thread pool. Defaults to `1`.
|
|
41
|
-
- **`maxQueue`**: (`number`) Maximum number of pending jobs allowed in the queue. If this limit is hit, `enqueue()` will throw a Backpressure error to protect the system.
|
|
42
|
-
- **`prefix`**: (`string`) A namespace prefix for all queue keys in the backend store (e.g., in Redis). Defaults to `'exis:queue'`.
|
|
43
|
-
- **`enableWorkers`**: (`boolean`) Explicitly enable or disable the background worker on this specific Node process (useful for splitting HTTP servers and Worker servers).
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## 2. Defining Jobs (Two Approaches)
|
|
48
|
-
|
|
49
|
-
ExisJS provides two distinctly different ways to define and process background jobs, depending on whether the task is CPU-intensive or just a quick asynchronous action.
|
|
50
|
-
|
|
51
|
-
### Approach 1: Auto-Mounted File-Based Jobs (Multi-Threaded)
|
|
52
|
-
If you place a job definition inside the `src/jobs/` directory, ExisJS automatically mounts it using **File-Based Routing**.
|
|
53
|
-
|
|
54
|
-
ExisJS will run these files off the main thread in a dedicated V8 isolate (`ThreadPool`). You do not need to write `worker_threads` boilerplate. Define the job, and ExisJS prevents the HTTP server from being blocked by heavy CPU tasks (like image processing or large calculations).
|
|
55
|
-
|
|
56
|
-
```typescript filename="src/jobs/process-image.ts"
|
|
57
|
-
import { defineJob } from 'exisjs/queue'
|
|
58
|
-
import { tex } from 'exisjs/validator'
|
|
59
|
-
|
|
60
|
-
export default defineJob({
|
|
61
|
-
name: 'process-image',
|
|
62
|
-
|
|
63
|
-
schema: tex.object({
|
|
64
|
-
imageId: tex.string(),
|
|
65
|
-
resize: tex.boolean()
|
|
66
|
-
}),
|
|
67
|
-
|
|
68
|
-
// ExisJS automatically runs this handler in a separate Worker Thread!
|
|
69
|
-
async handler({ data }) {
|
|
70
|
-
console.log(`[Worker Thread] Processing image ${data.imageId}...`)
|
|
71
|
-
const result = heavyImageProcessing(data);
|
|
72
|
-
return result;
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Approach 2: Inline Handlers (Main Thread)
|
|
78
|
-
If you have an IO-bound task (like sending an email or calling an external API) and you do not want to create a new file, you can use the global `queue()` helper.
|
|
79
|
-
|
|
80
|
-
Jobs defined this way run functionally in the **main thread** (alongside your HTTP server).
|
|
81
|
-
|
|
82
|
-
```typescript filename="src/http/server.ts"
|
|
83
|
-
import { queue } from 'exisjs/queue'
|
|
84
|
-
|
|
85
|
-
// Define a job inline! Runs in the main event loop.
|
|
86
|
-
queue<{ email: string }>('send-welcome-email', async ({ data }) => {
|
|
87
|
-
console.log(`Sending email to ${data.email}...`)
|
|
88
|
-
}, {
|
|
89
|
-
defaultOptions: { attempts: 3 }
|
|
90
|
-
})
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## 3. Enqueuing Jobs
|
|
96
|
-
|
|
97
|
-
Regardless of which approach you used to define the job, you dispatch them the exact same way using the global `enqueue` helper.
|
|
98
|
-
|
|
99
|
-
#### Functional Paradigm
|
|
100
|
-
|
|
101
|
-
```typescript filename="src/http/users/route.ts"
|
|
102
|
-
import { controller, route } from 'exisjs/router'
|
|
103
|
-
import { enqueue } from 'exisjs/queue'
|
|
104
|
-
|
|
105
|
-
export default controller({
|
|
106
|
-
register: route.post('/register', {
|
|
107
|
-
async handle({ req, res }) {
|
|
108
|
-
const user = await db.users.create(req.body)
|
|
109
|
-
|
|
110
|
-
// Enqueue the job
|
|
111
|
-
await enqueue('send-welcome-email', {
|
|
112
|
-
email: user.email
|
|
113
|
-
}, {
|
|
114
|
-
// You can override job options at dispatch time
|
|
115
|
-
delay: 5000 // Wait 5 seconds before processing
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
res.json({ success: true, user })
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
#### Class-Based (OOP) Paradigm
|
|
125
|
-
|
|
126
|
-
```typescript filename="src/http/users/route.ts"
|
|
127
|
-
import { Controller, Post, Body } from 'exisjs/decorators'
|
|
128
|
-
import { enqueue } from 'exisjs/queue'
|
|
129
|
-
|
|
130
|
-
@Controller()
|
|
131
|
-
export default class UsersController {
|
|
132
|
-
@Post('/register')
|
|
133
|
-
async register(@Body() body: any) {
|
|
134
|
-
const user = await db.users.create(body)
|
|
135
|
-
|
|
136
|
-
// Enqueue the job
|
|
137
|
-
await enqueue('send-welcome-email', {
|
|
138
|
-
email: user.email
|
|
139
|
-
}, {
|
|
140
|
-
// You can override job options at dispatch time
|
|
141
|
-
delay: 5000 // Wait 5 seconds before processing
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
return { success: true, user }
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Extended Options
|
|
150
|
-
|
|
151
|
-
When enqueuing a job, or setting `defaultOptions` in your job definitions, you can configure:
|
|
152
|
-
|
|
153
|
-
- **`attempts`**: How many times to retry a failed job.
|
|
154
|
-
- **`delay`**: How many milliseconds to wait before the job is processing.
|
|
155
|
-
- **`backoff`**: If a job fails, how to wait before retrying (e.g., `{ type: 'exponential', delay: 1000 }` waits 1s, 2s, 4s, etc.).
|
|
156
|
-
- **`visibilityTimeout`**: How long a job stays in the "processing" state before it is considered stuck and gets re-queued by the Sweeper (default: `30000`ms).
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## 4. Queue Drivers & Internals
|
|
161
|
-
|
|
162
|
-
ExisJS comes with two native queue drivers. Both drivers implement atomic operations and strict visibility timeouts to ensure jobs are not processed twice and are safely retried if a worker crashes.
|
|
163
|
-
|
|
164
|
-
### The Memory Driver (`memory`)
|
|
165
|
-
The in-memory driver is designed for development, testing, or simple single-node deployments.
|
|
166
|
-
- It uses ES6 `Map` and `Array.sort` to keep jobs sorted by their execution score (`Date.now() + delay`).
|
|
167
|
-
- Does not require any external infrastructure.
|
|
168
|
-
|
|
169
|
-
### The Redis Driver (`redis`)
|
|
170
|
-
Designed for horizontal scale, the Redis driver powers distributed clusters.
|
|
171
|
-
- **Atomic Operations**: Uses Lua scripts (`EVAL`) to atomically pop jobs from a pending `ZSET` (sorted set) into a processing state.
|
|
172
|
-
- **integrated Core**: It dynamically requires `ioredis` only if used, keeping the core framework lightweight.
|
|
173
|
-
- **Cluster Safe**: All jobs for a specific topic map to consistent Redis hash slots.
|
|
174
|
-
|
|
175
|
-
### The Sweeper
|
|
176
|
-
ExisJS runs a background **Sweeper** every 10 seconds.
|
|
177
|
-
If a worker crashes mid-job, or a job takes longer than its `visibilityTimeout`, the Sweeper detects the stalled job in the processing list and re-queues it back into the pending list so another worker can pick it up.
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
nextUrl: "/docs/decorators"
|
|
3
|
-
nextTitle: "Custom Decorators"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# RPC Client (End-to-End Type Safety)
|
|
7
|
-
|
|
8
|
-
ExisJS comes with a native RPC (Remote Procedure Call) client designed to give you **end-to-end type safety** without needing code generation (like OpenAPI/Swagger) or GraphQL.
|
|
9
|
-
|
|
10
|
-
Because ExisJS infers the types of your backend routes natively, you can share those types directly with your frontend (React, Vue, React Native) and get autocomplete, payload validation, and response typing.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 1. Exporting the AppRouter Type
|
|
15
|
-
|
|
16
|
-
To use the strictly typed client, you simply need to export the inferred type of your ExisJS application from your main backend entry point.
|
|
17
|
-
|
|
18
|
-
```typescript filename="backend/src/http/server.ts"
|
|
19
|
-
import { exis } from 'exisjs'
|
|
20
|
-
|
|
21
|
-
const app = exis({
|
|
22
|
-
async onStart(app) {
|
|
23
|
-
// Backend boot logic...
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
// Export the inferred router type for the frontend
|
|
28
|
-
export type AppRouter = typeof app
|
|
29
|
-
|
|
30
|
-
export default app
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
*(Note: Because this is just a TypeScript `type` export, no backend code gets compiled into your frontend bundle.)*
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 2. Initializing the Client
|
|
38
|
-
|
|
39
|
-
On your frontend (React, Vue, Svelte, etc.), install the lightweight client package:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npm install @exisjs/client
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Then, initialize the client using the `AppRouter` type from your backend:
|
|
46
|
-
|
|
47
|
-
```typescript filename="frontend/src/api.ts"
|
|
48
|
-
import { createClient } from '@exisjs/client'
|
|
49
|
-
import type { AppRouter } from '../../backend/src/http/server'
|
|
50
|
-
|
|
51
|
-
export const client = createClient<AppRouter>({
|
|
52
|
-
baseUrl: 'http://localhost:3000',
|
|
53
|
-
|
|
54
|
-
// Optionally provide default headers (like Auth tokens)
|
|
55
|
-
headers: () => ({
|
|
56
|
-
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
|
57
|
-
}),
|
|
58
|
-
|
|
59
|
-
// Global error handler
|
|
60
|
-
onError: (err) => {
|
|
61
|
-
if (err.status === 401) {
|
|
62
|
-
window.location.href = '/login'
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
})
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## 3. Using the Client
|
|
71
|
-
|
|
72
|
-
Because ExisJS uses an ES6 `Proxy` under the hood, the client dynamically maps your chained object calls into HTTP requests. It mirrors your backend's folder structure.
|
|
73
|
-
|
|
74
|
-
If you have a backend route at `src/http/api/users/route.ts` with a `get` handler:
|
|
75
|
-
|
|
76
|
-
```typescript filename="frontend/src/components/UserProfile.tsx"
|
|
77
|
-
import { client } from '../api'
|
|
78
|
-
|
|
79
|
-
async function fetchUser() {
|
|
80
|
-
// 1. Autocomplete for .api.users.get
|
|
81
|
-
// 2. Strong typing for the payload (e.g. { id: string })
|
|
82
|
-
// 3. The `user` variable is strictly typed to whatever the backend returns
|
|
83
|
-
const user = await client.api.users.get({
|
|
84
|
-
id: "123"
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
console.log(user.name)
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### Passing Query Parameters
|
|
92
|
-
|
|
93
|
-
If you need to pass HTTP query parameters (like `?sort=desc`), you can use the `options` argument (the second parameter):
|
|
94
|
-
|
|
95
|
-
```typescript filename="frontend/src/components/UserList.tsx"
|
|
96
|
-
const users = await client.api.users.get(
|
|
97
|
-
// The first argument is the JSON payload (Body/Params)
|
|
98
|
-
{},
|
|
99
|
-
// The second argument configures the Request Options
|
|
100
|
-
{
|
|
101
|
-
query: { sort: 'desc', limit: 10 },
|
|
102
|
-
headers: { 'X-Custom-Override': 'true' }
|
|
103
|
-
}
|
|
104
|
-
)
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## 4. Advanced Configuration
|
|
110
|
-
|
|
111
|
-
The `createClient` function accepts configuration options to intercept requests and responses globally.
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
export interface ClientConfig {
|
|
115
|
-
// The base URL of your ExisJS backend
|
|
116
|
-
baseUrl: string
|
|
117
|
-
|
|
118
|
-
// Static headers, or a dynamic function evaluated per-request
|
|
119
|
-
headers?: Record<string, string> | (() => Record<string, string>)
|
|
120
|
-
|
|
121
|
-
// Provide a custom fetch implementation (useful for testing or Polyfills)
|
|
122
|
-
fetch?: typeof fetch
|
|
123
|
-
|
|
124
|
-
// A global hook that runs BEFORE the request is dispatched
|
|
125
|
-
onRequest?: (req: RequestInit, url: string) => void | Promise<void>
|
|
126
|
-
|
|
127
|
-
// A global hook that runs AFTER the request successfully completes
|
|
128
|
-
onResponse?: (res: Response, url: string) => void | Promise<void>
|
|
129
|
-
|
|
130
|
-
// A global hook that catches any failed requests
|
|
131
|
-
onError?: (err: Error) => void | Promise<void>
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### ExisClientError
|
|
136
|
-
|
|
137
|
-
If an HTTP request fails (e.g., the backend returns a `400 Bad Request` or `500 Internal Server Error`), the client throws an `ExisClientError`. This error attaches the status code and parsed JSON response.
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
try {
|
|
141
|
-
await client.api.users.post({ email: "invalid-email" })
|
|
142
|
-
} catch (err) {
|
|
143
|
-
console.log(err.status) // 400
|
|
144
|
-
console.log(err.data) // { success: false, error: "Validation Failed..." }
|
|
145
|
-
}
|
|
146
|
-
```
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
nextUrl: "/docs/websockets"
|
|
3
|
-
nextTitle: "WebSockets"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Server-Sent Events (SSE)
|
|
7
|
-
|
|
8
|
-
Server-Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via an HTTP connection. Unlike WebSockets, SSE is unidirectional (server-to-client) and works over standard HTTP without requiring complex handshake protocols or specialized load balancer configurations.
|
|
9
|
-
|
|
10
|
-
SSE is the industry standard for Large Language Model (LLM) streaming (e.g., OpenAI, Anthropic) and real-time dashboard updates. ExisJS provides native SSE support.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 1. Creating an SSE Stream
|
|
15
|
-
|
|
16
|
-
When you declare a route as an SSE endpoint using `route.sse()` or `@Sse()`, ExisJS automatically configures the correct HTTP headers (`Content-Type: text/event-stream`, `Cache-Control: no-cache`, `Connection: keep-alive`) and provides an `ExisSSE` stream object.
|
|
17
|
-
|
|
18
|
-
### Functional Paradigm
|
|
19
|
-
|
|
20
|
-
```typescript filename="src/http/chat/route.ts"
|
|
21
|
-
import { controller, route } from 'exisjs/router'
|
|
22
|
-
import Groq from 'groq-sdk'
|
|
23
|
-
|
|
24
|
-
export default controller({
|
|
25
|
-
chat: route.sse('/api/chat', {
|
|
26
|
-
async handle({ stream: sse, req }) {
|
|
27
|
-
const groq = new Groq({ apiKey: process.env.GROQ_API_KEY })
|
|
28
|
-
const message = req.query.message as string
|
|
29
|
-
|
|
30
|
-
if (!message) {
|
|
31
|
-
sse.send({ error: 'Message is required' }, 'error')
|
|
32
|
-
sse.close()
|
|
33
|
-
return
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
const aiStream = await groq.chat.completions.create({
|
|
38
|
-
messages: [{ role: 'user', content: message }],
|
|
39
|
-
model: 'llama-3.1-8b-instant',
|
|
40
|
-
stream: true,
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
// Iterate over the async generator provided by the AI SDK
|
|
44
|
-
for await (const chunk of aiStream) {
|
|
45
|
-
// Prevent writing to a closed socket if the client disconnects early
|
|
46
|
-
if (!sse.connected) break
|
|
47
|
-
|
|
48
|
-
const content = chunk.choices[0]?.delta?.content || ''
|
|
49
|
-
if (content) {
|
|
50
|
-
sse.send({ text: content }, 'chunk')
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
sse.send({ text: '' }, 'done')
|
|
55
|
-
} finally {
|
|
56
|
-
// Ensure the connection is always closed when processing completes
|
|
57
|
-
sse.close()
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Class-Based (OOP) Paradigm
|
|
65
|
-
|
|
66
|
-
```typescript filename="src/http/chat/route.ts"
|
|
67
|
-
import { Controller, Sse, Stream, Req } from 'exisjs/decorators'
|
|
68
|
-
import type { ExisSSE } from 'exisjs/router'
|
|
69
|
-
import Groq from 'groq-sdk'
|
|
70
|
-
|
|
71
|
-
@Controller()
|
|
72
|
-
export default class AIChatController {
|
|
73
|
-
@Sse('/api/chat')
|
|
74
|
-
async handleChat(@Stream() sse: ExisSSE, @Req() req: any) {
|
|
75
|
-
const groq = new Groq({ apiKey: process.env.GROQ_API_KEY })
|
|
76
|
-
const message = req.query.message as string
|
|
77
|
-
|
|
78
|
-
if (!message) {
|
|
79
|
-
sse.send({ error: 'Message is required' }, 'error')
|
|
80
|
-
sse.close()
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
const aiStream = await groq.chat.completions.create({
|
|
86
|
-
messages: [{ role: 'user', content: message }],
|
|
87
|
-
model: 'llama-3.1-8b-instant',
|
|
88
|
-
stream: true,
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
for await (const chunk of aiStream) {
|
|
92
|
-
if (!sse.connected) break
|
|
93
|
-
|
|
94
|
-
const content = chunk.choices[0]?.delta?.content || ''
|
|
95
|
-
if (content) {
|
|
96
|
-
sse.send({ text: content }, 'chunk')
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
sse.send({ text: '' }, 'done')
|
|
100
|
-
} finally {
|
|
101
|
-
sse.close()
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## 2. The `ExisSSE` API
|
|
110
|
-
|
|
111
|
-
The injected `sse` object gives you full control over the streaming connection:
|
|
112
|
-
|
|
113
|
-
- **`sse.send(data: string | Record<string, any>, eventName?: string)`**: Serializes the data (if it is an object) to JSON and sends it down the wire. You can optionally tag it with a specific `eventName`.
|
|
114
|
-
- **`sse.connected`**: A boolean that evaluates to `true` while the connection is alive. You should always check this inside long-running `for await` or `while` loops to prevent throwing "Socket Closed" errors when the client disconnects unexpectedly.
|
|
115
|
-
- **`sse.close()`**: Safely closes the stream and terminates the HTTP connection.
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
// Sending a plain text message
|
|
119
|
-
sse.send("Processing your request...")
|
|
120
|
-
|
|
121
|
-
// Sending a JSON object tagged with a specific event type (e.g., 'metrics')
|
|
122
|
-
sse.send({ cpu_usage: 95, mem_usage: 60 }, 'metrics')
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
---
|
|
126
|
-
|
|
127
|
-
## 3. Client-Side Consumption
|
|
128
|
-
|
|
129
|
-
To consume the SSE stream from the frontend (e.g., in React, Vue, or Vanilla JS), use the native browser `EventSource` API.
|
|
130
|
-
|
|
131
|
-
```javascript filename="frontend/app.js"
|
|
132
|
-
// Connect to the ExisJS SSE endpoint
|
|
133
|
-
const eventSource = new EventSource('/api/chat?message=Hello')
|
|
134
|
-
|
|
135
|
-
// Listen for the default 'message' event (when no eventName is specified in sse.send)
|
|
136
|
-
eventSource.onmessage = (event) => {
|
|
137
|
-
const data = JSON.parse(event.data)
|
|
138
|
-
console.log("Standard message:", data)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Listen for a custom event type, such as 'chunk'
|
|
142
|
-
eventSource.addEventListener('chunk', (event) => {
|
|
143
|
-
const data = JSON.parse(event.data)
|
|
144
|
-
// Append the streamed text to the DOM
|
|
145
|
-
document.getElementById('output').textContent += data.text
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
// Listen for the 'done' event to close the connection from the client side
|
|
149
|
-
eventSource.addEventListener('done', () => {
|
|
150
|
-
console.log("Stream finished.")
|
|
151
|
-
eventSource.close()
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
// Handle connection errors
|
|
155
|
-
eventSource.onerror = (error) => {
|
|
156
|
-
console.error("SSE Connection Error:", error)
|
|
157
|
-
eventSource.close()
|
|
158
|
-
}
|
|
159
|
-
```
|