@zyno-io/ts-server-foundation 26.712.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/devconsole/assets/index-BlWLbczn.css +1 -0
- package/dist/devconsole/assets/index-lSF6DUY3.js +3 -0
- package/dist/devconsole/index.html +13 -0
- package/dist/src/app/base.d.ts +66 -0
- package/dist/src/app/base.d.ts.map +1 -0
- package/dist/src/app/base.js +577 -0
- package/dist/src/app/base.js.map +1 -0
- package/dist/src/app/commands.d.ts +20 -0
- package/dist/src/app/commands.d.ts.map +1 -0
- package/dist/src/app/commands.js +17 -0
- package/dist/src/app/commands.js.map +1 -0
- package/dist/src/app/config-loader.d.ts +9 -0
- package/dist/src/app/config-loader.d.ts.map +1 -0
- package/dist/src/app/config-loader.js +91 -0
- package/dist/src/app/config-loader.js.map +1 -0
- package/dist/src/app/config.d.ts +96 -0
- package/dist/src/app/config.d.ts.map +1 -0
- package/dist/src/app/config.js +114 -0
- package/dist/src/app/config.js.map +1 -0
- package/dist/src/app/const.d.ts +5 -0
- package/dist/src/app/const.d.ts.map +1 -0
- package/dist/src/app/const.js +17 -0
- package/dist/src/app/const.js.map +1 -0
- package/dist/src/app/current.d.ts +5 -0
- package/dist/src/app/current.d.ts.map +1 -0
- package/dist/src/app/current.js +14 -0
- package/dist/src/app/current.js.map +1 -0
- package/dist/src/app/index.d.ts +8 -0
- package/dist/src/app/index.d.ts.map +1 -0
- package/dist/src/app/index.js +13 -0
- package/dist/src/app/index.js.map +1 -0
- package/dist/src/app/lifecycle.d.ts +9 -0
- package/dist/src/app/lifecycle.d.ts.map +1 -0
- package/dist/src/app/lifecycle.js +21 -0
- package/dist/src/app/lifecycle.js.map +1 -0
- package/dist/src/app/migrations-entrypoint.d.ts +3 -0
- package/dist/src/app/migrations-entrypoint.d.ts.map +1 -0
- package/dist/src/app/migrations-entrypoint.js +35 -0
- package/dist/src/app/migrations-entrypoint.js.map +1 -0
- package/dist/src/app/resolver.d.ts +6 -0
- package/dist/src/app/resolver.d.ts.map +1 -0
- package/dist/src/app/resolver.js +15 -0
- package/dist/src/app/resolver.js.map +1 -0
- package/dist/src/auth/index.d.ts +3 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +15 -0
- package/dist/src/auth/index.js.map +1 -0
- package/dist/src/auth/jwt.d.ts +61 -0
- package/dist/src/auth/jwt.d.ts.map +1 -0
- package/dist/src/auth/jwt.js +379 -0
- package/dist/src/auth/jwt.js.map +1 -0
- package/dist/src/auth/provider.d.ts +21 -0
- package/dist/src/auth/provider.d.ts.map +1 -0
- package/dist/src/auth/provider.js +148 -0
- package/dist/src/auth/provider.js.map +1 -0
- package/dist/src/cli/common.d.ts +13 -0
- package/dist/src/cli/common.d.ts.map +1 -0
- package/dist/src/cli/common.js +99 -0
- package/dist/src/cli/common.js.map +1 -0
- package/dist/src/cli/tsf-create-app.d.ts +3 -0
- package/dist/src/cli/tsf-create-app.d.ts.map +1 -0
- package/dist/src/cli/tsf-create-app.js +89 -0
- package/dist/src/cli/tsf-create-app.js.map +1 -0
- package/dist/src/cli/tsf-dev.d.ts +3 -0
- package/dist/src/cli/tsf-dev.d.ts.map +1 -0
- package/dist/src/cli/tsf-dev.js +753 -0
- package/dist/src/cli/tsf-dev.js.map +1 -0
- package/dist/src/cli/tsf-gen-proto.d.ts +3 -0
- package/dist/src/cli/tsf-gen-proto.d.ts.map +1 -0
- package/dist/src/cli/tsf-gen-proto.js +134 -0
- package/dist/src/cli/tsf-gen-proto.js.map +1 -0
- package/dist/src/cli/tsf-install.d.ts +8 -0
- package/dist/src/cli/tsf-install.d.ts.map +1 -0
- package/dist/src/cli/tsf-install.js +424 -0
- package/dist/src/cli/tsf-install.js.map +1 -0
- package/dist/src/cli/tsf-migrate.d.ts +3 -0
- package/dist/src/cli/tsf-migrate.d.ts.map +1 -0
- package/dist/src/cli/tsf-migrate.js +271 -0
- package/dist/src/cli/tsf-migrate.js.map +1 -0
- package/dist/src/cli/tsf-test.d.ts +4 -0
- package/dist/src/cli/tsf-test.d.ts.map +1 -0
- package/dist/src/cli/tsf-test.js +350 -0
- package/dist/src/cli/tsf-test.js.map +1 -0
- package/dist/src/cli/tsf-update.d.ts +3 -0
- package/dist/src/cli/tsf-update.d.ts.map +1 -0
- package/dist/src/cli/tsf-update.js +12 -0
- package/dist/src/cli/tsf-update.js.map +1 -0
- package/dist/src/cli/tsf.d.ts +3 -0
- package/dist/src/cli/tsf.d.ts.map +1 -0
- package/dist/src/cli/tsf.js +29 -0
- package/dist/src/cli/tsf.js.map +1 -0
- package/dist/src/database/database.d.ts +54 -0
- package/dist/src/database/database.d.ts.map +1 -0
- package/dist/src/database/database.js +695 -0
- package/dist/src/database/database.js.map +1 -0
- package/dist/src/database/driver.d.ts +28 -0
- package/dist/src/database/driver.d.ts.map +1 -0
- package/dist/src/database/driver.js +5 -0
- package/dist/src/database/driver.js.map +1 -0
- package/dist/src/database/drivers/index.d.ts +4 -0
- package/dist/src/database/drivers/index.d.ts.map +1 -0
- package/dist/src/database/drivers/index.js +9 -0
- package/dist/src/database/drivers/index.js.map +1 -0
- package/dist/src/database/drivers/mysql-session-rpc.d.ts +40 -0
- package/dist/src/database/drivers/mysql-session-rpc.d.ts.map +1 -0
- package/dist/src/database/drivers/mysql-session-rpc.js +180 -0
- package/dist/src/database/drivers/mysql-session-rpc.js.map +1 -0
- package/dist/src/database/drivers/mysql-session.d.ts +25 -0
- package/dist/src/database/drivers/mysql-session.d.ts.map +1 -0
- package/dist/src/database/drivers/mysql-session.js +124 -0
- package/dist/src/database/drivers/mysql-session.js.map +1 -0
- package/dist/src/database/drivers/mysql.d.ts +20 -0
- package/dist/src/database/drivers/mysql.d.ts.map +1 -0
- package/dist/src/database/drivers/mysql.js +84 -0
- package/dist/src/database/drivers/mysql.js.map +1 -0
- package/dist/src/database/drivers/postgres.d.ts +22 -0
- package/dist/src/database/drivers/postgres.d.ts.map +1 -0
- package/dist/src/database/drivers/postgres.js +80 -0
- package/dist/src/database/drivers/postgres.js.map +1 -0
- package/dist/src/database/entity.d.ts +112 -0
- package/dist/src/database/entity.d.ts.map +1 -0
- package/dist/src/database/entity.js +333 -0
- package/dist/src/database/entity.js.map +1 -0
- package/dist/src/database/errors.d.ts +7 -0
- package/dist/src/database/errors.d.ts.map +1 -0
- package/dist/src/database/errors.js +34 -0
- package/dist/src/database/errors.js.map +1 -0
- package/dist/src/database/factory.d.ts +48 -0
- package/dist/src/database/factory.d.ts.map +1 -0
- package/dist/src/database/factory.js +139 -0
- package/dist/src/database/factory.js.map +1 -0
- package/dist/src/database/identifiers.d.ts +8 -0
- package/dist/src/database/identifiers.d.ts.map +1 -0
- package/dist/src/database/identifiers.js +46 -0
- package/dist/src/database/identifiers.js.map +1 -0
- package/dist/src/database/index.d.ts +14 -0
- package/dist/src/database/index.d.ts.map +1 -0
- package/dist/src/database/index.js +33 -0
- package/dist/src/database/index.js.map +1 -0
- package/dist/src/database/metadata.d.ts +27 -0
- package/dist/src/database/metadata.d.ts.map +1 -0
- package/dist/src/database/metadata.js +70 -0
- package/dist/src/database/metadata.js.map +1 -0
- package/dist/src/database/migration/create/comparator.d.ts +3 -0
- package/dist/src/database/migration/create/comparator.d.ts.map +1 -0
- package/dist/src/database/migration/create/comparator.js +302 -0
- package/dist/src/database/migration/create/comparator.js.map +1 -0
- package/dist/src/database/migration/create/db-reader.d.ts +9 -0
- package/dist/src/database/migration/create/db-reader.d.ts.map +1 -0
- package/dist/src/database/migration/create/db-reader.js +478 -0
- package/dist/src/database/migration/create/db-reader.js.map +1 -0
- package/dist/src/database/migration/create/ddl-generator.d.ts +4 -0
- package/dist/src/database/migration/create/ddl-generator.d.ts.map +1 -0
- package/dist/src/database/migration/create/ddl-generator.js +431 -0
- package/dist/src/database/migration/create/ddl-generator.js.map +1 -0
- package/dist/src/database/migration/create/entity-reader.d.ts +7 -0
- package/dist/src/database/migration/create/entity-reader.d.ts.map +1 -0
- package/dist/src/database/migration/create/entity-reader.js +169 -0
- package/dist/src/database/migration/create/entity-reader.js.map +1 -0
- package/dist/src/database/migration/create/file-generator.d.ts +7 -0
- package/dist/src/database/migration/create/file-generator.d.ts.map +1 -0
- package/dist/src/database/migration/create/file-generator.js +60 -0
- package/dist/src/database/migration/create/file-generator.js.map +1 -0
- package/dist/src/database/migration/create/index.d.ts +19 -0
- package/dist/src/database/migration/create/index.d.ts.map +1 -0
- package/dist/src/database/migration/create/index.js +102 -0
- package/dist/src/database/migration/create/index.js.map +1 -0
- package/dist/src/database/migration/create/schema-model.d.ts +99 -0
- package/dist/src/database/migration/create/schema-model.d.ts.map +1 -0
- package/dist/src/database/migration/create/schema-model.js +24 -0
- package/dist/src/database/migration/create/schema-model.js.map +1 -0
- package/dist/src/database/migration/create/type-mapper.d.ts +13 -0
- package/dist/src/database/migration/create/type-mapper.d.ts.map +1 -0
- package/dist/src/database/migration/create/type-mapper.js +293 -0
- package/dist/src/database/migration/create/type-mapper.js.map +1 -0
- package/dist/src/database/migration/index.d.ts +33 -0
- package/dist/src/database/migration/index.d.ts.map +1 -0
- package/dist/src/database/migration/index.js +165 -0
- package/dist/src/database/migration/index.js.map +1 -0
- package/dist/src/database/migration/maintenance.d.ts +26 -0
- package/dist/src/database/migration/maintenance.d.ts.map +1 -0
- package/dist/src/database/migration/maintenance.js +65 -0
- package/dist/src/database/migration/maintenance.js.map +1 -0
- package/dist/src/database/query.d.ts +79 -0
- package/dist/src/database/query.d.ts.map +1 -0
- package/dist/src/database/query.js +435 -0
- package/dist/src/database/query.js.map +1 -0
- package/dist/src/database/schema.d.ts +147 -0
- package/dist/src/database/schema.d.ts.map +1 -0
- package/dist/src/database/schema.js +709 -0
- package/dist/src/database/schema.js.map +1 -0
- package/dist/src/database/session.d.ts +63 -0
- package/dist/src/database/session.d.ts.map +1 -0
- package/dist/src/database/session.js +226 -0
- package/dist/src/database/session.js.map +1 -0
- package/dist/src/database/sql.d.ts +37 -0
- package/dist/src/database/sql.d.ts.map +1 -0
- package/dist/src/database/sql.js +143 -0
- package/dist/src/database/sql.js.map +1 -0
- package/dist/src/database/values.d.ts +6 -0
- package/dist/src/database/values.d.ts.map +1 -0
- package/dist/src/database/values.js +237 -0
- package/dist/src/database/values.js.map +1 -0
- package/dist/src/devconsole/controller.d.ts +11 -0
- package/dist/src/devconsole/controller.d.ts.map +1 -0
- package/dist/src/devconsole/controller.js +78 -0
- package/dist/src/devconsole/controller.js.map +1 -0
- package/dist/src/devconsole/generated/devconsole.d.ts +306 -0
- package/dist/src/devconsole/generated/devconsole.d.ts.map +1 -0
- package/dist/src/devconsole/generated/devconsole.js +4029 -0
- package/dist/src/devconsole/generated/devconsole.js.map +1 -0
- package/dist/src/devconsole/index.d.ts +10 -0
- package/dist/src/devconsole/index.d.ts.map +1 -0
- package/dist/src/devconsole/index.js +26 -0
- package/dist/src/devconsole/index.js.map +1 -0
- package/dist/src/devconsole/observers.d.ts +4 -0
- package/dist/src/devconsole/observers.d.ts.map +1 -0
- package/dist/src/devconsole/observers.js +170 -0
- package/dist/src/devconsole/observers.js.map +1 -0
- package/dist/src/devconsole/runtime.d.ts +16 -0
- package/dist/src/devconsole/runtime.d.ts.map +1 -0
- package/dist/src/devconsole/runtime.js +48 -0
- package/dist/src/devconsole/runtime.js.map +1 -0
- package/dist/src/devconsole/security.d.ts +8 -0
- package/dist/src/devconsole/security.d.ts.map +1 -0
- package/dist/src/devconsole/security.js +33 -0
- package/dist/src/devconsole/security.js.map +1 -0
- package/dist/src/devconsole/server.d.ts +25 -0
- package/dist/src/devconsole/server.d.ts.map +1 -0
- package/dist/src/devconsole/server.js +452 -0
- package/dist/src/devconsole/server.js.map +1 -0
- package/dist/src/devconsole/store.d.ts +111 -0
- package/dist/src/devconsole/store.d.ts.map +1 -0
- package/dist/src/devconsole/store.js +177 -0
- package/dist/src/devconsole/store.js.map +1 -0
- package/dist/src/di/container.d.ts +38 -0
- package/dist/src/di/container.d.ts.map +1 -0
- package/dist/src/di/container.js +252 -0
- package/dist/src/di/container.js.map +1 -0
- package/dist/src/di/errors.d.ts +18 -0
- package/dist/src/di/errors.d.ts.map +1 -0
- package/dist/src/di/errors.js +71 -0
- package/dist/src/di/errors.js.map +1 -0
- package/dist/src/di/index.d.ts +5 -0
- package/dist/src/di/index.d.ts.map +1 -0
- package/dist/src/di/index.js +10 -0
- package/dist/src/di/index.js.map +1 -0
- package/dist/src/di/module.d.ts +29 -0
- package/dist/src/di/module.d.ts.map +1 -0
- package/dist/src/di/module.js +42 -0
- package/dist/src/di/module.js.map +1 -0
- package/dist/src/di/provider.d.ts +34 -0
- package/dist/src/di/provider.d.ts.map +1 -0
- package/dist/src/di/provider.js +24 -0
- package/dist/src/di/provider.js.map +1 -0
- package/dist/src/env.d.ts +122 -0
- package/dist/src/env.d.ts.map +1 -0
- package/dist/src/env.js +61 -0
- package/dist/src/env.js.map +1 -0
- package/dist/src/events/event-bus.d.ts +26 -0
- package/dist/src/events/event-bus.d.ts.map +1 -0
- package/dist/src/events/event-bus.js +67 -0
- package/dist/src/events/event-bus.js.map +1 -0
- package/dist/src/events/index.d.ts +2 -0
- package/dist/src/events/index.d.ts.map +1 -0
- package/dist/src/events/index.js +7 -0
- package/dist/src/events/index.js.map +1 -0
- package/dist/src/health/healthcheck.controller.d.ts +9 -0
- package/dist/src/health/healthcheck.controller.d.ts.map +1 -0
- package/dist/src/health/healthcheck.controller.js +33 -0
- package/dist/src/health/healthcheck.controller.js.map +1 -0
- package/dist/src/health/healthcheck.service.d.ts +13 -0
- package/dist/src/health/healthcheck.service.d.ts.map +1 -0
- package/dist/src/health/healthcheck.service.js +37 -0
- package/dist/src/health/healthcheck.service.js.map +1 -0
- package/dist/src/health/index.d.ts +3 -0
- package/dist/src/health/index.d.ts.map +1 -0
- package/dist/src/health/index.js +8 -0
- package/dist/src/health/index.js.map +1 -0
- package/dist/src/helpers/async/context.d.ts +10 -0
- package/dist/src/helpers/async/context.d.ts.map +1 -0
- package/dist/src/helpers/async/context.js +52 -0
- package/dist/src/helpers/async/context.js.map +1 -0
- package/dist/src/helpers/async/process.d.ts +16 -0
- package/dist/src/helpers/async/process.d.ts.map +1 -0
- package/dist/src/helpers/async/process.js +62 -0
- package/dist/src/helpers/async/process.js.map +1 -0
- package/dist/src/helpers/async/promise.d.ts +11 -0
- package/dist/src/helpers/async/promise.d.ts.map +1 -0
- package/dist/src/helpers/async/promise.js +32 -0
- package/dist/src/helpers/async/promise.js.map +1 -0
- package/dist/src/helpers/data/array.d.ts +5 -0
- package/dist/src/helpers/data/array.d.ts.map +1 -0
- package/dist/src/helpers/data/array.js +27 -0
- package/dist/src/helpers/data/array.js.map +1 -0
- package/dist/src/helpers/data/objects.d.ts +13 -0
- package/dist/src/helpers/data/objects.d.ts.map +1 -0
- package/dist/src/helpers/data/objects.js +55 -0
- package/dist/src/helpers/data/objects.js.map +1 -0
- package/dist/src/helpers/data/serialization.d.ts +5 -0
- package/dist/src/helpers/data/serialization.d.ts.map +1 -0
- package/dist/src/helpers/data/serialization.js +25 -0
- package/dist/src/helpers/data/serialization.js.map +1 -0
- package/dist/src/helpers/data/transformer.d.ts +13 -0
- package/dist/src/helpers/data/transformer.d.ts.map +1 -0
- package/dist/src/helpers/data/transformer.js +50 -0
- package/dist/src/helpers/data/transformer.js.map +1 -0
- package/dist/src/helpers/index.d.ts +19 -0
- package/dist/src/helpers/index.d.ts.map +1 -0
- package/dist/src/helpers/index.js +30 -0
- package/dist/src/helpers/index.js.map +1 -0
- package/dist/src/helpers/io/package.d.ts +10 -0
- package/dist/src/helpers/io/package.d.ts.map +1 -0
- package/dist/src/helpers/io/package.js +35 -0
- package/dist/src/helpers/io/package.js.map +1 -0
- package/dist/src/helpers/io/stream.d.ts +18 -0
- package/dist/src/helpers/io/stream.d.ts.map +1 -0
- package/dist/src/helpers/io/stream.js +131 -0
- package/dist/src/helpers/io/stream.js.map +1 -0
- package/dist/src/helpers/redis/broadcast.d.ts +15 -0
- package/dist/src/helpers/redis/broadcast.d.ts.map +1 -0
- package/dist/src/helpers/redis/broadcast.js +93 -0
- package/dist/src/helpers/redis/broadcast.js.map +1 -0
- package/dist/src/helpers/redis/cache.d.ts +20 -0
- package/dist/src/helpers/redis/cache.d.ts.map +1 -0
- package/dist/src/helpers/redis/cache.js +57 -0
- package/dist/src/helpers/redis/cache.js.map +1 -0
- package/dist/src/helpers/redis/mutex.d.ts +45 -0
- package/dist/src/helpers/redis/mutex.d.ts.map +1 -0
- package/dist/src/helpers/redis/mutex.js +446 -0
- package/dist/src/helpers/redis/mutex.js.map +1 -0
- package/dist/src/helpers/redis/redis.d.ts +12 -0
- package/dist/src/helpers/redis/redis.d.ts.map +1 -0
- package/dist/src/helpers/redis/redis.js +62 -0
- package/dist/src/helpers/redis/redis.js.map +1 -0
- package/dist/src/helpers/security/crypto.d.ts +31 -0
- package/dist/src/helpers/security/crypto.d.ts.map +1 -0
- package/dist/src/helpers/security/crypto.js +108 -0
- package/dist/src/helpers/security/crypto.js.map +1 -0
- package/dist/src/helpers/security/validation.d.ts +3 -0
- package/dist/src/helpers/security/validation.d.ts.map +1 -0
- package/dist/src/helpers/security/validation.js +14 -0
- package/dist/src/helpers/security/validation.js.map +1 -0
- package/dist/src/helpers/utils/date.d.ts +4 -0
- package/dist/src/helpers/utils/date.d.ts.map +1 -0
- package/dist/src/helpers/utils/date.js +16 -0
- package/dist/src/helpers/utils/date.js.map +1 -0
- package/dist/src/helpers/utils/error.d.ts +20 -0
- package/dist/src/helpers/utils/error.d.ts.map +1 -0
- package/dist/src/helpers/utils/error.js +164 -0
- package/dist/src/helpers/utils/error.js.map +1 -0
- package/dist/src/helpers/utils/uuid.d.ts +5 -0
- package/dist/src/helpers/utils/uuid.d.ts.map +1 -0
- package/dist/src/helpers/utils/uuid.js +13 -0
- package/dist/src/helpers/utils/uuid.js.map +1 -0
- package/dist/src/http/auth.d.ts +20 -0
- package/dist/src/http/auth.d.ts.map +1 -0
- package/dist/src/http/auth.js +68 -0
- package/dist/src/http/auth.js.map +1 -0
- package/dist/src/http/base.d.ts +57 -0
- package/dist/src/http/base.d.ts.map +1 -0
- package/dist/src/http/base.js +331 -0
- package/dist/src/http/base.js.map +1 -0
- package/dist/src/http/context.d.ts +6 -0
- package/dist/src/http/context.d.ts.map +1 -0
- package/dist/src/http/context.js +26 -0
- package/dist/src/http/context.js.map +1 -0
- package/dist/src/http/cors.d.ts +25 -0
- package/dist/src/http/cors.d.ts.map +1 -0
- package/dist/src/http/cors.js +124 -0
- package/dist/src/http/cors.js.map +1 -0
- package/dist/src/http/decorators.d.ts +64 -0
- package/dist/src/http/decorators.d.ts.map +1 -0
- package/dist/src/http/decorators.js +102 -0
- package/dist/src/http/decorators.js.map +1 -0
- package/dist/src/http/errors.d.ts +50 -0
- package/dist/src/http/errors.d.ts.map +1 -0
- package/dist/src/http/errors.js +158 -0
- package/dist/src/http/errors.js.map +1 -0
- package/dist/src/http/index.d.ts +31 -0
- package/dist/src/http/index.d.ts.map +1 -0
- package/dist/src/http/index.js +33 -0
- package/dist/src/http/index.js.map +1 -0
- package/dist/src/http/middleware.d.ts +12 -0
- package/dist/src/http/middleware.d.ts.map +1 -0
- package/dist/src/http/middleware.js +31 -0
- package/dist/src/http/middleware.js.map +1 -0
- package/dist/src/http/parameter-resolvers.d.ts +3 -0
- package/dist/src/http/parameter-resolvers.d.ts.map +1 -0
- package/dist/src/http/parameter-resolvers.js +8 -0
- package/dist/src/http/parameter-resolvers.js.map +1 -0
- package/dist/src/http/request-logging.d.ts +34 -0
- package/dist/src/http/request-logging.d.ts.map +1 -0
- package/dist/src/http/request-logging.js +130 -0
- package/dist/src/http/request-logging.js.map +1 -0
- package/dist/src/http/request.d.ts +69 -0
- package/dist/src/http/request.d.ts.map +1 -0
- package/dist/src/http/request.js +366 -0
- package/dist/src/http/request.js.map +1 -0
- package/dist/src/http/response.d.ts +98 -0
- package/dist/src/http/response.d.ts.map +1 -0
- package/dist/src/http/response.js +292 -0
- package/dist/src/http/response.js.map +1 -0
- package/dist/src/http/router.d.ts +100 -0
- package/dist/src/http/router.d.ts.map +1 -0
- package/dist/src/http/router.js +1085 -0
- package/dist/src/http/router.js.map +1 -0
- package/dist/src/http/startup-logging.d.ts +8 -0
- package/dist/src/http/startup-logging.d.ts.map +1 -0
- package/dist/src/http/startup-logging.js +55 -0
- package/dist/src/http/startup-logging.js.map +1 -0
- package/dist/src/http/static-files.d.ts +15 -0
- package/dist/src/http/static-files.d.ts.map +1 -0
- package/dist/src/http/static-files.js +110 -0
- package/dist/src/http/static-files.js.map +1 -0
- package/dist/src/http/store.d.ts +8 -0
- package/dist/src/http/store.d.ts.map +1 -0
- package/dist/src/http/store.js +47 -0
- package/dist/src/http/store.js.map +1 -0
- package/dist/src/http/types.d.ts +23 -0
- package/dist/src/http/types.d.ts.map +1 -0
- package/dist/src/http/types.js +3 -0
- package/dist/src/http/types.js.map +1 -0
- package/dist/src/http/upgrade.d.ts +22 -0
- package/dist/src/http/upgrade.d.ts.map +1 -0
- package/dist/src/http/upgrade.js +164 -0
- package/dist/src/http/upgrade.js.map +1 -0
- package/dist/src/http/uploads.d.ts +36 -0
- package/dist/src/http/uploads.d.ts.map +1 -0
- package/dist/src/http/uploads.js +287 -0
- package/dist/src/http/uploads.js.map +1 -0
- package/dist/src/http/workflow.d.ts +34 -0
- package/dist/src/http/workflow.d.ts.map +1 -0
- package/dist/src/http/workflow.js +40 -0
- package/dist/src/http/workflow.js.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +88 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/openapi/controller.d.ts +9 -0
- package/dist/src/openapi/controller.d.ts.map +1 -0
- package/dist/src/openapi/controller.js +45 -0
- package/dist/src/openapi/controller.js.map +1 -0
- package/dist/src/openapi/index.d.ts +5 -0
- package/dist/src/openapi/index.d.ts.map +1 -0
- package/dist/src/openapi/index.js +21 -0
- package/dist/src/openapi/index.js.map +1 -0
- package/dist/src/openapi/schema.d.ts +26 -0
- package/dist/src/openapi/schema.d.ts.map +1 -0
- package/dist/src/openapi/schema.js +1128 -0
- package/dist/src/openapi/schema.js.map +1 -0
- package/dist/src/openapi/serializer.d.ts +16 -0
- package/dist/src/openapi/serializer.d.ts.map +1 -0
- package/dist/src/openapi/serializer.js +506 -0
- package/dist/src/openapi/serializer.js.map +1 -0
- package/dist/src/openapi/types.d.ts +84 -0
- package/dist/src/openapi/types.d.ts.map +1 -0
- package/dist/src/openapi/types.js +5 -0
- package/dist/src/openapi/types.js.map +1 -0
- package/dist/src/reflection/annotations.d.ts +15 -0
- package/dist/src/reflection/annotations.d.ts.map +1 -0
- package/dist/src/reflection/annotations.js +228 -0
- package/dist/src/reflection/annotations.js.map +1 -0
- package/dist/src/reflection/conversion.d.ts +15 -0
- package/dist/src/reflection/conversion.d.ts.map +1 -0
- package/dist/src/reflection/conversion.js +360 -0
- package/dist/src/reflection/conversion.js.map +1 -0
- package/dist/src/reflection/deserializer.d.ts +15 -0
- package/dist/src/reflection/deserializer.d.ts.map +1 -0
- package/dist/src/reflection/deserializer.js +42 -0
- package/dist/src/reflection/deserializer.js.map +1 -0
- package/dist/src/reflection/entity.d.ts +9 -0
- package/dist/src/reflection/entity.d.ts.map +1 -0
- package/dist/src/reflection/entity.js +74 -0
- package/dist/src/reflection/entity.js.map +1 -0
- package/dist/src/reflection/errors.d.ts +8 -0
- package/dist/src/reflection/errors.d.ts.map +1 -0
- package/dist/src/reflection/errors.js +21 -0
- package/dist/src/reflection/errors.js.map +1 -0
- package/dist/src/reflection/index.d.ts +8 -0
- package/dist/src/reflection/index.d.ts.map +1 -0
- package/dist/src/reflection/index.js +13 -0
- package/dist/src/reflection/index.js.map +1 -0
- package/dist/src/reflection/metadata-store.d.ts +14 -0
- package/dist/src/reflection/metadata-store.d.ts.map +1 -0
- package/dist/src/reflection/metadata-store.js +18 -0
- package/dist/src/reflection/metadata-store.js.map +1 -0
- package/dist/src/reflection/model.d.ts +271 -0
- package/dist/src/reflection/model.d.ts.map +1 -0
- package/dist/src/reflection/model.js +36 -0
- package/dist/src/reflection/model.js.map +1 -0
- package/dist/src/reflection/reflection-class.d.ts +60 -0
- package/dist/src/reflection/reflection-class.d.ts.map +1 -0
- package/dist/src/reflection/reflection-class.js +263 -0
- package/dist/src/reflection/reflection-class.js.map +1 -0
- package/dist/src/reflection/type-utils.d.ts +34 -0
- package/dist/src/reflection/type-utils.d.ts.map +1 -0
- package/dist/src/reflection/type-utils.js +485 -0
- package/dist/src/reflection/type-utils.js.map +1 -0
- package/dist/src/reflection.d.ts +2 -0
- package/dist/src/reflection.d.ts.map +1 -0
- package/dist/src/reflection.js +5 -0
- package/dist/src/reflection.js.map +1 -0
- package/dist/src/services/cli.d.ts +9 -0
- package/dist/src/services/cli.d.ts.map +1 -0
- package/dist/src/services/cli.js +47 -0
- package/dist/src/services/cli.js.map +1 -0
- package/dist/src/services/index.d.ts +8 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +13 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/leader.d.ts +31 -0
- package/dist/src/services/leader.d.ts.map +1 -0
- package/dist/src/services/leader.js +176 -0
- package/dist/src/services/leader.js.map +1 -0
- package/dist/src/services/logger.d.ts +60 -0
- package/dist/src/services/logger.d.ts.map +1 -0
- package/dist/src/services/logger.js +349 -0
- package/dist/src/services/logger.js.map +1 -0
- package/dist/src/services/mail/index.d.ts +57 -0
- package/dist/src/services/mail/index.d.ts.map +1 -0
- package/dist/src/services/mail/index.js +89 -0
- package/dist/src/services/mail/index.js.map +1 -0
- package/dist/src/services/mail/postmark.d.ts +11 -0
- package/dist/src/services/mail/postmark.d.ts.map +1 -0
- package/dist/src/services/mail/postmark.js +41 -0
- package/dist/src/services/mail/postmark.js.map +1 -0
- package/dist/src/services/mail/smtp.d.ts +11 -0
- package/dist/src/services/mail/smtp.d.ts.map +1 -0
- package/dist/src/services/mail/smtp.js +50 -0
- package/dist/src/services/mail/smtp.js.map +1 -0
- package/dist/src/services/mesh-client/index.d.ts +9 -0
- package/dist/src/services/mesh-client/index.d.ts.map +1 -0
- package/dist/src/services/mesh-client/index.js +18 -0
- package/dist/src/services/mesh-client/index.js.map +1 -0
- package/dist/src/services/mesh-client/mesh-client-redis-registry.d.ts +23 -0
- package/dist/src/services/mesh-client/mesh-client-redis-registry.d.ts.map +1 -0
- package/dist/src/services/mesh-client/mesh-client-redis-registry.js +360 -0
- package/dist/src/services/mesh-client/mesh-client-redis-registry.js.map +1 -0
- package/dist/src/services/mesh-client/mesh-client-registry.d.ts +16 -0
- package/dist/src/services/mesh-client/mesh-client-registry.d.ts.map +1 -0
- package/dist/src/services/mesh-client/mesh-client-registry.js +44 -0
- package/dist/src/services/mesh-client/mesh-client-registry.js.map +1 -0
- package/dist/src/services/mesh-client/mesh-client-service.d.ts +88 -0
- package/dist/src/services/mesh-client/mesh-client-service.d.ts.map +1 -0
- package/dist/src/services/mesh-client/mesh-client-service.js +222 -0
- package/dist/src/services/mesh-client/mesh-client-service.js.map +1 -0
- package/dist/src/services/mesh-client/mesh-srpc-server.d.ts +95 -0
- package/dist/src/services/mesh-client/mesh-srpc-server.d.ts.map +1 -0
- package/dist/src/services/mesh-client/mesh-srpc-server.js +475 -0
- package/dist/src/services/mesh-client/mesh-srpc-server.js.map +1 -0
- package/dist/src/services/mesh-client/types.d.ts +36 -0
- package/dist/src/services/mesh-client/types.d.ts.map +1 -0
- package/dist/src/services/mesh-client/types.js +38 -0
- package/dist/src/services/mesh-client/types.js.map +1 -0
- package/dist/src/services/mesh.d.ts +73 -0
- package/dist/src/services/mesh.d.ts.map +1 -0
- package/dist/src/services/mesh.js +511 -0
- package/dist/src/services/mesh.js.map +1 -0
- package/dist/src/services/worker/entity.d.ts +26 -0
- package/dist/src/services/worker/entity.d.ts.map +1 -0
- package/dist/src/services/worker/entity.js +30 -0
- package/dist/src/services/worker/entity.js.map +1 -0
- package/dist/src/services/worker/index.d.ts +25 -0
- package/dist/src/services/worker/index.d.ts.map +1 -0
- package/dist/src/services/worker/index.js +52 -0
- package/dist/src/services/worker/index.js.map +1 -0
- package/dist/src/services/worker/observer.d.ts +13 -0
- package/dist/src/services/worker/observer.d.ts.map +1 -0
- package/dist/src/services/worker/observer.js +22 -0
- package/dist/src/services/worker/observer.js.map +1 -0
- package/dist/src/services/worker/queue.d.ts +38 -0
- package/dist/src/services/worker/queue.d.ts.map +1 -0
- package/dist/src/services/worker/queue.js +227 -0
- package/dist/src/services/worker/queue.js.map +1 -0
- package/dist/src/services/worker/recorder.d.ts +17 -0
- package/dist/src/services/worker/recorder.d.ts.map +1 -0
- package/dist/src/services/worker/recorder.js +88 -0
- package/dist/src/services/worker/recorder.js.map +1 -0
- package/dist/src/services/worker/runner.d.ts +37 -0
- package/dist/src/services/worker/runner.d.ts.map +1 -0
- package/dist/src/services/worker/runner.js +319 -0
- package/dist/src/services/worker/runner.js.map +1 -0
- package/dist/src/services/worker/types.d.ts +63 -0
- package/dist/src/services/worker/types.d.ts.map +1 -0
- package/dist/src/services/worker/types.js +38 -0
- package/dist/src/services/worker/types.js.map +1 -0
- package/dist/src/srpc/SrpcByteStream.d.ts +60 -0
- package/dist/src/srpc/SrpcByteStream.d.ts.map +1 -0
- package/dist/src/srpc/SrpcByteStream.js +237 -0
- package/dist/src/srpc/SrpcByteStream.js.map +1 -0
- package/dist/src/srpc/SrpcClient.d.ts +67 -0
- package/dist/src/srpc/SrpcClient.d.ts.map +1 -0
- package/dist/src/srpc/SrpcClient.js +406 -0
- package/dist/src/srpc/SrpcClient.js.map +1 -0
- package/dist/src/srpc/SrpcServer.d.ts +56 -0
- package/dist/src/srpc/SrpcServer.d.ts.map +1 -0
- package/dist/src/srpc/SrpcServer.js +519 -0
- package/dist/src/srpc/SrpcServer.js.map +1 -0
- package/dist/src/srpc/index.d.ts +9 -0
- package/dist/src/srpc/index.d.ts.map +1 -0
- package/dist/src/srpc/index.js +17 -0
- package/dist/src/srpc/index.js.map +1 -0
- package/dist/src/srpc/observer.d.ts +21 -0
- package/dist/src/srpc/observer.d.ts.map +1 -0
- package/dist/src/srpc/observer.js +22 -0
- package/dist/src/srpc/observer.js.map +1 -0
- package/dist/src/srpc/types.d.ts +92 -0
- package/dist/src/srpc/types.d.ts.map +1 -0
- package/dist/src/srpc/types.js +28 -0
- package/dist/src/srpc/types.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +3 -0
- package/dist/src/telemetry/index.d.ts.map +1 -0
- package/dist/src/telemetry/index.js +22 -0
- package/dist/src/telemetry/index.js.map +1 -0
- package/dist/src/telemetry/otel/helpers.d.ts +45 -0
- package/dist/src/telemetry/otel/helpers.d.ts.map +1 -0
- package/dist/src/telemetry/otel/helpers.js +142 -0
- package/dist/src/telemetry/otel/helpers.js.map +1 -0
- package/dist/src/telemetry/otel/index.d.ts +22 -0
- package/dist/src/telemetry/otel/index.d.ts.map +1 -0
- package/dist/src/telemetry/otel/index.js +268 -0
- package/dist/src/telemetry/otel/index.js.map +1 -0
- package/dist/src/telemetry/otel/metrics.controller.d.ts +5 -0
- package/dist/src/telemetry/otel/metrics.controller.d.ts.map +1 -0
- package/dist/src/telemetry/otel/metrics.controller.js +82 -0
- package/dist/src/telemetry/otel/metrics.controller.js.map +1 -0
- package/dist/src/telemetry/otel/metrics.d.ts +2 -0
- package/dist/src/telemetry/otel/metrics.d.ts.map +1 -0
- package/dist/src/telemetry/otel/metrics.js +16 -0
- package/dist/src/telemetry/otel/metrics.js.map +1 -0
- package/dist/src/telemetry/sentry.d.ts +9 -0
- package/dist/src/telemetry/sentry.d.ts.map +1 -0
- package/dist/src/telemetry/sentry.js +63 -0
- package/dist/src/telemetry/sentry.js.map +1 -0
- package/dist/src/testing/database-readiness.d.ts +11 -0
- package/dist/src/testing/database-readiness.d.ts.map +1 -0
- package/dist/src/testing/database-readiness.js +102 -0
- package/dist/src/testing/database-readiness.js.map +1 -0
- package/dist/src/testing/expect.d.ts +21 -0
- package/dist/src/testing/expect.d.ts.map +1 -0
- package/dist/src/testing/expect.js +110 -0
- package/dist/src/testing/expect.js.map +1 -0
- package/dist/src/testing/fixtures.d.ts +18 -0
- package/dist/src/testing/fixtures.d.ts.map +1 -0
- package/dist/src/testing/fixtures.js +46 -0
- package/dist/src/testing/fixtures.js.map +1 -0
- package/dist/src/testing/index.d.ts +143 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +993 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/mysql-session-manager-process.d.ts +3 -0
- package/dist/src/testing/mysql-session-manager-process.d.ts.map +1 -0
- package/dist/src/testing/mysql-session-manager-process.js +77 -0
- package/dist/src/testing/mysql-session-manager-process.js.map +1 -0
- package/dist/src/testing/mysql-session-manager.d.ts +59 -0
- package/dist/src/testing/mysql-session-manager.d.ts.map +1 -0
- package/dist/src/testing/mysql-session-manager.js +910 -0
- package/dist/src/testing/mysql-session-manager.js.map +1 -0
- package/dist/src/testing/sql.d.ts +47 -0
- package/dist/src/testing/sql.d.ts.map +1 -0
- package/dist/src/testing/sql.js +313 -0
- package/dist/src/testing/sql.js.map +1 -0
- package/dist/src/type-compiler/go/ast_expression.go +161 -0
- package/dist/src/type-compiler/go/ast_metadata.go +355 -0
- package/dist/src/type-compiler/go/collect.go +806 -0
- package/dist/src/type-compiler/go/emission_plan.go +205 -0
- package/dist/src/type-compiler/go/emit_ast.go +406 -0
- package/dist/src/type-compiler/go/emit_ast_test.go +248 -0
- package/dist/src/type-compiler/go/go.mod +10 -0
- package/dist/src/type-compiler/go/plugin.go +308 -0
- package/dist/src/type-compiler/go/plugin_test.go +752 -0
- package/dist/src/type-compiler/go/precompute.go +86 -0
- package/dist/src/type-compiler/go/receive_type.go +837 -0
- package/dist/src/type-compiler/go/resolve.go +265 -0
- package/dist/src/type-compiler/go/source_scan.go +51 -0
- package/dist/src/type-compiler/go/text_parse.go +671 -0
- package/dist/src/type-compiler/go/type_expr.go +1227 -0
- package/dist/src/type-compiler/go/typia_expr.go +2119 -0
- package/dist/src/type-compiler/index.cjs +6 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +14 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/phone.d.ts +6 -0
- package/dist/src/types/phone.d.ts.map +1 -0
- package/dist/src/types/phone.js +64 -0
- package/dist/src/types/phone.js.map +1 -0
- package/dist/src/types/primitives.d.ts +33 -0
- package/dist/src/types/primitives.d.ts.map +1 -0
- package/dist/src/types/primitives.js +5 -0
- package/dist/src/types/primitives.js.map +1 -0
- package/dist/src/types/runtime.d.ts +5 -0
- package/dist/src/types/runtime.d.ts.map +1 -0
- package/dist/src/types/runtime.js +20 -0
- package/dist/src/types/runtime.js.map +1 -0
- package/dist/src/types/type-annotations.d.ts +28 -0
- package/dist/src/types/type-annotations.d.ts.map +1 -0
- package/dist/src/types/type-annotations.js +33 -0
- package/dist/src/types/type-annotations.js.map +1 -0
- package/dist/src/types.d.ts +2 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +7 -0
- package/dist/src/types.js.map +1 -0
- package/docs/.vitepress/config.mts +85 -0
- package/docs/content/CONTRIBUTING.md +53 -0
- package/docs/content/README-DEV.md +59 -0
- package/docs/content/README.md +52 -0
- package/docs/content/authentication.md +213 -0
- package/docs/content/cli.md +214 -0
- package/docs/content/configuration.md +191 -0
- package/docs/content/database.md +476 -0
- package/docs/content/devconsole.md +148 -0
- package/docs/content/di.md +212 -0
- package/docs/content/documentation-plan.md +182 -0
- package/docs/content/env.md +120 -0
- package/docs/content/getting-started.md +324 -0
- package/docs/content/health.md +64 -0
- package/docs/content/helpers.md +294 -0
- package/docs/content/http.md +402 -0
- package/docs/content/index.md +109 -0
- package/docs/content/leader-service.md +98 -0
- package/docs/content/logging.md +225 -0
- package/docs/content/mail.md +171 -0
- package/docs/content/mesh-client.md +333 -0
- package/docs/content/mesh-service.md +255 -0
- package/docs/content/migrations.md +190 -0
- package/docs/content/openapi.md +134 -0
- package/docs/content/overview.md +98 -0
- package/docs/content/public/images/devconsole/01-dashboard.png +0 -0
- package/docs/content/public/images/devconsole/02-routes.png +0 -0
- package/docs/content/public/images/devconsole/03-openapi.png +0 -0
- package/docs/content/public/images/devconsole/04-requests.png +0 -0
- package/docs/content/public/images/devconsole/05-srpc.png +0 -0
- package/docs/content/public/images/devconsole/06-database.png +0 -0
- package/docs/content/public/images/devconsole/06b-database-log.png +0 -0
- package/docs/content/public/images/devconsole/07-health.png +0 -0
- package/docs/content/public/images/devconsole/08-mutex.png +0 -0
- package/docs/content/public/images/devconsole/09-repl.png +0 -0
- package/docs/content/public/images/devconsole/10-workers.png +0 -0
- package/docs/content/public-api.md +84 -0
- package/docs/content/redis.md +174 -0
- package/docs/content/reflection.md +180 -0
- package/docs/content/release.md +100 -0
- package/docs/content/sql.md +121 -0
- package/docs/content/srpc.md +292 -0
- package/docs/content/telemetry.md +173 -0
- package/docs/content/testing.md +327 -0
- package/docs/content/type-reflection-architecture.md +149 -0
- package/docs/content/types.md +286 -0
- package/docs/content/uploads.md +145 -0
- package/docs/content/worker.md +182 -0
- package/docs/openapi.md +3 -0
- package/package.json +124 -0
- package/resources/proto/devconsole.proto +286 -0
- package/template-app/.env.development +10 -0
- package/template-app/gitignore.tmpl +11 -0
- package/template-app/package.json.tmpl +25 -0
- package/template-app/src/app.ts +13 -0
- package/template-app/src/config.ts +5 -0
- package/template-app/src/controllers/Example.controller.ts +19 -0
- package/template-app/src/database.ts +5 -0
- package/template-app/src/entities/Example.entity.ts +9 -0
- package/template-app/src/index.ts +7 -0
- package/template-app/src/migrations/.gitkeep +2 -0
- package/template-app/src/services/Example.service.ts +20 -0
- package/template-app/tests/app.spec.ts +8 -0
- package/template-app/tsconfig.json +26 -0
- package/template-app/tsconfig.test.json +5 -0
- package/types.d.ts +4 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
# HTTP
|
|
2
|
+
|
|
3
|
+
`ts-server-foundation` provides a small HTTP router and response layer for controller-based APIs.
|
|
4
|
+
|
|
5
|
+
## Controllers
|
|
6
|
+
|
|
7
|
+
Register controllers through `createApp({ controllers: [...] })` and decorate them with the exported `http` helper.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { HttpBody, http } from '@zyno-io/ts-server-foundation';
|
|
11
|
+
|
|
12
|
+
interface CreateUserBody {
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@http.controller('/users')
|
|
17
|
+
class UserController {
|
|
18
|
+
@http.GET('/:id')
|
|
19
|
+
async getUser(id: number) {
|
|
20
|
+
return { id };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@http.POST()
|
|
24
|
+
async createUser(body: HttpBody<CreateUserBody>) {
|
|
25
|
+
return { id: 1, ...body };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Supported route decorators are `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, and `HEAD`.
|
|
31
|
+
|
|
32
|
+
Controller and method paths are joined with one `/`; leading, repeated, and final slashes in declarations are normalized. A request may include one trailing slash and still match. `:name` segments match one encoded URL segment, are decoded before injection, and return HTTP `400` when percent encoding is malformed.
|
|
33
|
+
|
|
34
|
+
Methods match exactly. A `GET` route does not implicitly handle `HEAD`; declare `@http.HEAD()` when the endpoint supports it. Matching also follows declaration and registration order rather than preferring literal paths over parameters, so place `/fixed` before `/:id` when both can match the same request. Controllers exported by imported modules join the same route table and retain module-local DI resolution. If no exact route matches, the router runs `onRouteNotFound` and then returns the normalized `404` response unless a listener has completed the response.
|
|
35
|
+
|
|
36
|
+
When the app listens outside `APP_ENV=test`, startup output includes the registered HTTP route count, routes grouped by controller, the bound URL, and a final started line. This makes silent server starts easier to diagnose.
|
|
37
|
+
|
|
38
|
+
## HTTP Runtime
|
|
39
|
+
|
|
40
|
+
HTTP server operations live on `app.http`, not directly on `App`:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const app = createApp({ controllers: [UserController] });
|
|
44
|
+
|
|
45
|
+
const server = await app.http.listen(0, '127.0.0.1');
|
|
46
|
+
const address = server.address();
|
|
47
|
+
const port = typeof address === 'object' && address ? address.port : undefined;
|
|
48
|
+
|
|
49
|
+
const removeObserver = app.http.registerObserver(entry => {
|
|
50
|
+
console.log(entry.request.method, entry.request.url, entry.response.statusCode, entry.durationMs);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const removeUpgrade = app.http.registerUpgradeHandler((request, socket, head) => {
|
|
54
|
+
// Claim and handle WebSocket or other HTTP upgrade requests.
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
await app.stop();
|
|
58
|
+
removeObserver();
|
|
59
|
+
removeUpgrade();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`app.http.listen()` starts the app if needed, runs the server bootstrap lifecycle events after the socket binds, installs signal handlers, and starts DevConsole when enabled. If binding or a post-bind bootstrap hook fails, it closes any socket that was opened and rolls back app startup when that listen call initiated it. Application entrypoints should usually call `app.run()` and pass `server:start` on the command line; direct `app.http.listen()` is mainly for tests, demos, embedded servers, and custom process managers.
|
|
63
|
+
|
|
64
|
+
`app.http.getPort()` resolves an explicit or configured listen port before binding. When `listen(0)` asks the operating system for an ephemeral port, read the actual port from `server.address()` as shown above.
|
|
65
|
+
|
|
66
|
+
`app.http.request(request, response?)` sends an in-memory `HttpRequest` through the same router/CORS/static-file flow without creating a Node server.
|
|
67
|
+
|
|
68
|
+
Observers run once after every in-memory or Node request, including CORS, static-file, `404`, and error results. The observation contains `request`, `response`, `startedAt`, `durationMs`, and the processing `error` when one was recorded. An observer exception is isolated from request handling, and the function returned by `registerObserver()` unregisters it.
|
|
69
|
+
|
|
70
|
+
## Request Order
|
|
71
|
+
|
|
72
|
+
The request pipeline is:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
CORS preflight short circuit
|
|
76
|
+
-> prepare CORS response headers
|
|
77
|
+
-> static GET handling when no registered route matches
|
|
78
|
+
-> onRoute workflow
|
|
79
|
+
-> multipart guard, or raw-stream bypass
|
|
80
|
+
-> controller middleware, then route middleware
|
|
81
|
+
-> onController workflow
|
|
82
|
+
-> controller construction and left-to-right parameter resolution
|
|
83
|
+
-> route handler and response-result handling
|
|
84
|
+
-> onResponse workflow
|
|
85
|
+
-> upload cleanup, even when onResponse fails
|
|
86
|
+
-> final CORS application and response observation
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
An ended response short-circuits later router stages. Multipart guarding happens before middleware so an undeclared or unsafe file cannot be hidden by middleware. `onResponse` runs for successful and failed router requests; upload cleanup runs in its own `finally` after that workflow.
|
|
90
|
+
|
|
91
|
+
## Request Logging
|
|
92
|
+
|
|
93
|
+
Node HTTP requests are logged at the server boundary and configured with `HTTP_REQUEST_LOGGING_MODE`:
|
|
94
|
+
|
|
95
|
+
| Mode | Behavior |
|
|
96
|
+
| -------- | --------------------------------------------------------- |
|
|
97
|
+
| `e2e` | Logs request start and finish. |
|
|
98
|
+
| `finish` | Logs only request finish. |
|
|
99
|
+
| `errors` | Logs only request processing errors and aborted requests. |
|
|
100
|
+
| `none` | Disables normal request logs. |
|
|
101
|
+
|
|
102
|
+
Test mode defaults to `errors` so service/application logs remain visible without routine HTTP `Request` and `Response` records. Request logs include method, URL, status code, duration, remote address on start, and the active request context. `/healthz` request logging is disabled by default; set `HEALTHZ_ENABLE_REQUEST_LOGGING=true` to include it. `/metrics` is always skipped.
|
|
103
|
+
|
|
104
|
+
`HttpLogPayloadMiddleware` is an opt-in diagnostic middleware that reads and logs the request body as text along with the method, URL, and content type. Because it can record credentials, tokens, personal data, and large payloads, use it only on deliberately selected routes and with a logger whose destination and retention are appropriate for that data.
|
|
105
|
+
|
|
106
|
+
### Client Address And Trusted Proxies
|
|
107
|
+
|
|
108
|
+
`request.remoteAddress` is the transport socket address. `request.getRemoteAddress()` returns that address unless `USE_REAL_IP_HEADER=true`; when proxy headers are trusted it prefers `x-real-ip`, then the first `x-forwarded-for` entry.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
@http.GET('/whoami')
|
|
112
|
+
whoAmI(request: HttpRequest) {
|
|
113
|
+
return { address: request.getRemoteAddress() };
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Enable `USE_REAL_IP_HEADER` only when every path to the application passes through a trusted proxy that removes untrusted forwarding headers. DevConsole and `/metrics` deliberately use the socket address for their local/private access checks and do not trust these headers.
|
|
118
|
+
|
|
119
|
+
## Parameter Injection
|
|
120
|
+
|
|
121
|
+
Parameters are explicit by default. The router only auto-infers a parameter when its name matches a URL path parameter.
|
|
122
|
+
|
|
123
|
+
| Parameter type | Source |
|
|
124
|
+
| ----------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
125
|
+
| `HttpRequest` | Current request metadata and guarded body readers. |
|
|
126
|
+
| `HttpRequestStream` | Raw request stream escape hatch. Bypasses body parsing and guards. |
|
|
127
|
+
| `HttpResponse` | Current response object for imperative writes. |
|
|
128
|
+
| `HttpBody<T>` | Parsed JSON body or parsed multipart `_payload` object; one per route. |
|
|
129
|
+
| `HttpQueries<T>` | Full query object. |
|
|
130
|
+
| `HttpQuery<T>` | Query value matching the parameter name. |
|
|
131
|
+
| `HttpQuery<T, { name: 'key' }>` | Query value from an explicit key. |
|
|
132
|
+
| `HttpPath<T>` | Path value matching the parameter name. |
|
|
133
|
+
| `HttpPath<T, { name: 'id' }>` | Path value from an explicit key. |
|
|
134
|
+
| `HttpHeader<T>` | Header value matching the parameter name. |
|
|
135
|
+
| `HttpHeader<T, { name: 'x-request-id' }>` | Header value from an explicit header name. |
|
|
136
|
+
| `FileUpload` | Required multipart file matching the parameter name, or the only declared uploaded file. |
|
|
137
|
+
|
|
138
|
+
Any unannotated non-path parameter fails at startup with an error that asks for an explicit HTTP annotation.
|
|
139
|
+
Routes may declare at most one `HttpBody<T>` parameter. Registering a route with multiple body parameters fails at startup instead of assigning one request body to multiple controller arguments.
|
|
140
|
+
An omitted optional `query?: HttpQueries<T>` parameter is injected as `undefined`. Once any query value is supplied, the resulting object is deserialized and validated as `T`, including its required properties.
|
|
141
|
+
|
|
142
|
+
`HttpRequest` normalizes constructed header names to lowercase; Node already supplies lowercased incoming names. An inferred `HttpHeader` lookup checks the parameter name, its lowercase and kebab-case forms, then the `x-`-prefixed kebab form, so `requestId: HttpHeader<string>` can read `x-request-id`. Use `{ name: '...' }` when the wire name should be explicit.
|
|
143
|
+
|
|
144
|
+
Repeated query keys are stored in order as `string[]`. `HttpQueries<T>` receives that complete shape, while a scalar `HttpQuery<T>` selects the last value for its key.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { HttpBody, HttpHeader, HttpQueries, HttpQuery, HttpRequestStream, http } from '@zyno-io/ts-server-foundation';
|
|
148
|
+
|
|
149
|
+
interface ListUsersQuery {
|
|
150
|
+
search?: string;
|
|
151
|
+
limit?: number;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@http.controller('/users')
|
|
155
|
+
class UserController {
|
|
156
|
+
@http.GET()
|
|
157
|
+
async list(query: HttpQueries<ListUsersQuery>) {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@http.GET('/by-email')
|
|
162
|
+
async byEmail(email: HttpQuery<string>) {
|
|
163
|
+
return { email };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@http.POST()
|
|
167
|
+
async create(body: HttpBody<CreateUserBody>, requestId: HttpHeader<string, { name: 'x-request-id' }>) {
|
|
168
|
+
return { requestId, body };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@http.POST('/stream')
|
|
172
|
+
async streamUpload(request: HttpRequestStream) {
|
|
173
|
+
for await (const chunk of request) {
|
|
174
|
+
// Stream directly without body parsing.
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Input Deserialization And Validation
|
|
181
|
+
|
|
182
|
+
Controller-facing values from `HttpBody<T>`, `HttpQueries<T>`, `HttpQuery<T>`, `HttpPath<T>`, `HttpHeader<T>`, and inferred path parameters are automatically reflected-deserialized and then validated before the controller is invoked.
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
request bytes or URL strings
|
|
186
|
+
-> JSON/multipart parsing when needed
|
|
187
|
+
-> HTTP normalization
|
|
188
|
+
-> reflected deserialization
|
|
189
|
+
-> reflected validation
|
|
190
|
+
-> final HTTP shape check
|
|
191
|
+
-> controller argument
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Deserialization includes primitive coercion, nested DTO projection, reflected class construction, `Date` construction, and registered transforms such as trimmed strings and phone normalization. Validation then enforces required and nullable properties, shapes, literals, enums, string and numeric constraints, and custom validators. A nonnumeric string coerces to `NaN`, which is rejected as an invalid `number`. Any failure becomes an HTTP `400` and the controller is not called.
|
|
195
|
+
|
|
196
|
+
An absent optional parameter bypasses deserialization and validation and is injected as `undefined`. This includes an optional standalone `FileUpload`. A missing required standalone upload produces HTTP `400`. A missing structured `HttpBody<T>` is treated as `{}`, which permits an all-optional body but still reports missing required properties. Undeclared DTO properties are generally dropped during deserialization rather than reported as errors.
|
|
197
|
+
|
|
198
|
+
`HttpRequest`, `HttpRequestStream`, `HttpResponse`, `ParsedJwt`, direct `FileUpload` parameters, and custom parameter-resolver results do not pass through this reflected pipeline. File uploads instead use the multipart declaration, size, and MIME guards. A file declared as a property inside `HttpBody<T>` is included in that body's reflected traversal after multipart parsing.
|
|
199
|
+
|
|
200
|
+
Route middleware and the `onController` workflow run before controller parameters are resolved. If either ends the response, parameter deserialization and validation do not run. Multipart parsing and upload guards may run earlier so unsafe file parts are rejected before controller dispatch.
|
|
201
|
+
|
|
202
|
+
### Custom Parameter Resolvers
|
|
203
|
+
|
|
204
|
+
Use `http.resolveParameter()` for a controller-specific class parameter. A resolver can be a function, an object with `resolve()`, or a resolver class. Register resolver classes as providers when they need DI.
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { createApp, http, type RouteParameterResolverContext } from '@zyno-io/ts-server-foundation';
|
|
208
|
+
|
|
209
|
+
class ResolvedTenant {
|
|
210
|
+
constructor(readonly id: string) {}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
class ResolvedTenantResolver {
|
|
214
|
+
resolve(context: RouteParameterResolverContext) {
|
|
215
|
+
return new ResolvedTenant(String(context.parameters.tenantId));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
@http.resolveParameter(ResolvedTenant, ResolvedTenantResolver)
|
|
220
|
+
@http.controller('/tenants/:tenantId')
|
|
221
|
+
class TenantController {
|
|
222
|
+
@http.GET()
|
|
223
|
+
get(tenantId: string, tenant: ResolvedTenant) {
|
|
224
|
+
return { tenantId, resolvedId: tenant.id };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const app = createApp({
|
|
229
|
+
controllers: [TenantController],
|
|
230
|
+
providers: [ResolvedTenantResolver]
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`RouteParameterResolverContext` includes the request, response, route, parameter name and reflection metadata, query object, and parameters already resolved to the left of the custom parameter. For an app-wide resolver, pass `httpResolvers: { ResolvedTenant: ResolvedTenantResolver }` to `createApp()`.
|
|
235
|
+
|
|
236
|
+
### Request-Scoped Values
|
|
237
|
+
|
|
238
|
+
`HttpRequest.store` is available for state that should live for one request. The exported cache helpers support string, symbol, and object keys; `getOrCacheValue()` is useful when middleware, parameter resolvers, and controllers may all need the same asynchronous lookup.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import { getOrCacheValue, type HttpRequest } from '@zyno-io/ts-server-foundation';
|
|
242
|
+
|
|
243
|
+
const CurrentAccountKey = Symbol('current-account');
|
|
244
|
+
|
|
245
|
+
function getCurrentAccount(request: HttpRequest) {
|
|
246
|
+
return getOrCacheValue(request, CurrentAccountKey, () => loadAccount(request));
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The full helper set is `getCachedValue`, `setCachedValue`, `hasCachedValue`, `clearCachedValue`, and `getOrCacheValue`. Values disappear with the request; this store is not a cross-request cache.
|
|
251
|
+
|
|
252
|
+
## Bodies And Streams
|
|
253
|
+
|
|
254
|
+
JSON body parsing happens when a route resolves `HttpBody<T>`. Multipart requests are guarded eagerly on every route except one that opts into raw streaming with `HttpRequestStream`; file parts are rejected unless the route explicitly declares matching `FileUpload` fields.
|
|
255
|
+
|
|
256
|
+
`HttpRequest.readBodyBuffer()` and `HttpRequest.readBodyText()` decode supported request content encodings, enforce request size limits, and cache the consumed body on `request.body`. They are safe to call more than once; later calls resolve from the cached buffer. For an incoming Node request, `request.body` remains unset until a guarded read consumes it. In-memory requests constructed with a buffer, string, object, or `.multiPart()` set `request.body` immediately.
|
|
257
|
+
|
|
258
|
+
Guarded reads accept an absent encoding or `identity`, plus `gzip` and `x-gzip`. Gzip is decoded before JSON or multipart parsing. Unsupported encodings return HTTP `415`; corrupt compressed data returns HTTP `400`.
|
|
259
|
+
|
|
260
|
+
Compressed bytes are limited by `HTTP_MAX_REQUEST_COMPRESSED_BODY_BYTES` and decoded or identity bytes by `HTTP_MAX_REQUEST_BODY_BYTES`. A numeric `content-length` above the applicable limit is rejected before streaming, while the byte transforms still enforce the real size when the header is missing, invalid, or too small.
|
|
261
|
+
|
|
262
|
+
`HttpRequestStream` deliberately bypasses content decoding, both byte limits, `content-length` rejection, JSON/multipart parsing, and upload guards. Routes combining it with `HttpBody<T>` or `FileUpload` fail registration.
|
|
263
|
+
|
|
264
|
+
In-memory object builders are a convenience boundary, not a wire-parser simulation: `HttpRequest.POST(url, object)` and `.json(object)` prepopulate `parsedBody`, so an `HttpBody<T>` route skips byte decoding and JSON parsing. Use a string or buffer with headers, or a real Node request, when testing encodings, malformed JSON, and byte limits. Both transports otherwise share CORS, static routing, route matching, parameter deserialization, middleware, handler, and observer behavior.
|
|
265
|
+
|
|
266
|
+
## Multipart Uploads
|
|
267
|
+
|
|
268
|
+
Multipart parsing uses `busboy` and writes uploaded files into temporary directories. The router cleans those temporary upload directories after the request finishes. File parts whose field name is not declared by a `FileUpload` parameter or `FileUpload` body property are rejected before being written.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { FileUpload, HttpBody, http } from '@zyno-io/ts-server-foundation';
|
|
272
|
+
|
|
273
|
+
interface UploadPayload {
|
|
274
|
+
title: string;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@http.controller('/files')
|
|
278
|
+
class FileController {
|
|
279
|
+
@http.POST()
|
|
280
|
+
async upload(payload: HttpBody<UploadPayload>, file: FileUpload<{ maxSize: '40MB'; allowedTypes: ['image/jpeg', 'image/png'] }>) {
|
|
281
|
+
return {
|
|
282
|
+
title: payload.title,
|
|
283
|
+
originalName: file.originalName,
|
|
284
|
+
type: file.type,
|
|
285
|
+
size: file.size
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Multipart field `_payload` is parsed as JSON and merged into the body object. Other text fields are also included. Multiple values for the same field are represented as arrays.
|
|
292
|
+
|
|
293
|
+
Multipart parsing runs before middleware for every guarded multipart route, including a route that injects only `HttpRequest`. Use `HttpRequestStream` when the controller must consume the raw multipart bytes without parsing or temporary upload files. Temporary upload directories are automatically removed after request handling completes, including error responses.
|
|
294
|
+
|
|
295
|
+
## Responses
|
|
296
|
+
|
|
297
|
+
Plain returned values are JSON serialized. `undefined` ends the response; `EmptyResponse` return annotations produce status `204`.
|
|
298
|
+
|
|
299
|
+
Responses intentionally do not pass through reflected validation, DTO projection, or a reflected serialization registry. TypeScript return types provide the application contract; at runtime the router sends the value produced by the controller through ordinary `JSON.stringify`. `ApiResponse<T, Status>` affects response metadata and status handling, not runtime value validation.
|
|
300
|
+
|
|
301
|
+
Use response result helpers for explicit writes:
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import { emptyResponse, jsonResponse, rawResponse, redirectResponse } from '@zyno-io/ts-server-foundation';
|
|
305
|
+
|
|
306
|
+
return jsonResponse({ ok: true }, 201);
|
|
307
|
+
return redirectResponse('/new-path', 302);
|
|
308
|
+
return emptyResponse(204);
|
|
309
|
+
return rawResponse(Buffer.from('data'), { contentType: 'application/octet-stream' });
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
The package also exports `OkResponse`, `RedirectResponse`, `EmptyResponse`, and `AnyResponse` return-type helpers. OpenAPI-specific response typing is documented in [OpenAPI](./openapi.md).
|
|
313
|
+
|
|
314
|
+
For imperative responses, `setHeader()` and `getHeader()` are case-insensitive, `headers` exposes comma-joined values, and `rawHeaders` preserves array values. `writeHead()` accepts an object or header tuples and sets the status before data is written. Call `response.write()`/`response.end()` to stream raw output; after a Node response commits, `headersSent` becomes true and later header changes are ignored. The in-memory response buffers writes and does not model header commitment, so `headersSent` remains false there. A handler that starts a Node stream owns ending it.
|
|
315
|
+
|
|
316
|
+
The router does not serialize another result after a response has ended or Node headers have been sent. Explicit `HEAD` routes run normally but both Node and in-memory transports suppress their response body while retaining status and headers.
|
|
317
|
+
|
|
318
|
+
## Errors
|
|
319
|
+
|
|
320
|
+
Throw `HttpError` or one of the exported helpers for intentional HTTP errors. Unhandled routing, middleware, parameter, and controller errors are returned as status `500` with a normalized JSON body.
|
|
321
|
+
|
|
322
|
+
`onResponse` is the final workflow and runs after router error normalization. If it throws, an in-memory `app.http.request()` rejects after upload cleanup. At the Node boundary, an uncommitted response becomes a generic `500`; a response whose headers were already committed is ended without appending another error body. Final-response listeners should observe and clean up, not throw as a response-control mechanism.
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { HttpBadRequestError, HttpNotFoundError } from '@zyno-io/ts-server-foundation';
|
|
326
|
+
|
|
327
|
+
throw new HttpBadRequestError('Invalid request');
|
|
328
|
+
throw new HttpNotFoundError('User not found');
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Error responses use this shape:
|
|
332
|
+
|
|
333
|
+
```json
|
|
334
|
+
{ "error": "User not found" }
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## CORS
|
|
338
|
+
|
|
339
|
+
Pass `cors` to `createApp()` to apply CORS headers to normal responses, error responses, and preflight requests.
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
const app = createApp({
|
|
343
|
+
controllers: [UserController],
|
|
344
|
+
cors: () => ({
|
|
345
|
+
hosts: ['https://app.example.com'],
|
|
346
|
+
credentials: true
|
|
347
|
+
})
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
`HttpCorsOptions` supports `hosts`, `paths`, `methods`, `credentials`, `allowHeaders`, and `exposeHeaders`.
|
|
352
|
+
|
|
353
|
+
## Middleware
|
|
354
|
+
|
|
355
|
+
Middleware classes implement `HttpMiddleware` and can be attached at controller or route level.
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { HttpBadRequestError, HttpMiddleware, HttpRequest, HttpResponse, http } from '@zyno-io/ts-server-foundation';
|
|
359
|
+
|
|
360
|
+
class RequireHeaderMiddleware implements HttpMiddleware {
|
|
361
|
+
async handle(request: HttpRequest, _response: HttpResponse) {
|
|
362
|
+
if (!request.headers['x-request-id']) throw new HttpBadRequestError('Missing request id');
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
class AuditMiddleware implements HttpMiddleware {
|
|
367
|
+
async handle(request: HttpRequest) {
|
|
368
|
+
request.context.audited = 'true';
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
@(http.controller('/admin').middleware(RequireHeaderMiddleware))
|
|
373
|
+
class AdminController {
|
|
374
|
+
@http.middleware(AuditMiddleware)
|
|
375
|
+
@(http.GET().use(RequireHeaderMiddleware))
|
|
376
|
+
async index() {
|
|
377
|
+
return { ok: true };
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Use `http.middleware(...)` as a class or method decorator, or chain `.middleware(...)`/`.use(...)` from `http.controller()` and a route decorator. Controller middleware always runs before route middleware. Within each group, middleware runs in the stored decorator/list order; when mixing standalone and chained decorators, remember that TypeScript applies stacked decorators from bottom to top.
|
|
383
|
+
|
|
384
|
+
Returning a response result such as `jsonResponse(...)` writes and ends the response, short-circuiting the remaining middleware, controller workflow, parameter resolution, and handler. Middleware may also end the supplied `HttpResponse` directly.
|
|
385
|
+
|
|
386
|
+
Registered middleware is resolved through DI. Register middleware with `scope: 'request'` when it injects request-scoped providers or `HttpRequest`; it then shares the controller's request context. A middleware class with no constructor arguments may be used without provider registration and is constructed directly. Once a middleware class is registered, DI failures are reported rather than falling back to direct construction.
|
|
387
|
+
|
|
388
|
+
## Static Files
|
|
389
|
+
|
|
390
|
+
Pass `staticFiles` to `createApp()` to serve files after route matching. Static files are only considered for `GET` requests that do not match a registered route.
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
const app = createApp({
|
|
394
|
+
controllers: [ApiController],
|
|
395
|
+
staticFiles: {
|
|
396
|
+
directory: 'static',
|
|
397
|
+
spaFallback: 'index.html'
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
`staticFiles: true` uses the default `static/` directory. `directory` defaults to `static`, `index` to `index.html`, and `spaFallback` to the selected index. A custom fallback is served when no concrete file exists. Static handling is GET-only and never shadows a registered route; unsafe decoded paths return `400`.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: home
|
|
3
|
+
|
|
4
|
+
hero:
|
|
5
|
+
name: '@zyno-io/ts-server-foundation'
|
|
6
|
+
text: 'Server Foundation Library'
|
|
7
|
+
tagline: TypeScript server foundation with reflected type metadata
|
|
8
|
+
actions:
|
|
9
|
+
- theme: brand
|
|
10
|
+
text: Get Started
|
|
11
|
+
link: /getting-started
|
|
12
|
+
- theme: alt
|
|
13
|
+
text: Explore Features
|
|
14
|
+
link: /overview
|
|
15
|
+
|
|
16
|
+
features:
|
|
17
|
+
- title: Application Runtime
|
|
18
|
+
details: createApp, lifecycle hooks, app.http server APIs, health checks, CORS, request handling, and request-scoped DI.
|
|
19
|
+
- title: Dependency Injection
|
|
20
|
+
details: Constructor injection from reflected type metadata, request scopes, module exports, and globally injectable imported exports.
|
|
21
|
+
- title: HTTP
|
|
22
|
+
details: Decorator-based controllers, explicit body/query/header/path annotations, multipart uploads, raw request streaming, and OpenAPI metadata.
|
|
23
|
+
- title: Database
|
|
24
|
+
details: Thin active-record layer over mysql2 and pg with transactions, savepoints, raw SQL bindings, locks, migrations, and schema diffing.
|
|
25
|
+
- title: Workers
|
|
26
|
+
details: In-process job registration, inline test execution, cron scheduling, queue recording, and DI-owned job handlers.
|
|
27
|
+
- title: SRPC
|
|
28
|
+
details: HMAC-authenticated WebSocket RPC with generated proto types, bidirectional calls, byte streams, and upgrade claiming.
|
|
29
|
+
- title: Configuration
|
|
30
|
+
details: Reflected config classes loaded from env files and Env while preserving process env for later code and child processes.
|
|
31
|
+
- title: Testing
|
|
32
|
+
details: Test facades, in-memory HTTP requests, isolated MySQL/PostgreSQL databases, seed hooks, and assertion helpers.
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
corepack yarn add @zyno-io/ts-server-foundation
|
|
39
|
+
corepack yarn tsf-install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`tsf-install` configures the TypeScript transform and compiler dependencies. The TSF compiler emits reflected type metadata and compiler-recognized annotation markers used by DI, HTTP parameters, config classes, entities, validation, and OpenAPI generation. See [Getting Started](./getting-started.md#typescript-configuration) for the manual configuration.
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { BaseAppConfig, createApp, createDatabase, http } from '@zyno-io/ts-server-foundation';
|
|
48
|
+
|
|
49
|
+
class AppConfig extends BaseAppConfig {
|
|
50
|
+
APP_ENV = 'development';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@http.controller('/hello')
|
|
54
|
+
class HelloController {
|
|
55
|
+
@http.GET()
|
|
56
|
+
hello() {
|
|
57
|
+
return { ok: true };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
class AppDatabase extends createDatabase('mysql', {}, []) {}
|
|
62
|
+
|
|
63
|
+
export const app = createApp({
|
|
64
|
+
config: AppConfig,
|
|
65
|
+
db: AppDatabase,
|
|
66
|
+
controllers: [HelloController]
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Documentation
|
|
71
|
+
|
|
72
|
+
- [Feature Overview](./overview.md)
|
|
73
|
+
- [Getting Started](./getting-started.md)
|
|
74
|
+
- [Public API](./public-api.md)
|
|
75
|
+
- [Dependency Injection](./di.md)
|
|
76
|
+
- [Configuration](./configuration.md)
|
|
77
|
+
- [Environment](./env.md)
|
|
78
|
+
- [Database](./database.md)
|
|
79
|
+
- [SQL](./sql.md)
|
|
80
|
+
- [Migrations](./migrations.md)
|
|
81
|
+
- [HTTP](./http.md)
|
|
82
|
+
- [Uploads](./uploads.md)
|
|
83
|
+
- [OpenAPI](./openapi.md)
|
|
84
|
+
- [Authentication](./authentication.md)
|
|
85
|
+
- [Health Checks](./health.md)
|
|
86
|
+
- [DevConsole](./devconsole.md)
|
|
87
|
+
- [Logging](./logging.md)
|
|
88
|
+
- [Types](./types.md)
|
|
89
|
+
- [Type Reflection](./reflection.md)
|
|
90
|
+
- [Type Reflection Architecture](./type-reflection-architecture.md)
|
|
91
|
+
- [Testing](./testing.md)
|
|
92
|
+
- [CLI](./cli.md)
|
|
93
|
+
- [Workers](./worker.md)
|
|
94
|
+
- [Redis](./redis.md)
|
|
95
|
+
- [SRPC](./srpc.md)
|
|
96
|
+
- [Mail](./mail.md)
|
|
97
|
+
- [Leader Service](./leader-service.md)
|
|
98
|
+
- [Mesh Service](./mesh-service.md)
|
|
99
|
+
- [Mesh Client Tracking](./mesh-client.md)
|
|
100
|
+
- [Helpers](./helpers.md)
|
|
101
|
+
- [Telemetry](./telemetry.md)
|
|
102
|
+
- [Release](./release.md)
|
|
103
|
+
- [Documentation Maintenance](./documentation-plan.md)
|
|
104
|
+
|
|
105
|
+
## Acknowledgements
|
|
106
|
+
|
|
107
|
+
TS Server Foundation owes a great deal to the open-source projects that made its architecture possible. [Deepkit](https://github.com/marcj/deepkit) inspired many of the design ideas behind its runtime type reflection, dependency injection, and metadata-driven server APIs. We are especially grateful to Deepkit's maintainer, [Marc J. Schmidt](https://github.com/marcj), for showing how powerful a cohesive, type-aware TypeScript framework can be.
|
|
108
|
+
|
|
109
|
+
[Typia](https://typia.io/) and [ttsc](https://github.com/samchon/ttsc) provided the essential compiler groundwork for bringing those ideas to TypeScript 7. TSF builds on their type-analysis and transform infrastructure to generate the runtime metadata at the heart of the framework. Our sincere thanks to Jeongho Nam and every contributor to these projects for making that work available to the TypeScript community.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# LeaderService
|
|
2
|
+
|
|
3
|
+
Distributed leader election using a Redis TTL lease with atomic acquisition and periodic renewal. Redis grants the lease to one owner at a time, but an expired holder can still locally report leadership until its next renewal detects the loss, so leader-only work must tolerate lease transitions.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { LeaderService } from '@zyno-io/ts-server-foundation';
|
|
9
|
+
|
|
10
|
+
const leader = new LeaderService('my-feature');
|
|
11
|
+
|
|
12
|
+
leader.setBecameLeaderCallback(async () => {
|
|
13
|
+
console.log('This instance is now the leader');
|
|
14
|
+
// Start leader-only work (e.g. scheduled jobs, cleanup tasks)
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
leader.setLostLeaderCallback(async () => {
|
|
18
|
+
console.log('Leadership lost');
|
|
19
|
+
// Stop leader-only work
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
leader.start();
|
|
23
|
+
|
|
24
|
+
// Check leadership status at any time
|
|
25
|
+
if (leader.isLeader) {
|
|
26
|
+
// perform leader-only operation
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Graceful shutdown
|
|
30
|
+
await leader.stop();
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API
|
|
34
|
+
|
|
35
|
+
### `new LeaderService(key: string, options?: LeaderServiceOptions)`
|
|
36
|
+
|
|
37
|
+
Creates a new leader election instance.
|
|
38
|
+
|
|
39
|
+
- **`key`** -- Logical name for the leadership group. All instances using the same key compete for the same lock. The full Redis key is derived as `{prefix}:leader:{key}`.
|
|
40
|
+
- **`options`** -- Optional tuning parameters (see below).
|
|
41
|
+
|
|
42
|
+
### `LeaderServiceOptions`
|
|
43
|
+
|
|
44
|
+
| Option | Type | Default | Description |
|
|
45
|
+
| ------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
|
|
46
|
+
| `ttlMs` | `number` | `30000` | Lock TTL in milliseconds. If the leader crashes without releasing, the lock expires after this period. |
|
|
47
|
+
| `renewalIntervalMs` | `number` | `10000` | How often the leader renews its lock. Should be well below `ttlMs` to avoid accidental expiry. |
|
|
48
|
+
| `retryDelayMs` | `number` | `5000` | Delay between acquisition attempts for non-leader instances. |
|
|
49
|
+
|
|
50
|
+
### Properties
|
|
51
|
+
|
|
52
|
+
| Property | Type | Description |
|
|
53
|
+
| ---------- | --------- | ----------------------------------------------------------------------------------------- |
|
|
54
|
+
| `isLeader` | `boolean` | Whether this instance most recently acquired the lease and has not yet detected its loss. |
|
|
55
|
+
|
|
56
|
+
### Methods
|
|
57
|
+
|
|
58
|
+
#### `setBecameLeaderCallback(callback: () => void | Promise<void>): void`
|
|
59
|
+
|
|
60
|
+
Register a callback invoked when this instance acquires leadership. Errors thrown by the callback are logged but do not affect leader status.
|
|
61
|
+
|
|
62
|
+
#### `setLostLeaderCallback(callback: () => void | Promise<void>): void`
|
|
63
|
+
|
|
64
|
+
Register a callback invoked when this instance loses leadership (e.g. renewal failure, network partition). Errors are logged and do not prevent re-election attempts.
|
|
65
|
+
|
|
66
|
+
#### `start(): void`
|
|
67
|
+
|
|
68
|
+
Begin participating in leader election. Throws if already running. Acquisition is asynchronous -- the instance may not be leader immediately after `start()` returns.
|
|
69
|
+
|
|
70
|
+
#### `stop(): Promise<void>`
|
|
71
|
+
|
|
72
|
+
Stop participating and release the lock if currently leader. Safe to call multiple times.
|
|
73
|
+
|
|
74
|
+
## How It Works
|
|
75
|
+
|
|
76
|
+
1. **Acquisition**: Each instance attempts to set a Redis key with `NX` (set-if-not-exists) semantics and a TTL via a Lua script. If the key doesn't exist, the caller becomes leader.
|
|
77
|
+
2. **Renewal**: The leader periodically refreshes the TTL on its lock. If the key's value no longer matches (another instance took over), leadership is considered lost.
|
|
78
|
+
3. **Release**: On `stop()`, the leader deletes its key (only if the value still matches), allowing immediate failover.
|
|
79
|
+
4. **Retry**: Non-leaders retry acquisition on a timer. If the leader crashes, the lock expires after `ttlMs` and another instance acquires it.
|
|
80
|
+
|
|
81
|
+
All Redis operations use Lua scripts for atomicity:
|
|
82
|
+
|
|
83
|
+
- **ACQUIRE** -- `SET key value PX ttl` only if the key doesn't exist
|
|
84
|
+
- **RENEW** -- `PEXPIRE key ttl` only if the value matches
|
|
85
|
+
- **RELEASE** -- `DEL key` only if the value matches
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
The Redis connection is configured via environment variables with the `MUTEX_REDIS_` prefix (falls back to `REDIS_`):
|
|
90
|
+
|
|
91
|
+
| Variable | Description |
|
|
92
|
+
| --------------------------- | ------------------------------------------------------------ |
|
|
93
|
+
| `MUTEX_REDIS_HOST` | Redis host |
|
|
94
|
+
| `MUTEX_REDIS_PORT` | Redis port |
|
|
95
|
+
| `MUTEX_REDIS_PREFIX` | Key prefix (falls back to `REDIS_PREFIX`, then package name) |
|
|
96
|
+
| `MUTEX_REDIS_SENTINEL_HOST` | Sentinel host (optional) |
|
|
97
|
+
| `MUTEX_REDIS_SENTINEL_PORT` | Sentinel port (optional) |
|
|
98
|
+
| `MUTEX_REDIS_SENTINEL_NAME` | Sentinel master name (optional) |
|