@vigajs/core 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +99 -0
- package/LICENSE +21 -0
- package/README.es.md +240 -0
- package/README.md +239 -2
- package/dist/app.d.ts +75 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +251 -0
- package/dist/app.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +127 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/templates.d.ts +20 -0
- package/dist/cli/templates.d.ts.map +1 -0
- package/dist/cli/templates.js +168 -0
- package/dist/cli/templates.js.map +1 -0
- package/dist/config/config.module.d.ts +19 -0
- package/dist/config/config.module.d.ts.map +1 -0
- package/dist/config/config.module.js +115 -0
- package/dist/config/config.module.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +57 -0
- package/dist/context.js.map +1 -0
- package/dist/crypto/crypto.module.d.ts +7 -0
- package/dist/crypto/crypto.module.d.ts.map +1 -0
- package/dist/crypto/crypto.module.js +68 -0
- package/dist/crypto/crypto.module.js.map +1 -0
- package/dist/crypto/encryptor.d.ts +11 -0
- package/dist/crypto/encryptor.d.ts.map +1 -0
- package/dist/crypto/encryptor.js +121 -0
- package/dist/crypto/encryptor.js.map +1 -0
- package/dist/crypto/index.d.ts +9 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +9 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/options.d.ts +12 -0
- package/dist/crypto/options.d.ts.map +1 -0
- package/dist/crypto/options.js +12 -0
- package/dist/crypto/options.js.map +1 -0
- package/dist/crypto/password.d.ts +4 -0
- package/dist/crypto/password.d.ts.map +1 -0
- package/dist/crypto/password.js +74 -0
- package/dist/crypto/password.js.map +1 -0
- package/dist/crypto/signed.d.ts +3 -0
- package/dist/crypto/signed.d.ts.map +1 -0
- package/dist/crypto/signed.js +64 -0
- package/dist/crypto/signed.js.map +1 -0
- package/dist/crypto/tokens.d.ts +4 -0
- package/dist/crypto/tokens.d.ts.map +1 -0
- package/dist/crypto/tokens.js +19 -0
- package/dist/crypto/tokens.js.map +1 -0
- package/dist/crypto/url-signer.d.ts +14 -0
- package/dist/crypto/url-signer.d.ts.map +1 -0
- package/dist/crypto/url-signer.js +108 -0
- package/dist/crypto/url-signer.js.map +1 -0
- package/dist/decorators/controller.d.ts +27 -0
- package/dist/decorators/controller.d.ts.map +1 -0
- package/dist/decorators/controller.js +44 -0
- package/dist/decorators/controller.js.map +1 -0
- package/dist/decorators/index.d.ts +8 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +8 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/injectable.d.ts +3 -0
- package/dist/decorators/injectable.d.ts.map +1 -0
- package/dist/decorators/injectable.js +7 -0
- package/dist/decorators/injectable.js.map +1 -0
- package/dist/decorators/module.d.ts +12 -0
- package/dist/decorators/module.d.ts.map +1 -0
- package/dist/decorators/module.js +10 -0
- package/dist/decorators/module.js.map +1 -0
- package/dist/decorators/pipeline.d.ts +23 -0
- package/dist/decorators/pipeline.d.ts.map +1 -0
- package/dist/decorators/pipeline.js +63 -0
- package/dist/decorators/pipeline.js.map +1 -0
- package/dist/decorators/public.d.ts +2 -0
- package/dist/decorators/public.d.ts.map +1 -0
- package/dist/decorators/public.js +14 -0
- package/dist/decorators/public.js.map +1 -0
- package/dist/decorators/rate-limit.d.ts +4 -0
- package/dist/decorators/rate-limit.d.ts.map +1 -0
- package/dist/decorators/rate-limit.js +13 -0
- package/dist/decorators/rate-limit.js.map +1 -0
- package/dist/decorators/use-guards.d.ts +18 -0
- package/dist/decorators/use-guards.d.ts.map +1 -0
- package/dist/decorators/use-guards.js +36 -0
- package/dist/decorators/use-guards.js.map +1 -0
- package/dist/decorators/use-interceptors.d.ts +19 -0
- package/dist/decorators/use-interceptors.d.ts.map +1 -0
- package/dist/decorators/use-interceptors.js +47 -0
- package/dist/decorators/use-interceptors.js.map +1 -0
- package/dist/di/injector.d.ts +53 -0
- package/dist/di/injector.d.ts.map +1 -0
- package/dist/di/injector.js +169 -0
- package/dist/di/injector.js.map +1 -0
- package/dist/di/lifecycle.d.ts +24 -0
- package/dist/di/lifecycle.d.ts.map +1 -0
- package/dist/di/lifecycle.js +47 -0
- package/dist/di/lifecycle.js.map +1 -0
- package/dist/di/module-loader.d.ts +18 -0
- package/dist/di/module-loader.d.ts.map +1 -0
- package/dist/di/module-loader.js +97 -0
- package/dist/di/module-loader.js.map +1 -0
- package/dist/diagnostics.d.ts +96 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +123 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/drizzle/database.service.d.ts +33 -0
- package/dist/drizzle/database.service.d.ts.map +1 -0
- package/dist/drizzle/database.service.js +134 -0
- package/dist/drizzle/database.service.js.map +1 -0
- package/dist/drizzle/drizzle.module.d.ts +7 -0
- package/dist/drizzle/drizzle.module.d.ts.map +1 -0
- package/dist/drizzle/drizzle.module.js +66 -0
- package/dist/drizzle/drizzle.module.js.map +1 -0
- package/dist/drizzle/index.d.ts +5 -0
- package/dist/drizzle/index.d.ts.map +1 -0
- package/dist/drizzle/index.js +5 -0
- package/dist/drizzle/index.js.map +1 -0
- package/dist/drizzle/transactional.d.ts +3 -0
- package/dist/drizzle/transactional.d.ts.map +1 -0
- package/dist/drizzle/transactional.js +11 -0
- package/dist/drizzle/transactional.js.map +1 -0
- package/dist/events/event-bus.d.ts +21 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +128 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/events.module.d.ts +7 -0
- package/dist/events/events.module.d.ts.map +1 -0
- package/dist/events/events.module.js +63 -0
- package/dist/events/events.module.js.map +1 -0
- package/dist/events/index.d.ts +5 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +5 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/on-event.d.ts +8 -0
- package/dist/events/on-event.d.ts.map +1 -0
- package/dist/events/on-event.js +15 -0
- package/dist/events/on-event.js.map +1 -0
- package/dist/health/health.module.d.ts +11 -0
- package/dist/health/health.module.d.ts.map +1 -0
- package/dist/health/health.module.js +110 -0
- package/dist/health/health.module.js.map +1 -0
- package/dist/health/health.service.d.ts +21 -0
- package/dist/health/health.service.d.ts.map +1 -0
- package/dist/health/health.service.js +108 -0
- package/dist/health/health.service.js.map +1 -0
- package/dist/health/index.d.ts +4 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/health/index.js +4 -0
- package/dist/health/index.js.map +1 -0
- package/dist/http/client-ip.d.ts +7 -0
- package/dist/http/client-ip.d.ts.map +1 -0
- package/dist/http/client-ip.js +13 -0
- package/dist/http/client-ip.js.map +1 -0
- package/dist/http/context.d.ts +21 -0
- package/dist/http/context.d.ts.map +1 -0
- package/dist/http/context.js +10 -0
- package/dist/http/context.js.map +1 -0
- package/dist/http/csrf.d.ts +6 -0
- package/dist/http/csrf.d.ts.map +1 -0
- package/dist/http/csrf.js +54 -0
- package/dist/http/csrf.js.map +1 -0
- package/dist/http/error-handler.d.ts +23 -0
- package/dist/http/error-handler.d.ts.map +1 -0
- package/dist/http/error-handler.js +83 -0
- package/dist/http/error-handler.js.map +1 -0
- package/dist/http/exceptions.d.ts +40 -0
- package/dist/http/exceptions.d.ts.map +1 -0
- package/dist/http/exceptions.js +68 -0
- package/dist/http/exceptions.js.map +1 -0
- package/dist/http/ip.d.ts +2 -0
- package/dist/http/ip.d.ts.map +1 -0
- package/dist/http/ip.js +29 -0
- package/dist/http/ip.js.map +1 -0
- package/dist/http/messages.d.ts +6 -0
- package/dist/http/messages.d.ts.map +1 -0
- package/dist/http/messages.js +28 -0
- package/dist/http/messages.js.map +1 -0
- package/dist/http/rate-limit.d.ts +44 -0
- package/dist/http/rate-limit.d.ts.map +1 -0
- package/dist/http/rate-limit.js +117 -0
- package/dist/http/rate-limit.js.map +1 -0
- package/dist/http/request-id.d.ts +9 -0
- package/dist/http/request-id.d.ts.map +1 -0
- package/dist/http/request-id.js +14 -0
- package/dist/http/request-id.js.map +1 -0
- package/dist/http/router.d.ts +25 -0
- package/dist/http/router.d.ts.map +1 -0
- package/dist/http/router.js +146 -0
- package/dist/http/router.js.map +1 -0
- package/dist/http/security-headers.d.ts +5 -0
- package/dist/http/security-headers.d.ts.map +1 -0
- package/dist/http/security-headers.js +26 -0
- package/dist/http/security-headers.js.map +1 -0
- package/dist/i18n/diagnostics.es.d.ts +91 -0
- package/dist/i18n/diagnostics.es.d.ts.map +1 -0
- package/dist/i18n/diagnostics.es.js +91 -0
- package/dist/i18n/diagnostics.es.js.map +1 -0
- package/dist/i18n/i18n.d.ts +30 -0
- package/dist/i18n/i18n.d.ts.map +1 -0
- package/dist/i18n/i18n.js +74 -0
- package/dist/i18n/i18n.js.map +1 -0
- package/dist/i18n/index.d.ts +4 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +4 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/messages.d.ts +4 -0
- package/dist/i18n/messages.d.ts.map +1 -0
- package/dist/i18n/messages.js +55 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/i18n/negotiate.d.ts +3 -0
- package/dist/i18n/negotiate.d.ts.map +1 -0
- package/dist/i18n/negotiate.js +25 -0
- package/dist/i18n/negotiate.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +9 -0
- package/dist/logger.js.map +1 -0
- package/dist/metadata.d.ts +16 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +44 -0
- package/dist/metadata.js.map +1 -0
- package/dist/pagination/index.d.ts +3 -0
- package/dist/pagination/index.d.ts.map +1 -0
- package/dist/pagination/index.js +3 -0
- package/dist/pagination/index.js.map +1 -0
- package/dist/pagination/paginate.d.ts +29 -0
- package/dist/pagination/paginate.d.ts.map +1 -0
- package/dist/pagination/paginate.js +67 -0
- package/dist/pagination/paginate.js.map +1 -0
- package/dist/polyfills.d.ts +2 -0
- package/dist/polyfills.d.ts.map +1 -0
- package/dist/polyfills.js +3 -0
- package/dist/polyfills.js.map +1 -0
- package/dist/standard-schema.d.ts +33 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +2 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +3 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/testing.d.ts +27 -0
- package/dist/testing/testing.d.ts.map +1 -0
- package/dist/testing/testing.js +38 -0
- package/dist/testing/testing.js.map +1 -0
- package/dist/upload/index.d.ts +4 -0
- package/dist/upload/index.d.ts.map +1 -0
- package/dist/upload/index.js +3 -0
- package/dist/upload/index.js.map +1 -0
- package/dist/upload/upload.d.ts +28 -0
- package/dist/upload/upload.d.ts.map +1 -0
- package/dist/upload/upload.js +120 -0
- package/dist/upload/upload.js.map +1 -0
- package/dist/upload/uploaded-file.d.ts +20 -0
- package/dist/upload/uploaded-file.d.ts.map +1 -0
- package/dist/upload/uploaded-file.js +32 -0
- package/dist/upload/uploaded-file.js.map +1 -0
- package/dist/validation/index.d.ts +5 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +4 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/validate.d.ts +14 -0
- package/dist/validation/validate.d.ts.map +1 -0
- package/dist/validation/validate.js +59 -0
- package/dist/validation/validate.js.map +1 -0
- package/dist/validation/validation.module.d.ts +12 -0
- package/dist/validation/validation.module.d.ts.map +1 -0
- package/dist/validation/validation.module.js +64 -0
- package/dist/validation/validation.module.js.map +1 -0
- package/dist/websocket/adapter.d.ts +30 -0
- package/dist/websocket/adapter.d.ts.map +1 -0
- package/dist/websocket/adapter.js +2 -0
- package/dist/websocket/adapter.js.map +1 -0
- package/dist/websocket/errors.d.ts +3 -0
- package/dist/websocket/errors.d.ts.map +1 -0
- package/dist/websocket/errors.js +5 -0
- package/dist/websocket/errors.js.map +1 -0
- package/dist/websocket/gateway.d.ts +48 -0
- package/dist/websocket/gateway.d.ts.map +1 -0
- package/dist/websocket/gateway.js +58 -0
- package/dist/websocket/gateway.js.map +1 -0
- package/dist/websocket/index.d.ts +9 -0
- package/dist/websocket/index.d.ts.map +1 -0
- package/dist/websocket/index.js +8 -0
- package/dist/websocket/index.js.map +1 -0
- package/dist/websocket/options.d.ts +39 -0
- package/dist/websocket/options.d.ts.map +1 -0
- package/dist/websocket/options.js +45 -0
- package/dist/websocket/options.js.map +1 -0
- package/dist/websocket/rate-limit.d.ts +11 -0
- package/dist/websocket/rate-limit.d.ts.map +1 -0
- package/dist/websocket/rate-limit.js +14 -0
- package/dist/websocket/rate-limit.js.map +1 -0
- package/dist/websocket/server.d.ts +51 -0
- package/dist/websocket/server.d.ts.map +1 -0
- package/dist/websocket/server.js +632 -0
- package/dist/websocket/server.js.map +1 -0
- package/dist/websocket/websocket.module.d.ts +7 -0
- package/dist/websocket/websocket.module.d.ts.map +1 -0
- package/dist/websocket/websocket.module.js +67 -0
- package/dist/websocket/websocket.module.js.map +1 -0
- package/dist/websocket/ws-adapter.d.ts +3 -0
- package/dist/websocket/ws-adapter.d.ts.map +1 -0
- package/dist/websocket/ws-adapter.js +102 -0
- package/dist/websocket/ws-adapter.js.map +1 -0
- package/dist/workers/index.d.ts +6 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +6 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/start-worker.d.ts +8 -0
- package/dist/workers/start-worker.d.ts.map +1 -0
- package/dist/workers/start-worker.js +31 -0
- package/dist/workers/start-worker.js.map +1 -0
- package/dist/workers/supervisor.d.ts +37 -0
- package/dist/workers/supervisor.d.ts.map +1 -0
- package/dist/workers/supervisor.js +201 -0
- package/dist/workers/supervisor.js.map +1 -0
- package/dist/workers/worker-key.d.ts +9 -0
- package/dist/workers/worker-key.d.ts.map +1 -0
- package/dist/workers/worker-key.js +71 -0
- package/dist/workers/worker-key.js.map +1 -0
- package/dist/workers/workers.module.d.ts +7 -0
- package/dist/workers/workers.module.d.ts.map +1 -0
- package/dist/workers/workers.module.js +66 -0
- package/dist/workers/workers.module.js.map +1 -0
- package/package.json +173 -3
- package/src/app.ts +339 -0
- package/src/cli/index.ts +151 -0
- package/src/cli/templates.ts +183 -0
- package/src/config/config.module.ts +85 -0
- package/src/config/index.ts +10 -0
- package/src/context.ts +81 -0
- package/src/crypto/crypto.module.ts +22 -0
- package/src/crypto/encryptor.ts +85 -0
- package/src/crypto/index.ts +9 -0
- package/src/crypto/options.ts +24 -0
- package/src/crypto/password.ts +99 -0
- package/src/crypto/signed.ts +19 -0
- package/src/crypto/tokens.ts +23 -0
- package/src/crypto/url-signer.ts +73 -0
- package/src/decorators/controller.ts +85 -0
- package/src/decorators/index.ts +13 -0
- package/src/decorators/injectable.ts +7 -0
- package/src/decorators/module.ts +20 -0
- package/src/decorators/pipeline.ts +93 -0
- package/src/decorators/public.ts +15 -0
- package/src/decorators/rate-limit.ts +12 -0
- package/src/decorators/use-guards.ts +60 -0
- package/src/decorators/use-interceptors.ts +81 -0
- package/src/di/injector.ts +198 -0
- package/src/di/lifecycle.ts +82 -0
- package/src/di/module-loader.ts +130 -0
- package/src/diagnostics.ts +161 -0
- package/src/drizzle/database.service.ts +113 -0
- package/src/drizzle/drizzle.module.ts +20 -0
- package/src/drizzle/index.ts +15 -0
- package/src/drizzle/transactional.ts +14 -0
- package/src/events/event-bus.ts +105 -0
- package/src/events/events.module.ts +15 -0
- package/src/events/index.ts +5 -0
- package/src/events/on-event.ts +25 -0
- package/src/health/health.module.ts +59 -0
- package/src/health/health.service.ts +75 -0
- package/src/health/index.ts +4 -0
- package/src/http/client-ip.ts +18 -0
- package/src/http/context.ts +44 -0
- package/src/http/csrf.ts +58 -0
- package/src/http/error-handler.ts +120 -0
- package/src/http/exceptions.ts +75 -0
- package/src/http/ip.ts +33 -0
- package/src/http/messages.ts +40 -0
- package/src/http/rate-limit.ts +168 -0
- package/src/http/request-id.ts +27 -0
- package/src/http/router.ts +193 -0
- package/src/http/security-headers.ts +32 -0
- package/src/i18n/diagnostics.es.ts +123 -0
- package/src/i18n/i18n.ts +105 -0
- package/src/i18n/index.ts +10 -0
- package/src/i18n/messages.ts +58 -0
- package/src/i18n/negotiate.ts +34 -0
- package/src/index.ts +46 -0
- package/src/logger.ts +17 -0
- package/src/metadata.ts +52 -0
- package/src/pagination/index.ts +10 -0
- package/src/pagination/paginate.ts +117 -0
- package/src/polyfills.ts +1 -0
- package/src/standard-schema.ts +45 -0
- package/src/testing/index.ts +9 -0
- package/src/testing/testing.ts +71 -0
- package/src/upload/index.ts +4 -0
- package/src/upload/upload.ts +167 -0
- package/src/upload/uploaded-file.ts +42 -0
- package/src/validation/index.ts +9 -0
- package/src/validation/validate.ts +84 -0
- package/src/validation/validation.module.ts +22 -0
- package/src/websocket/adapter.ts +28 -0
- package/src/websocket/errors.ts +5 -0
- package/src/websocket/gateway.ts +132 -0
- package/src/websocket/index.ts +23 -0
- package/src/websocket/options.ts +102 -0
- package/src/websocket/rate-limit.ts +22 -0
- package/src/websocket/server.ts +724 -0
- package/src/websocket/websocket.module.ts +21 -0
- package/src/websocket/ws-adapter.ts +122 -0
- package/src/workers/index.ts +11 -0
- package/src/workers/start-worker.ts +44 -0
- package/src/workers/supervisor.ts +207 -0
- package/src/workers/worker-key.ts +26 -0
- package/src/workers/workers.module.ts +20 -0
- package/tsconfig.base.json +14 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [Semantic Versioning](https://semver.org/). While the version is `0.x`, minor releases may include breaking changes.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-11-02
|
|
6
|
+
|
|
7
|
+
First public release.
|
|
8
|
+
|
|
9
|
+
### Generator
|
|
10
|
+
|
|
11
|
+
- `viga generate` (`viga g`) creates a `resource`, `module`, `controller` or `service`. It has no dependencies, never changes existing files and prints what to register by hand.
|
|
12
|
+
|
|
13
|
+
### `@vigajs/create`
|
|
14
|
+
|
|
15
|
+
- `pnpm create @vigajs my-app`, also with npm, yarn and bun, creates a project with its scripts, TypeScript configuration and a first module. It has no dependencies and runs no installs.
|
|
16
|
+
|
|
17
|
+
### Core (`@vigajs/core`)
|
|
18
|
+
|
|
19
|
+
- Modules with `imports`, `exports`, re-exports and global modules (which must be imported by the root module).
|
|
20
|
+
- Dependency injection with `inject()` in class fields: class, `useClass`, `useValue` and `useFactory` providers, `InjectionToken`, and detection of circular dependencies and imports.
|
|
21
|
+
- Inside a controller, routes are sorted by specificity, so `/export` wins over `/:id` whatever the declaration order. Startup fails on routes that match the same requests, and warns when a route in another controller shadows a later one.
|
|
22
|
+
- Controllers with standard TC39 decorators, `@HttpCode`, guards, interceptors and `@Public`. Every guard, including method guards and `@RateLimit`, runs before any interceptor, in HTTP and WebSocket, so a caching interceptor can't skip them. `@Public` isn't inherited: subclasses and overridden methods are private until they declare it again.
|
|
23
|
+
- Private routes by default through `app.useAuthGuard()`. Startup warns when private routes have no auth guard and lists the public routes at debug level (also for WebSocket gateways).
|
|
24
|
+
- Lifecycle hooks `OnModuleInit` and `OnModuleDestroy`, `close()` that only closes providers that finished starting, and `enableShutdownHooks()`, which exits with the signal's standard code (also as PID 1 in a container).
|
|
25
|
+
- Per-request context with `createContextKey` and `runInNewContext`.
|
|
26
|
+
- Security defaults: security headers, body size limit, server timeouts, request id, `X-Powered-By` disabled, `requireValidation` on by default (a route without a body schema doesn't parse a body and answers 400 `errors.unexpectedBody` when one arrives, and `ctx.req.body` holds the validated value), `concealRoutes` on by default when there is an auth guard (which also covers WebSocket handshakes), and a body parsed only on existing routes and after authentication. `trustProxy: true` logs a warning because it lets clients forge their IP. CSRF protection (`csrf`) rejects, before parsing the body, cross-site `POST` requests a browser can send without a CORS preflight, with `trustedOrigins` for callbacks such as OAuth `form_post`.
|
|
27
|
+
- Rate limiting with `rateLimit()` and `@RateLimit()`, with a pluggable store. The default key groups IPv6 clients by /56 network and IPv4-mapped addresses by their IPv4, through the exported `ipKey()`. The exported `CLIENT_IP` token resolves the client IP with the app's `trustProxy` from a raw Node.js request, such as a WebSocket handshake. The in-memory store is bounded (`maxKeys`), hashes long keys, and when full evicts only keys seen once, so a flood of new keys can't reset a counter under attack; with no room left it fails closed.
|
|
28
|
+
- HTTP exceptions with stable codes, `resolveMessage` and developer diagnostics that can be translated with `setDiagnostics`. `HttpException` covers any other status; when its message is free text, the response `code` is `errors.badRequest` for 4xx and `errors.internal` for 5xx. A failure after the response started is logged once and closes the connection.
|
|
29
|
+
- `listen()` defaults to port 3000.
|
|
30
|
+
- `@vigajs/core/tsconfig.json`, a base TypeScript configuration to extend, so a project only needs `extends` and `include`.
|
|
31
|
+
- `OnServerListen`, `OnServerClose` and `OnDrain` lifecycle hooks. `OnDrain` runs once in-flight requests have finished and before any `onModuleDestroy`.
|
|
32
|
+
- `createContextKey(name, { detached: true })` for values that must not reach `@vigajs/core/events` listeners, such as a transaction.
|
|
33
|
+
- Guards and interceptors accept a context type, so they can be used outside HTTP.
|
|
34
|
+
|
|
35
|
+
### `@vigajs/core/validation`
|
|
36
|
+
|
|
37
|
+
- `@Validate` for `body`, `query` and `params` with any Standard Schema library, typed against the handler's context (which may extend `HttpContext`). Each error's `code` comes from the library's `code` or `type` field, so it works with Zod, Valibot and ArkType.
|
|
38
|
+
- `ValidationModule.forRoot({ formatIssue })` to customize or translate validation messages.
|
|
39
|
+
|
|
40
|
+
### `@vigajs/core/i18n`
|
|
41
|
+
|
|
42
|
+
- `I18n` with nested catalogs, `Accept-Language` negotiation, `resolveLocale` (header name or function), and framework messages in English and Spanish.
|
|
43
|
+
- `diagnosticsEs`, the Spanish dictionary for developer messages.
|
|
44
|
+
|
|
45
|
+
### `@vigajs/core/health`
|
|
46
|
+
|
|
47
|
+
- `HealthModule.forRoot()` adds public `/health` and `/ready` routes (configurable, under `globalPrefix`). `/health` never runs the checks; `/ready` answers 503 if a check throws, returns `false` or exceeds `timeoutMs`. Responses carry no details, failures go to the logger, concurrent requests share one run and the result is cached for `cacheMs`.
|
|
48
|
+
- `DatabaseService.ping()` in `@vigajs/core/drizzle`.
|
|
49
|
+
|
|
50
|
+
### `@vigajs/core/crypto`
|
|
51
|
+
|
|
52
|
+
- `hashPassword`, `verifyPassword` and `needsRehash` with Argon2id from `node:crypto` (no dependencies), in the standard PHC format, with NFKC normalization.
|
|
53
|
+
- `randomToken`, `hashToken` and `safeEqual`.
|
|
54
|
+
- `CryptoModule.forRoot()` with `UrlSigner` and `@Signed()` for signed URLs with expiry, bound to the path, query and method, and `Encryptor` for AES-256-GCM with a context that binds a value to its owner. Both support key rotation and refuse keys under 32 bytes at startup.
|
|
55
|
+
|
|
56
|
+
### `@vigajs/core/events`
|
|
57
|
+
|
|
58
|
+
- `EventsModule.forRoot()`, `EventBus` and `@OnEvent` for an in-memory event bus with class-based events. `emit()` resolves when every listener has finished and never rejects; listener errors are logged and isolated.
|
|
59
|
+
- Listeners inherit a copy of the context without `detached` keys, so they don't join the emitter's transaction. Emitting inside a transaction logs a warning.
|
|
60
|
+
- Shutdown waits for running listeners, up to `drainTimeoutMs`, before any `onModuleDestroy`.
|
|
61
|
+
|
|
62
|
+
### `@vigajs/core/workers`
|
|
63
|
+
|
|
64
|
+
- `WORKER_KEY`, `WorkerModule.forKey()` and `startWorker()` so the same worker module runs inside the API, as a child process or on another server, without a queue library of its own. A worker closes in an orderly way on a signal and when its parent dies, with `orphanTimeoutMs` as a limit in the second case.
|
|
65
|
+
- `WorkersModule.forRoot()` and `WorkerSupervisor` fork one process per key, with `start`, `stop` and `list`, restart with backoff, a graceful stop that ends in `SIGKILL` after `stopTimeoutMs`, and a `maxWorkers` limit (8 by default).
|
|
66
|
+
|
|
67
|
+
### `@vigajs/core/upload`
|
|
68
|
+
|
|
69
|
+
- `@Upload()` over Multer and `file-type`, both optional peer dependencies. It reads files after authentication and guards, requires `types` or `check`, detects the type from the content, stores files under generated names in a temporary folder and removes what isn't moved with `moveTo` when the response ends, also when a request fails or is cut off. Text fields are rejected unless the route uses `@Validate({ body })`. `optional: true` with `OptionalUploadContext` covers forms where the file may be absent.
|
|
70
|
+
|
|
71
|
+
### `@vigajs/core/websocket`
|
|
72
|
+
|
|
73
|
+
- `WebSocketModule.forRoot()` (an object or a function that runs in the container and can use `inject()`, also in `DrizzleModule.forRoot()`), `@Gateway`, `@OnMessage` with Standard Schema validation, `WsContext` and `WsServer`.
|
|
74
|
+
- Rooms with `join`, `leave`, `to(room).send()` and `broadcast()`, limited per connection by `maxRoomsPerClient`.
|
|
75
|
+
- Per-connection language with `i18n` and `resolveLocale`, applied to every message and to error messages.
|
|
76
|
+
- `RateLimit` per event or per gateway, keyed per connection by default or by any value of the context, sharing the bounded in-memory store with HTTP.
|
|
77
|
+
- Public `WsAdapter` interface, with a default adapter on top of `ws` that is loaded only when needed. Adapters receive the gateway paths; a socket.io adapter in the test suite checks that the interface works beyond `ws`.
|
|
78
|
+
- Security defaults: private gateways, handshake authentication with a timeout (`handshakeTimeoutMs`), session expiry from the `expiresAt` that `authenticate` returns (closes with 1008, renewable with `client.expireAt()`), a cap on simultaneous connections (`maxConnections`), a cap per client IP on by default (`connectionsPerKey`, 50, using `trustProxy` and grouping IPv6 by /56), a cap on handshakes still authenticating (`maxPendingHandshakes`), `Origin` allowlist, `maxPayload`, per-connection message rate limit counted on arrival (twice the limit disconnects with 1008, as does piling up more than 100 messages before `onConnection` ends), heartbeat, slow-client protection and `requireValidation`: an event without a schema doesn't accept data and answers 400 `errors.unexpectedData` when it arrives.
|
|
79
|
+
|
|
80
|
+
### `@vigajs/core/config`
|
|
81
|
+
|
|
82
|
+
- `ConfigModule.forRoot({ schema, env? })` validates the configuration at startup with any Standard Schema library and fails listing every invalid variable, without showing their values, even short or nested ones.
|
|
83
|
+
- `inject(CONFIG)` is typed through `Register` and returns a deeply frozen object.
|
|
84
|
+
|
|
85
|
+
### `@vigajs/core/pagination`
|
|
86
|
+
|
|
87
|
+
- `@Paginate` with `page.offset`, `page.limit` and a generic `page.result(items, total)` that returns `PaginatedResult<T>` with `total`, `lastPage` and relative `next`/`prev` links that keep the query parameters.
|
|
88
|
+
- Security defaults: `maxLimit` caps the page size, `maxPage` and `maxOffset` (10,000 rows) cap the depth, invalid values respond 400, and links never use the `Host` header.
|
|
89
|
+
|
|
90
|
+
### `@vigajs/core/drizzle`
|
|
91
|
+
|
|
92
|
+
- `DrizzleModule.forRoot()` and `DatabaseService` with pool shutdown, default timeouts for statements, connections and idle transactions, and a startup warning for connections without verified TLS to a remote host.
|
|
93
|
+
- Transactions with `database.transaction()` and `@Transactional()`, nested savepoints and isolation options.
|
|
94
|
+
|
|
95
|
+
### `@vigajs/core/testing`
|
|
96
|
+
|
|
97
|
+
- `createTestingApp(Module, { overrides, configure })` starts the app on a free local port with the production defaults and a silent logger. `overrides` replaces providers in any module and fails on a token that matches no provider; `app.request()` returns the status, headers and parsed body.
|
|
98
|
+
|
|
99
|
+
[0.1.0]: https://github.com/dialmonsalve/viga/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Diego Monsalve
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.es.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# viga
|
|
2
|
+
|
|
3
|
+
[English](README.md) · **Español** · [Documentación](https://vigajs.dev/es/)
|
|
4
|
+
|
|
5
|
+
Framework HTTP para Node.js sobre Express 5: módulos, inyección de dependencias, guards e interceptores con **decoradores estándar de JavaScript (TC39)**. Sin `reflect-metadata`, sin `experimentalDecorators` y sin `emitDecoratorMetadata`.
|
|
6
|
+
|
|
7
|
+
El core solo resuelve lo que todo servidor necesita. Lo demás son subrutas opcionales: si no las importas, no se instala nada extra.
|
|
8
|
+
|
|
9
|
+
| Importación | Qué trae | Requiere |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `@vigajs/core` | Módulos, DI, controladores, guards, interceptores, `@Public`, excepciones HTTP, ciclo de vida, logger | `express` |
|
|
12
|
+
| `@vigajs/core/validation` | `@Validate` y `ValidationModule` con cualquier librería [Standard Schema](https://standardschema.dev) | Nada (tú eliges Zod, Valibot, ArkType…) |
|
|
13
|
+
| `@vigajs/core/i18n` | Catálogos de mensajes, negociación de `Accept-Language`, mensajes del framework en es/en | Nada |
|
|
14
|
+
| `@vigajs/core/drizzle` | `DrizzleModule` y `DatabaseService` con cierre del pool | `drizzle-orm`, `pg` |
|
|
15
|
+
| `@vigajs/core/config` | `ConfigModule` que valida y tipa las variables de entorno al arrancar | Nada |
|
|
16
|
+
| `@vigajs/core/pagination` | `@Paginate` con resultados tipados, enlaces relativos y límites | Nada |
|
|
17
|
+
| `@vigajs/core/websocket` | Gateways, salas y una interfaz de adaptador pública, con valores restrictivos por defecto | `ws` |
|
|
18
|
+
| `@vigajs/core/testing` | `createTestingApp` para probar la app con peticiones HTTP reales y providers reemplazados | Nada |
|
|
19
|
+
| `@vigajs/core/health` | Rutas `/health` y `/ready` con tus propias comprobaciones, sin revelar detalles | Nada |
|
|
20
|
+
| `@vigajs/core/crypto` | Hash de contraseñas con Argon2id, tokens aleatorios, URLs firmadas y cifrado AES-256-GCM | Nada |
|
|
21
|
+
| `@vigajs/core/events` | Bus de eventos en memoria con eventos tipados, errores aislados y listeners que terminan antes de apagar | Nada |
|
|
22
|
+
| `@vigajs/core/workers` | El mismo worker en la API, en procesos hijos o en otro servidor, con un supervisor que los reinicia | Nada |
|
|
23
|
+
| `@vigajs/core/upload` | `@Upload` con límites, tipos de archivo detectados por su contenido y limpieza automática | `multer`, `file-type` |
|
|
24
|
+
|
|
25
|
+
## Agradecimientos
|
|
26
|
+
|
|
27
|
+
viga está inspirado en [NestJS](https://nestjs.com). Los módulos, la inyección de dependencias, los controladores con decoradores, los guards y los interceptores vienen de las ideas que Kamil Myśliwiec y la comunidad de Nest llevan años perfeccionando. Gracias por mostrar que en Node se puede construir backends con estructura.
|
|
28
|
+
|
|
29
|
+
viga no comparte código con Nest. Toma esas ideas y las lleva a otro terreno: decoradores estándar de JavaScript (TC39) en lugar de `experimentalDecorators` y `reflect-metadata`, promesas en lugar de RxJS y un core pequeño con todo lo demás opcional.
|
|
30
|
+
|
|
31
|
+
También se apoya en el trabajo de [Express](https://expressjs.com), [Standard Schema](https://standardschema.dev) y [Drizzle ORM](https://orm.drizzle.team).
|
|
32
|
+
|
|
33
|
+
## Requisitos
|
|
34
|
+
|
|
35
|
+
- Node.js 24.13 o superior
|
|
36
|
+
- Express 5
|
|
37
|
+
- TypeScript con decoradores estándar (sin `experimentalDecorators`). Heredar `@vigajs/core/tsconfig.json` lo configura por ti
|
|
38
|
+
- Un compilador que transforme los decoradores, como `tsc` o `tsx`. Node ejecuta TypeScript quitando los tipos, pero todavía no soporta decoradores: `node main.ts` falla en el primer `@`.
|
|
39
|
+
|
|
40
|
+
## Instalación
|
|
41
|
+
|
|
42
|
+
La forma más rápida es crear un proyecto:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pnpm create @vigajs mi-app
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Para añadir viga a un proyecto existente:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm add @vigajs/core express
|
|
52
|
+
pnpm add -D typescript tsx @types/express @types/node
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"extends": "@vigajs/core/tsconfig.json",
|
|
58
|
+
"include": ["src"]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Solo si usas `@vigajs/core/drizzle`:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm add drizzle-orm@0.45 pg
|
|
66
|
+
pnpm add -D @types/pg
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Solo si usas `@vigajs/core/websocket` con el adaptador por defecto:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pnpm add ws
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Solo si usas `@vigajs/core/upload`:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pnpm add multer file-type
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Ejemplo mínimo
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { Controller, Get, Injectable, Module, Public, createApp, inject } from '@vigajs/core';
|
|
85
|
+
|
|
86
|
+
@Injectable()
|
|
87
|
+
class BooksService {
|
|
88
|
+
list() {
|
|
89
|
+
return [{ id: 1, title: 'Dune' }];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@Controller('/books')
|
|
94
|
+
class BooksController {
|
|
95
|
+
private readonly books = inject(BooksService);
|
|
96
|
+
|
|
97
|
+
@Public()
|
|
98
|
+
@Get()
|
|
99
|
+
list() {
|
|
100
|
+
return this.books.list();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Module({ controllers: [BooksController], providers: [BooksService] })
|
|
105
|
+
class AppModule {}
|
|
106
|
+
|
|
107
|
+
const app = createApp({ rootModule: AppModule, globalPrefix: '/api/v1' }).enableShutdownHooks();
|
|
108
|
+
|
|
109
|
+
await app.listen(3000);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Las rutas son privadas por defecto: sin `@Public()`, `GET /api/v1/books` respondería 401 hasta configurar un guard con `app.useAuthGuard()` (ver [Guards](https://vigajs.dev/es/core/guards/)).
|
|
113
|
+
|
|
114
|
+
## Core (`@vigajs/core`)
|
|
115
|
+
|
|
116
|
+
### Módulos e inyección de dependencias
|
|
117
|
+
|
|
118
|
+
Consulta [Módulos](https://vigajs.dev/es/core/modules/) y [Providers e inyección de dependencias](https://vigajs.dev/es/core/providers/) en la documentación.
|
|
119
|
+
|
|
120
|
+
### Ciclo de vida
|
|
121
|
+
|
|
122
|
+
Consulta [Ciclo de vida de la app](https://vigajs.dev/es/core/app-lifecycle/) en la documentación.
|
|
123
|
+
|
|
124
|
+
### Rutas privadas por defecto
|
|
125
|
+
|
|
126
|
+
Consulta [Guards](https://vigajs.dev/es/core/guards/) en la documentación. Las mismas reglas, incluido que `@Public` no se hereda, valen para los gateways de `@vigajs/core/websocket`.
|
|
127
|
+
|
|
128
|
+
### Orden de una petición
|
|
129
|
+
|
|
130
|
+
Consulta [Ciclo de vida de una petición](https://vigajs.dev/es/core/request-lifecycle/) en la documentación.
|
|
131
|
+
|
|
132
|
+
### Guards e interceptores
|
|
133
|
+
|
|
134
|
+
Consulta [Guards](https://vigajs.dev/es/core/guards/) e [Interceptores](https://vigajs.dev/es/core/interceptors/) en la documentación.
|
|
135
|
+
|
|
136
|
+
### Contexto por petición
|
|
137
|
+
|
|
138
|
+
Consulta [El contexto de la petición](https://vigajs.dev/es/core/request-lifecycle/#el-contexto-de-la-petición) en la documentación.
|
|
139
|
+
|
|
140
|
+
### Middlewares de Express
|
|
141
|
+
|
|
142
|
+
Consulta [Middlewares de Express](https://vigajs.dev/es/core/request-lifecycle/#middlewares-de-express) en la documentación.
|
|
143
|
+
|
|
144
|
+
### Valores de seguridad por defecto
|
|
145
|
+
|
|
146
|
+
Consulta [Valores por defecto](https://vigajs.dev/es/security/defaults/) e [IP del cliente y proxies](https://vigajs.dev/es/security/client-ip/) en la documentación. Estos valores reducen riesgos habituales, pero no hacen segura una aplicación por sí solos.
|
|
147
|
+
|
|
148
|
+
### Rate limiting
|
|
149
|
+
|
|
150
|
+
Consulta [Límite de peticiones](https://vigajs.dev/es/security/rate-limiting/) en la documentación.
|
|
151
|
+
|
|
152
|
+
### Checklist para pruebas de seguridad
|
|
153
|
+
|
|
154
|
+
Consulta [Lista para pruebas de seguridad](https://vigajs.dev/es/security/checklist/) en la documentación.
|
|
155
|
+
|
|
156
|
+
### Errores
|
|
157
|
+
|
|
158
|
+
Consulta [Excepciones](https://vigajs.dev/es/core/exceptions/) en la documentación.
|
|
159
|
+
|
|
160
|
+
### Mensajes para desarrolladores
|
|
161
|
+
|
|
162
|
+
Consulta [Mensajes para desarrolladores](https://vigajs.dev/es/optional/i18n/#mensajes-para-desarrolladores) en la documentación.
|
|
163
|
+
|
|
164
|
+
### Logger
|
|
165
|
+
|
|
166
|
+
Consulta [Usa tu propio logger](https://vigajs.dev/es/core/providers/#usa-tu-propio-logger) en la documentación.
|
|
167
|
+
|
|
168
|
+
## @vigajs/core/validation
|
|
169
|
+
|
|
170
|
+
Consulta [@vigajs/core/validation](https://vigajs.dev/es/optional/validation/) en la documentación.
|
|
171
|
+
|
|
172
|
+
## @vigajs/core/i18n
|
|
173
|
+
|
|
174
|
+
Consulta [@vigajs/core/i18n](https://vigajs.dev/es/optional/i18n/) en la documentación.
|
|
175
|
+
|
|
176
|
+
## @vigajs/core/config
|
|
177
|
+
|
|
178
|
+
Consulta [@vigajs/core/config](https://vigajs.dev/es/optional/config/) en la documentación.
|
|
179
|
+
|
|
180
|
+
## @vigajs/core/pagination
|
|
181
|
+
|
|
182
|
+
Consulta [@vigajs/core/pagination](https://vigajs.dev/es/optional/pagination/) en la documentación.
|
|
183
|
+
|
|
184
|
+
## @vigajs/core/drizzle
|
|
185
|
+
|
|
186
|
+
Consulta [@vigajs/core/drizzle](https://vigajs.dev/es/optional/drizzle/) en la documentación.
|
|
187
|
+
|
|
188
|
+
## @vigajs/core/websocket
|
|
189
|
+
|
|
190
|
+
Consulta [@vigajs/core/websocket](https://vigajs.dev/es/optional/websocket/) en la documentación.
|
|
191
|
+
|
|
192
|
+
## @vigajs/core/testing
|
|
193
|
+
|
|
194
|
+
Consulta [@vigajs/core/testing](https://vigajs.dev/es/optional/testing/) en la documentación.
|
|
195
|
+
|
|
196
|
+
## @vigajs/core/health
|
|
197
|
+
|
|
198
|
+
Consulta [@vigajs/core/health](https://vigajs.dev/es/optional/health/) en la documentación.
|
|
199
|
+
|
|
200
|
+
## @vigajs/core/crypto
|
|
201
|
+
|
|
202
|
+
Consulta [@vigajs/core/crypto](https://vigajs.dev/es/optional/crypto/) en la documentación.
|
|
203
|
+
|
|
204
|
+
## @vigajs/core/events
|
|
205
|
+
|
|
206
|
+
Consulta [@vigajs/core/events](https://vigajs.dev/es/optional/events/) en la documentación.
|
|
207
|
+
|
|
208
|
+
## @vigajs/core/workers
|
|
209
|
+
|
|
210
|
+
Consulta [@vigajs/core/workers](https://vigajs.dev/es/optional/workers/) en la documentación.
|
|
211
|
+
|
|
212
|
+
## @vigajs/core/upload
|
|
213
|
+
|
|
214
|
+
Consulta [@vigajs/core/upload](https://vigajs.dev/es/optional/upload/) en la documentación.
|
|
215
|
+
|
|
216
|
+
## Generar código
|
|
217
|
+
|
|
218
|
+
`pnpm exec viga g resource books` crea un módulo, un controlador CRUD, un servicio y sus esquemas, y nunca modifica tus archivos existentes. Consulta [Generar código](https://vigajs.dev/es/start/generate/) en la documentación.
|
|
219
|
+
|
|
220
|
+
## Desarrollo
|
|
221
|
+
|
|
222
|
+
| Script | Qué hace |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `pnpm test` | Tests con el runner nativo de Node. Los de PostgreSQL se saltan |
|
|
225
|
+
| `pnpm db:test:up` / `db:test:down` | Levanta o apaga un PostgreSQL desechable en el puerto 55432 (datos en memoria) |
|
|
226
|
+
| `pnpm test:db` | Todos los tests, incluidos los de PostgreSQL (requiere `db:test:up`) |
|
|
227
|
+
| `pnpm test:coverage` | Tests con un informe de cobertura de `src/` (ejecútalo con `VIGA_TEST_DATABASE_URL` para incluir PostgreSQL). Las líneas que solo contienen tipos pueden aparecer como no cubiertas |
|
|
228
|
+
| `pnpm check-types` | Comprueba los tipos |
|
|
229
|
+
| `pnpm build` | Compila a `dist/` con `tsc` (JS + tipos) |
|
|
230
|
+
| `pnpm pack` | Genera el `.tgz` que se publicaría, para probarlo en otro proyecto |
|
|
231
|
+
|
|
232
|
+
`prepublishOnly` ejecuta tipos, todos los tests (con PostgreSQL) y build antes de cada `npm publish`.
|
|
233
|
+
|
|
234
|
+
## Contribuciones
|
|
235
|
+
|
|
236
|
+
viga es un proyecto personal que mantengo en mi tiempo libre, así que no acepto pull requests ni issues. Puedes hacer un fork bajo la licencia MIT.
|
|
237
|
+
|
|
238
|
+
## Licencia
|
|
239
|
+
|
|
240
|
+
[MIT](LICENSE)
|
package/README.md
CHANGED
|
@@ -1,3 +1,240 @@
|
|
|
1
|
-
#
|
|
1
|
+
# viga
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**English** · [Español](README.es.md) · [Documentation](https://vigajs.dev/en/)
|
|
4
|
+
|
|
5
|
+
HTTP framework for Node.js on top of Express 5: modules, dependency injection, guards and interceptors with **standard JavaScript decorators (TC39)**. No `reflect-metadata`, no `experimentalDecorators` and no `emitDecoratorMetadata`.
|
|
6
|
+
|
|
7
|
+
The core only covers what every server needs. Everything else lives in optional subpaths: if you don't import them, nothing extra gets installed.
|
|
8
|
+
|
|
9
|
+
| Import | What it provides | Requires |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `@vigajs/core` | Modules, DI, controllers, guards, interceptors, `@Public`, HTTP exceptions, lifecycle, logger | `express` |
|
|
12
|
+
| `@vigajs/core/validation` | `@Validate` and `ValidationModule` with any [Standard Schema](https://standardschema.dev) library | Nothing (you pick Zod, Valibot, ArkType…) |
|
|
13
|
+
| `@vigajs/core/i18n` | Message catalogs, `Accept-Language` negotiation, framework messages in en/es | Nothing |
|
|
14
|
+
| `@vigajs/core/drizzle` | `DrizzleModule` and `DatabaseService` with pool shutdown | `drizzle-orm`, `pg` |
|
|
15
|
+
| `@vigajs/core/config` | `ConfigModule` that validates and types environment variables at startup | Nothing |
|
|
16
|
+
| `@vigajs/core/pagination` | `@Paginate` with typed results, relative links and limits | Nothing |
|
|
17
|
+
| `@vigajs/core/websocket` | Gateways, rooms and a public adapter interface, with restrictive defaults | `ws` |
|
|
18
|
+
| `@vigajs/core/testing` | `createTestingApp` to test the app with real HTTP requests and replaced providers | Nothing |
|
|
19
|
+
| `@vigajs/core/health` | `/health` and `/ready` routes with your own checks, without revealing details | Nothing |
|
|
20
|
+
| `@vigajs/core/crypto` | Password hashing with Argon2id, random tokens, signed URLs and AES-256-GCM encryption | Nothing |
|
|
21
|
+
| `@vigajs/core/events` | In-memory event bus with typed events, isolated errors and listeners that finish before shutdown | Nothing |
|
|
22
|
+
| `@vigajs/core/workers` | The same worker in the API, in child processes or on another server, with a supervisor that restarts them | Nothing |
|
|
23
|
+
| `@vigajs/core/upload` | `@Upload` with limits, file types detected from the content and automatic cleanup | `multer`, `file-type` |
|
|
24
|
+
|
|
25
|
+
## Acknowledgements
|
|
26
|
+
|
|
27
|
+
viga is inspired by [NestJS](https://nestjs.com). Modules, dependency injection, decorator-based controllers, guards and interceptors come from the ideas Kamil Myśliwiec and the Nest community have spent years refining. Thank you for showing that Node backends can have structure.
|
|
28
|
+
|
|
29
|
+
viga shares no code with Nest. It takes those ideas somewhere else: standard JavaScript decorators (TC39) instead of `experimentalDecorators` and `reflect-metadata`, promises instead of RxJS, and a small core with everything else optional.
|
|
30
|
+
|
|
31
|
+
It also builds on the work of [Express](https://expressjs.com), [Standard Schema](https://standardschema.dev) and [Drizzle ORM](https://orm.drizzle.team).
|
|
32
|
+
|
|
33
|
+
## Requirements
|
|
34
|
+
|
|
35
|
+
- Node.js 24.13 or later
|
|
36
|
+
- Express 5
|
|
37
|
+
- TypeScript with standard decorators (no `experimentalDecorators`). Extending `@vigajs/core/tsconfig.json` sets this up for you
|
|
38
|
+
- A compiler that transforms decorators, such as `tsc` or `tsx`. Node runs TypeScript by stripping types, but it doesn't support decorators yet: `node main.ts` fails at the first `@`.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
The fastest way is to create a project:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pnpm create @vigajs my-app
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
To add @vigajs/core to an existing project:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm add @vigajs/core express
|
|
52
|
+
pnpm add -D typescript tsx @types/express @types/node
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"extends": "@vigajs/core/tsconfig.json",
|
|
58
|
+
"include": ["src"]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Only if you use `@vigajs/core/drizzle`:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm add drizzle-orm@0.45 pg
|
|
66
|
+
pnpm add -D @types/pg
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Only if you use `@vigajs/core/websocket` with the default adapter:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pnpm add ws
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Only if you use `@vigajs/core/upload`:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pnpm add multer file-type
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Minimal example
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { Controller, Get, Injectable, Module, Public, createApp, inject } from '@vigajs/core';
|
|
85
|
+
|
|
86
|
+
@Injectable()
|
|
87
|
+
class BooksService {
|
|
88
|
+
list() {
|
|
89
|
+
return [{ id: 1, title: 'Dune' }];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@Controller('/books')
|
|
94
|
+
class BooksController {
|
|
95
|
+
private readonly books = inject(BooksService);
|
|
96
|
+
|
|
97
|
+
@Public()
|
|
98
|
+
@Get()
|
|
99
|
+
list() {
|
|
100
|
+
return this.books.list();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Module({ controllers: [BooksController], providers: [BooksService] })
|
|
105
|
+
class AppModule {}
|
|
106
|
+
|
|
107
|
+
const app = createApp({ rootModule: AppModule, globalPrefix: '/api/v1' }).enableShutdownHooks();
|
|
108
|
+
|
|
109
|
+
await app.listen(3000);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Routes are private by default: without `@Public()`, `GET /api/v1/books` would respond 401 until you set a guard with `app.useAuthGuard()` (see [Guards](https://vigajs.dev/en/core/guards/)).
|
|
113
|
+
|
|
114
|
+
## Core (`@vigajs/core`)
|
|
115
|
+
|
|
116
|
+
### Modules and dependency injection
|
|
117
|
+
|
|
118
|
+
See [Modules](https://vigajs.dev/en/core/modules/) and [Providers and dependency injection](https://vigajs.dev/en/core/providers/) in the documentation.
|
|
119
|
+
|
|
120
|
+
### Lifecycle
|
|
121
|
+
|
|
122
|
+
See [App lifecycle](https://vigajs.dev/en/core/app-lifecycle/) in the documentation.
|
|
123
|
+
|
|
124
|
+
### Private routes by default
|
|
125
|
+
|
|
126
|
+
See [Guards](https://vigajs.dev/en/core/guards/) in the documentation. The same rules, `@Public` not being inherited included, apply to `@vigajs/core/websocket` gateways.
|
|
127
|
+
|
|
128
|
+
### Request order
|
|
129
|
+
|
|
130
|
+
See [Request lifecycle](https://vigajs.dev/en/core/request-lifecycle/) in the documentation.
|
|
131
|
+
|
|
132
|
+
### Guards and interceptors
|
|
133
|
+
|
|
134
|
+
See [Guards](https://vigajs.dev/en/core/guards/) and [Interceptors](https://vigajs.dev/en/core/interceptors/) in the documentation.
|
|
135
|
+
|
|
136
|
+
### Request context
|
|
137
|
+
|
|
138
|
+
See [The request context](https://vigajs.dev/en/core/request-lifecycle/#the-request-context) in the documentation.
|
|
139
|
+
|
|
140
|
+
### Express middlewares
|
|
141
|
+
|
|
142
|
+
See [Express middlewares](https://vigajs.dev/en/core/request-lifecycle/#express-middlewares) in the documentation.
|
|
143
|
+
|
|
144
|
+
### Security defaults
|
|
145
|
+
|
|
146
|
+
See [Security defaults](https://vigajs.dev/en/security/defaults/) and [Client IP and proxies](https://vigajs.dev/en/security/client-ip/) in the documentation. These defaults reduce common risks, but they don't make an application secure on their own.
|
|
147
|
+
|
|
148
|
+
### Rate limiting
|
|
149
|
+
|
|
150
|
+
See [Rate limiting](https://vigajs.dev/en/security/rate-limiting/) in the documentation.
|
|
151
|
+
|
|
152
|
+
### Security testing checklist
|
|
153
|
+
|
|
154
|
+
See [Security testing checklist](https://vigajs.dev/en/security/checklist/) in the documentation.
|
|
155
|
+
|
|
156
|
+
### Errors
|
|
157
|
+
|
|
158
|
+
See [Exceptions](https://vigajs.dev/en/core/exceptions/) in the documentation.
|
|
159
|
+
|
|
160
|
+
### Developer messages
|
|
161
|
+
|
|
162
|
+
See [Developer messages](https://vigajs.dev/en/optional/i18n/#developer-messages) in the documentation.
|
|
163
|
+
|
|
164
|
+
### Logger
|
|
165
|
+
|
|
166
|
+
See [Use your own logger](https://vigajs.dev/en/core/providers/#use-your-own-logger) in the documentation.
|
|
167
|
+
|
|
168
|
+
## @vigajs/core/validation
|
|
169
|
+
|
|
170
|
+
See [@vigajs/core/validation](https://vigajs.dev/en/optional/validation/) in the documentation.
|
|
171
|
+
|
|
172
|
+
## @vigajs/core/i18n
|
|
173
|
+
|
|
174
|
+
See [@vigajs/core/i18n](https://vigajs.dev/en/optional/i18n/) in the documentation.
|
|
175
|
+
|
|
176
|
+
## @vigajs/core/config
|
|
177
|
+
|
|
178
|
+
See [@vigajs/core/config](https://vigajs.dev/en/optional/config/) in the documentation.
|
|
179
|
+
|
|
180
|
+
## @vigajs/core/pagination
|
|
181
|
+
|
|
182
|
+
See [@vigajs/core/pagination](https://vigajs.dev/en/optional/pagination/) in the documentation.
|
|
183
|
+
|
|
184
|
+
## @vigajs/core/drizzle
|
|
185
|
+
|
|
186
|
+
See [@vigajs/core/drizzle](https://vigajs.dev/en/optional/drizzle/) in the documentation.
|
|
187
|
+
|
|
188
|
+
## @vigajs/core/websocket
|
|
189
|
+
|
|
190
|
+
See [@vigajs/core/websocket](https://vigajs.dev/en/optional/websocket/) in the documentation.
|
|
191
|
+
|
|
192
|
+
## @vigajs/core/testing
|
|
193
|
+
|
|
194
|
+
See [@vigajs/core/testing](https://vigajs.dev/en/optional/testing/) in the documentation.
|
|
195
|
+
|
|
196
|
+
## @vigajs/core/health
|
|
197
|
+
|
|
198
|
+
See [@vigajs/core/health](https://vigajs.dev/en/optional/health/) in the documentation.
|
|
199
|
+
|
|
200
|
+
## @vigajs/core/crypto
|
|
201
|
+
|
|
202
|
+
See [@vigajs/core/crypto](https://vigajs.dev/en/optional/crypto/) in the documentation.
|
|
203
|
+
|
|
204
|
+
## @vigajs/core/events
|
|
205
|
+
|
|
206
|
+
See [@vigajs/core/events](https://vigajs.dev/en/optional/events/) in the documentation.
|
|
207
|
+
|
|
208
|
+
## @vigajs/core/workers
|
|
209
|
+
|
|
210
|
+
See [@vigajs/core/workers](https://vigajs.dev/en/optional/workers/) in the documentation.
|
|
211
|
+
|
|
212
|
+
## @vigajs/core/upload
|
|
213
|
+
|
|
214
|
+
See [@vigajs/core/upload](https://vigajs.dev/en/optional/upload/) in the documentation.
|
|
215
|
+
|
|
216
|
+
## Generating code
|
|
217
|
+
|
|
218
|
+
`pnpm exec viga g resource books` creates a module, a CRUD controller, a service and its schemas, and never changes your existing files. See [Generating code](https://vigajs.dev/en/start/generate/) in the documentation.
|
|
219
|
+
|
|
220
|
+
## Development
|
|
221
|
+
|
|
222
|
+
| Script | What it does |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `pnpm test` | Tests with Node's native runner. PostgreSQL tests are skipped |
|
|
225
|
+
| `pnpm db:test:up` / `db:test:down` | Starts or stops a disposable PostgreSQL on port 55432 (in-memory data) |
|
|
226
|
+
| `pnpm test:db` | All tests, PostgreSQL ones included (requires `db:test:up`) |
|
|
227
|
+
| `pnpm test:coverage` | Tests with a coverage report of `src/` (run it with `VIGA_TEST_DATABASE_URL` set to include PostgreSQL). Lines that only contain types can show as uncovered |
|
|
228
|
+
| `pnpm check-types` | Type checks |
|
|
229
|
+
| `pnpm build` | Compiles to `dist/` with `tsc` (JS + types) |
|
|
230
|
+
| `pnpm pack` | Builds the `.tgz` that would be published, to try it in another project |
|
|
231
|
+
|
|
232
|
+
`prepublishOnly` runs type checks, every test (with PostgreSQL) and the build before each `npm publish`.
|
|
233
|
+
|
|
234
|
+
## Contributing
|
|
235
|
+
|
|
236
|
+
viga is a personal project maintained in my spare time, so I'm not accepting pull requests or issues. You are welcome to fork it under the MIT license.
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
[MIT](LICENSE)
|