@sixthsummit/ship-api 0.0.0-stage → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +605 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +58 -2
- package/cli/commands/add.js +537 -0
- package/cli/commands/contract.js +2 -0
- package/cli/commands/create.js +250 -0
- package/cli/commands/dev.js +227 -0
- package/cli/commands/doctor.js +286 -0
- package/cli/commands/generate.js +937 -0
- package/cli/commands/graph.js +2 -0
- package/cli/commands/migrate-orm.js +1171 -0
- package/cli/commands/update.js +37 -0
- package/cli/ship-api.js +285 -0
- package/lib/app/auth/AuthProvider.d.ts +91 -0
- package/lib/app/auth/AuthProvider.d.ts.map +1 -0
- package/lib/app/auth/AuthProvider.js +13 -0
- package/lib/app/auth/AuthProvider.js.map +1 -0
- package/lib/app/auth/adapters/firebase.d.ts +79 -0
- package/lib/app/auth/adapters/firebase.d.ts.map +1 -0
- package/lib/app/auth/adapters/firebase.js +122 -0
- package/lib/app/auth/adapters/firebase.js.map +1 -0
- package/lib/app/auth/adapters/jwtCookie.d.ts +55 -0
- package/lib/app/auth/adapters/jwtCookie.d.ts.map +1 -0
- package/lib/app/auth/adapters/jwtCookie.js +120 -0
- package/lib/app/auth/adapters/jwtCookie.js.map +1 -0
- package/lib/app/auth/index.d.ts +8 -0
- package/lib/app/auth/index.d.ts.map +1 -0
- package/lib/app/auth/index.js +7 -0
- package/lib/app/auth/index.js.map +1 -0
- package/lib/app/auth/jwt/AuthFlow.d.ts +94 -0
- package/lib/app/auth/jwt/AuthFlow.d.ts.map +1 -0
- package/lib/app/auth/jwt/AuthFlow.js +127 -0
- package/lib/app/auth/jwt/AuthFlow.js.map +1 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts +80 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts.map +1 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js +134 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js.map +1 -0
- package/lib/app/auth/jwt/JwtSigner.d.ts +123 -0
- package/lib/app/auth/jwt/JwtSigner.d.ts.map +1 -0
- package/lib/app/auth/jwt/JwtSigner.js +118 -0
- package/lib/app/auth/jwt/JwtSigner.js.map +1 -0
- package/lib/app/auth/jwt/RefreshTokenStore.d.ts +97 -0
- package/lib/app/auth/jwt/RefreshTokenStore.d.ts.map +1 -0
- package/lib/app/auth/jwt/RefreshTokenStore.js +122 -0
- package/lib/app/auth/jwt/RefreshTokenStore.js.map +1 -0
- package/lib/app/auth/permissionDefinition.d.ts +20 -0
- package/lib/app/auth/permissionDefinition.d.ts.map +1 -0
- package/lib/app/auth/permissionDefinition.js +2 -0
- package/lib/app/auth/permissionDefinition.js.map +1 -0
- package/lib/app/context/RequestContext.d.ts +59 -0
- package/lib/app/context/RequestContext.d.ts.map +1 -0
- package/lib/app/context/RequestContext.js +25 -0
- package/lib/app/context/RequestContext.js.map +1 -0
- package/lib/app/db/QueryOptions.d.ts +82 -0
- package/lib/app/db/QueryOptions.d.ts.map +1 -0
- package/lib/app/db/QueryOptions.js +37 -0
- package/lib/app/db/QueryOptions.js.map +1 -0
- package/lib/app/db/baseFields.d.ts +60 -0
- package/lib/app/db/baseFields.d.ts.map +1 -0
- package/lib/app/db/baseFields.js +54 -0
- package/lib/app/db/baseFields.js.map +1 -0
- package/lib/app/db/buildWhere.d.ts +22 -0
- package/lib/app/db/buildWhere.d.ts.map +1 -0
- package/lib/app/db/buildWhere.js +75 -0
- package/lib/app/db/buildWhere.js.map +1 -0
- package/lib/app/db/client.d.ts +111 -0
- package/lib/app/db/client.d.ts.map +1 -0
- package/lib/app/db/client.js +99 -0
- package/lib/app/db/client.js.map +1 -0
- package/lib/app/db/tenantScoped.d.ts +59 -0
- package/lib/app/db/tenantScoped.d.ts.map +1 -0
- package/lib/app/db/tenantScoped.js +54 -0
- package/lib/app/db/tenantScoped.js.map +1 -0
- package/lib/app/db/transaction.d.ts +58 -0
- package/lib/app/db/transaction.d.ts.map +1 -0
- package/lib/app/db/transaction.js +106 -0
- package/lib/app/db/transaction.js.map +1 -0
- package/lib/app/health/HealthCheck.d.ts +121 -0
- package/lib/app/health/HealthCheck.d.ts.map +1 -0
- package/lib/app/health/HealthCheck.js +151 -0
- package/lib/app/health/HealthCheck.js.map +1 -0
- package/lib/app/health/redisHealthCheck.d.ts +14 -0
- package/lib/app/health/redisHealthCheck.d.ts.map +1 -0
- package/lib/app/health/redisHealthCheck.js +21 -0
- package/lib/app/health/redisHealthCheck.js.map +1 -0
- package/lib/app/lifecycle/Bootstrapper.d.ts +92 -0
- package/lib/app/lifecycle/Bootstrapper.d.ts.map +1 -0
- package/lib/app/lifecycle/Bootstrapper.js +99 -0
- package/lib/app/lifecycle/Bootstrapper.js.map +1 -0
- package/lib/app/registry/routes.d.ts +89 -0
- package/lib/app/registry/routes.d.ts.map +1 -0
- package/lib/app/registry/routes.js +72 -0
- package/lib/app/registry/routes.js.map +1 -0
- package/lib/app/services/DrizzleEntityService.d.ts +123 -0
- package/lib/app/services/DrizzleEntityService.d.ts.map +1 -0
- package/lib/app/services/DrizzleEntityService.js +342 -0
- package/lib/app/services/DrizzleEntityService.js.map +1 -0
- package/lib/app/services/RedisProvider.d.ts +52 -0
- package/lib/app/services/RedisProvider.d.ts.map +1 -0
- package/lib/app/services/RedisProvider.js +75 -0
- package/lib/app/services/RedisProvider.js.map +1 -0
- package/lib/app/services/cache/Cache.d.ts +70 -0
- package/lib/app/services/cache/Cache.d.ts.map +1 -0
- package/lib/app/services/cache/Cache.js +18 -0
- package/lib/app/services/cache/Cache.js.map +1 -0
- package/lib/app/services/cache/InMemoryCache.d.ts +35 -0
- package/lib/app/services/cache/InMemoryCache.d.ts.map +1 -0
- package/lib/app/services/cache/InMemoryCache.js +76 -0
- package/lib/app/services/cache/InMemoryCache.js.map +1 -0
- package/lib/app/services/cache/RedisCache.d.ts +99 -0
- package/lib/app/services/cache/RedisCache.d.ts.map +1 -0
- package/lib/app/services/cache/RedisCache.js +150 -0
- package/lib/app/services/cache/RedisCache.js.map +1 -0
- package/lib/app/services/cache/cached.d.ts +30 -0
- package/lib/app/services/cache/cached.d.ts.map +1 -0
- package/lib/app/services/cache/cached.js +38 -0
- package/lib/app/services/cache/cached.js.map +1 -0
- package/lib/app/services/cache/index.d.ts +5 -0
- package/lib/app/services/cache/index.d.ts.map +1 -0
- package/lib/app/services/cache/index.js +4 -0
- package/lib/app/services/cache/index.js.map +1 -0
- package/lib/app/services/cron/defineCron.d.ts +57 -0
- package/lib/app/services/cron/defineCron.d.ts.map +1 -0
- package/lib/app/services/cron/defineCron.js +15 -0
- package/lib/app/services/cron/defineCron.js.map +1 -0
- package/lib/app/services/cron/index.d.ts +2 -0
- package/lib/app/services/cron/index.d.ts.map +1 -0
- package/lib/app/services/cron/index.js +2 -0
- package/lib/app/services/cron/index.js.map +1 -0
- package/lib/app/services/hooks/LifecycleHooks.d.ts +61 -0
- package/lib/app/services/hooks/LifecycleHooks.d.ts.map +1 -0
- package/lib/app/services/hooks/LifecycleHooks.js +85 -0
- package/lib/app/services/hooks/LifecycleHooks.js.map +1 -0
- package/lib/app/services/jobs/JobsManager.d.ts +67 -0
- package/lib/app/services/jobs/JobsManager.d.ts.map +1 -0
- package/lib/app/services/jobs/JobsManager.js +121 -0
- package/lib/app/services/jobs/JobsManager.js.map +1 -0
- package/lib/app/services/jobs/bullBoard.d.ts +72 -0
- package/lib/app/services/jobs/bullBoard.d.ts.map +1 -0
- package/lib/app/services/jobs/bullBoard.js +96 -0
- package/lib/app/services/jobs/bullBoard.js.map +1 -0
- package/lib/app/services/jobs/defineJob.d.ts +81 -0
- package/lib/app/services/jobs/defineJob.d.ts.map +1 -0
- package/lib/app/services/jobs/defineJob.js +49 -0
- package/lib/app/services/jobs/defineJob.js.map +1 -0
- package/lib/app/services/jobs/index.d.ts +4 -0
- package/lib/app/services/jobs/index.d.ts.map +1 -0
- package/lib/app/services/jobs/index.js +4 -0
- package/lib/app/services/jobs/index.js.map +1 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts +23 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js +51 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js.map +1 -0
- package/lib/app/services/rateLimit/RateLimitBackend.d.ts +41 -0
- package/lib/app/services/rateLimit/RateLimitBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/RateLimitBackend.js +19 -0
- package/lib/app/services/rateLimit/RateLimitBackend.js.map +1 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts +16 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js +80 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js.map +1 -0
- package/lib/app/services/rateLimit/index.d.ts +4 -0
- package/lib/app/services/rateLimit/index.d.ts.map +1 -0
- package/lib/app/services/rateLimit/index.js +3 -0
- package/lib/app/services/rateLimit/index.js.map +1 -0
- package/lib/app/services/storage/DiskStorageAdapter.d.ts +62 -0
- package/lib/app/services/storage/DiskStorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/DiskStorageAdapter.js +295 -0
- package/lib/app/services/storage/DiskStorageAdapter.js.map +1 -0
- package/lib/app/services/storage/GCSStorageAdapter.d.ts +44 -0
- package/lib/app/services/storage/GCSStorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/GCSStorageAdapter.js +133 -0
- package/lib/app/services/storage/GCSStorageAdapter.js.map +1 -0
- package/lib/app/services/storage/S3StorageAdapter.d.ts +57 -0
- package/lib/app/services/storage/S3StorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/S3StorageAdapter.js +162 -0
- package/lib/app/services/storage/S3StorageAdapter.js.map +1 -0
- package/lib/app/services/storage/StorageService.d.ts +88 -0
- package/lib/app/services/storage/StorageService.d.ts.map +1 -0
- package/lib/app/services/storage/StorageService.js +18 -0
- package/lib/app/services/storage/StorageService.js.map +1 -0
- package/lib/app/services/storage/index.d.ts +5 -0
- package/lib/app/services/storage/index.d.ts.map +1 -0
- package/lib/app/services/storage/index.js +4 -0
- package/lib/app/services/storage/index.js.map +1 -0
- package/lib/app/utils/ContextValidators.d.ts +46 -0
- package/lib/app/utils/ContextValidators.d.ts.map +1 -0
- package/lib/app/utils/ContextValidators.js +81 -0
- package/lib/app/utils/ContextValidators.js.map +1 -0
- package/lib/app/utils/defineEnv.d.ts +80 -0
- package/lib/app/utils/defineEnv.d.ts.map +1 -0
- package/lib/app/utils/defineEnv.js +95 -0
- package/lib/app/utils/defineEnv.js.map +1 -0
- package/lib/client.d.ts +139 -0
- package/lib/client.d.ts.map +1 -0
- package/lib/client.js +98 -0
- package/lib/client.js.map +1 -0
- package/lib/contract/application.d.ts +3 -0
- package/lib/contract/application.d.ts.map +1 -0
- package/lib/contract/application.js +2 -0
- package/lib/contract/application.js.map +1 -0
- package/lib/contract/client.d.ts +3 -0
- package/lib/contract/client.d.ts.map +1 -0
- package/lib/contract/client.js +3 -0
- package/lib/contract/client.js.map +1 -0
- package/lib/contract/index.d.ts +3 -0
- package/lib/contract/index.d.ts.map +1 -0
- package/lib/contract/index.js +3 -0
- package/lib/contract/index.js.map +1 -0
- package/lib/contract/manifest.d.ts +3 -0
- package/lib/contract/manifest.d.ts.map +1 -0
- package/lib/contract/manifest.js +2 -0
- package/lib/contract/manifest.js.map +1 -0
- package/lib/contract/openapi.d.ts +3 -0
- package/lib/contract/openapi.d.ts.map +1 -0
- package/lib/contract/openapi.js +3 -0
- package/lib/contract/openapi.js.map +1 -0
- package/lib/contract/project.d.ts +3 -0
- package/lib/contract/project.d.ts.map +1 -0
- package/lib/contract/project.js +3 -0
- package/lib/contract/project.js.map +1 -0
- package/lib/contract/schema.d.ts +3 -0
- package/lib/contract/schema.d.ts.map +1 -0
- package/lib/contract/schema.js +3 -0
- package/lib/contract/schema.js.map +1 -0
- package/lib/drizzle/index.d.ts +3 -0
- package/lib/drizzle/index.d.ts.map +1 -0
- package/lib/drizzle/index.js +3 -0
- package/lib/drizzle/index.js.map +1 -0
- package/lib/hono/auth.d.ts +6 -0
- package/lib/hono/auth.d.ts.map +1 -0
- package/lib/hono/auth.js +54 -0
- package/lib/hono/auth.js.map +1 -0
- package/lib/hono/index.d.ts +4 -0
- package/lib/hono/index.d.ts.map +1 -0
- package/lib/hono/index.js +4 -0
- package/lib/hono/index.js.map +1 -0
- package/lib/http/app/createApp.d.ts +132 -0
- package/lib/http/app/createApp.d.ts.map +1 -0
- package/lib/http/app/createApp.js +215 -0
- package/lib/http/app/createApp.js.map +1 -0
- package/lib/http/app/devRoutes.d.ts +31 -0
- package/lib/http/app/devRoutes.d.ts.map +1 -0
- package/lib/http/app/devRoutes.js +145 -0
- package/lib/http/app/devRoutes.js.map +1 -0
- package/lib/http/app/errors.d.ts +45 -0
- package/lib/http/app/errors.d.ts.map +1 -0
- package/lib/http/app/errors.js +93 -0
- package/lib/http/app/errors.js.map +1 -0
- package/lib/http/app/health.d.ts +66 -0
- package/lib/http/app/health.d.ts.map +1 -0
- package/lib/http/app/health.js +104 -0
- package/lib/http/app/health.js.map +1 -0
- package/lib/http/errors/AppError.d.ts +10 -0
- package/lib/http/errors/AppError.d.ts.map +1 -0
- package/lib/http/errors/AppError.js +19 -0
- package/lib/http/errors/AppError.js.map +1 -0
- package/lib/http/errors/AuthenticationError.d.ts +8 -0
- package/lib/http/errors/AuthenticationError.d.ts.map +1 -0
- package/lib/http/errors/AuthenticationError.js +10 -0
- package/lib/http/errors/AuthenticationError.js.map +1 -0
- package/lib/http/errors/AuthorizationError.d.ts +8 -0
- package/lib/http/errors/AuthorizationError.d.ts.map +1 -0
- package/lib/http/errors/AuthorizationError.js +10 -0
- package/lib/http/errors/AuthorizationError.js.map +1 -0
- package/lib/http/errors/BadRequestError.d.ts +8 -0
- package/lib/http/errors/BadRequestError.d.ts.map +1 -0
- package/lib/http/errors/BadRequestError.js +10 -0
- package/lib/http/errors/BadRequestError.js.map +1 -0
- package/lib/http/errors/ConflictError.d.ts +8 -0
- package/lib/http/errors/ConflictError.d.ts.map +1 -0
- package/lib/http/errors/ConflictError.js +10 -0
- package/lib/http/errors/ConflictError.js.map +1 -0
- package/lib/http/errors/InternalServerError.d.ts +8 -0
- package/lib/http/errors/InternalServerError.d.ts.map +1 -0
- package/lib/http/errors/InternalServerError.js +10 -0
- package/lib/http/errors/InternalServerError.js.map +1 -0
- package/lib/http/errors/NotFoundError.d.ts +8 -0
- package/lib/http/errors/NotFoundError.d.ts.map +1 -0
- package/lib/http/errors/NotFoundError.js +10 -0
- package/lib/http/errors/NotFoundError.js.map +1 -0
- package/lib/http/errors/RateLimitError.d.ts +13 -0
- package/lib/http/errors/RateLimitError.d.ts.map +1 -0
- package/lib/http/errors/RateLimitError.js +16 -0
- package/lib/http/errors/RateLimitError.js.map +1 -0
- package/lib/http/errors/ServiceUnavailableError.d.ts +8 -0
- package/lib/http/errors/ServiceUnavailableError.d.ts.map +1 -0
- package/lib/http/errors/ServiceUnavailableError.js +10 -0
- package/lib/http/errors/ServiceUnavailableError.js.map +1 -0
- package/lib/http/errors/ValidationError.d.ts +9 -0
- package/lib/http/errors/ValidationError.d.ts.map +1 -0
- package/lib/http/errors/ValidationError.js +12 -0
- package/lib/http/errors/ValidationError.js.map +1 -0
- package/lib/http/errors/index.d.ts +11 -0
- package/lib/http/errors/index.d.ts.map +1 -0
- package/lib/http/errors/index.js +12 -0
- package/lib/http/errors/index.js.map +1 -0
- package/lib/http/middleware/apiKey.d.ts +9 -0
- package/lib/http/middleware/apiKey.d.ts.map +1 -0
- package/lib/http/middleware/apiKey.js +71 -0
- package/lib/http/middleware/apiKey.js.map +1 -0
- package/lib/http/middleware/csrf.d.ts +63 -0
- package/lib/http/middleware/csrf.d.ts.map +1 -0
- package/lib/http/middleware/csrf.js +169 -0
- package/lib/http/middleware/csrf.js.map +1 -0
- package/lib/http/middleware/httpLogger.d.ts +39 -0
- package/lib/http/middleware/httpLogger.d.ts.map +1 -0
- package/lib/http/middleware/httpLogger.js +118 -0
- package/lib/http/middleware/httpLogger.js.map +1 -0
- package/lib/http/middleware/idempotency.d.ts +48 -0
- package/lib/http/middleware/idempotency.d.ts.map +1 -0
- package/lib/http/middleware/idempotency.js +180 -0
- package/lib/http/middleware/idempotency.js.map +1 -0
- package/lib/http/middleware/rateLimit.d.ts +105 -0
- package/lib/http/middleware/rateLimit.d.ts.map +1 -0
- package/lib/http/middleware/rateLimit.js +84 -0
- package/lib/http/middleware/rateLimit.js.map +1 -0
- package/lib/http/middleware/requireAuth.d.ts +58 -0
- package/lib/http/middleware/requireAuth.d.ts.map +1 -0
- package/lib/http/middleware/requireAuth.js +63 -0
- package/lib/http/middleware/requireAuth.js.map +1 -0
- package/lib/http/middleware/requirePermission.d.ts +23 -0
- package/lib/http/middleware/requirePermission.d.ts.map +1 -0
- package/lib/http/middleware/requirePermission.js +50 -0
- package/lib/http/middleware/requirePermission.js.map +1 -0
- package/lib/http/middleware/resolveTenant.d.ts +41 -0
- package/lib/http/middleware/resolveTenant.d.ts.map +1 -0
- package/lib/http/middleware/resolveTenant.js +17 -0
- package/lib/http/middleware/resolveTenant.js.map +1 -0
- package/lib/http/streaming/sse.d.ts +31 -0
- package/lib/http/streaming/sse.d.ts.map +1 -0
- package/lib/http/streaming/sse.js +11 -0
- package/lib/http/streaming/sse.js.map +1 -0
- package/lib/http/streaming/streamLLM.d.ts +94 -0
- package/lib/http/streaming/streamLLM.d.ts.map +1 -0
- package/lib/http/streaming/streamLLM.js +94 -0
- package/lib/http/streaming/streamLLM.js.map +1 -0
- package/lib/http/utils/authCookies.d.ts +74 -0
- package/lib/http/utils/authCookies.d.ts.map +1 -0
- package/lib/http/utils/authCookies.js +102 -0
- package/lib/http/utils/authCookies.js.map +1 -0
- package/lib/http/utils/clientIp.d.ts +85 -0
- package/lib/http/utils/clientIp.d.ts.map +1 -0
- package/lib/http/utils/clientIp.js +249 -0
- package/lib/http/utils/clientIp.js.map +1 -0
- package/lib/http/utils/index.d.ts +4 -0
- package/lib/http/utils/index.d.ts.map +1 -0
- package/lib/http/utils/index.js +5 -0
- package/lib/http/utils/index.js.map +1 -0
- package/lib/http/utils/metaTags.d.ts +49 -0
- package/lib/http/utils/metaTags.d.ts.map +1 -0
- package/lib/http/utils/metaTags.js +32 -0
- package/lib/http/utils/metaTags.js.map +1 -0
- package/lib/http/utils/publicSuffix.d.ts +34 -0
- package/lib/http/utils/publicSuffix.d.ts.map +1 -0
- package/lib/http/utils/publicSuffix.js +276 -0
- package/lib/http/utils/publicSuffix.js.map +1 -0
- package/lib/http/utils/uploads.d.ts +92 -0
- package/lib/http/utils/uploads.d.ts.map +1 -0
- package/lib/http/utils/uploads.js +126 -0
- package/lib/http/utils/uploads.js.map +1 -0
- package/lib/http/utils/validate.d.ts +41 -0
- package/lib/http/utils/validate.d.ts.map +1 -0
- package/lib/http/utils/validate.js +55 -0
- package/lib/http/utils/validate.js.map +1 -0
- package/lib/http/utils/webhooks.d.ts +63 -0
- package/lib/http/utils/webhooks.d.ts.map +1 -0
- package/lib/http/utils/webhooks.js +133 -0
- package/lib/http/utils/webhooks.js.map +1 -0
- package/lib/http/ws/auth.d.ts +46 -0
- package/lib/http/ws/auth.d.ts.map +1 -0
- package/lib/http/ws/auth.js +123 -0
- package/lib/http/ws/auth.js.map +1 -0
- package/lib/index.d.ts +80 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +61 -0
- package/lib/index.js.map +1 -0
- package/lib/kernel/index.d.ts +3 -0
- package/lib/kernel/index.d.ts.map +1 -0
- package/lib/kernel/index.js +3 -0
- package/lib/kernel/index.js.map +1 -0
- package/lib/libraries/.gitkeep +0 -0
- package/lib/libraries/ai/CHANGELOG.md +17 -0
- package/lib/libraries/ai/README.md +164 -0
- package/lib/libraries/ai/adapters/AnthropicAdapter.ts +382 -0
- package/lib/libraries/ai/adapters/LLMProvider.ts +76 -0
- package/lib/libraries/ai/adapters/OpenAIAdapter.ts +466 -0
- package/lib/libraries/ai/experimental/index.ts +20 -0
- package/lib/libraries/ai/index.ts +128 -0
- package/lib/libraries/ai/library.json +19 -0
- package/lib/libraries/ai/loop/agentLoop.ts +377 -0
- package/lib/libraries/ai/prompts/definePrompt.ts +0 -0
- package/lib/libraries/ai/rag/retrieveAndAnswer.ts +177 -0
- package/lib/libraries/ai/streaming/streamLLM.ts +94 -0
- package/lib/libraries/ai/structured/completeStructured.ts +143 -0
- package/lib/libraries/ai/tokens/Tokenizer.ts +216 -0
- package/lib/libraries/ai/tools/defineTool.ts +208 -0
- package/lib/libraries/ai/types.ts +260 -0
- package/lib/libraries/chunking/ChunkingService.ts +103 -0
- package/lib/libraries/chunking/README.md +104 -0
- package/lib/libraries/chunking/docs/api-reference.md +549 -0
- package/lib/libraries/chunking/docs/best-practices.md +321 -0
- package/lib/libraries/chunking/docs/code-organization.md +538 -0
- package/lib/libraries/chunking/docs/configuration.md +418 -0
- package/lib/libraries/chunking/docs/index.md +236 -0
- package/lib/libraries/chunking/docs/quick-start.md +298 -0
- package/lib/libraries/chunking/docs/strategies.md +407 -0
- package/lib/libraries/chunking/docs/summary.md +258 -0
- package/lib/libraries/chunking/docs/troubleshooting.md +527 -0
- package/lib/libraries/chunking/index.ts +17 -0
- package/lib/libraries/chunking/library.json +16 -0
- package/lib/libraries/chunking/strategies/ChunkingStrategy.ts +13 -0
- package/lib/libraries/chunking/strategies/FixedLengthChunkingStrategy.ts +88 -0
- package/lib/libraries/chunking/strategies/SemanticChunkingStrategy.ts +389 -0
- package/lib/libraries/chunking/strategies/SlidingWindowChunkingStrategy.ts +258 -0
- package/lib/libraries/chunking/types/index.ts +63 -0
- package/lib/libraries/email/EmailService.ts +591 -0
- package/lib/libraries/email/README.md +777 -0
- package/lib/libraries/email/TemplateRegistry.ts +148 -0
- package/lib/libraries/email/TemplateRenderer.ts +273 -0
- package/lib/libraries/email/index.ts +4 -0
- package/lib/libraries/email/initializeEmailService.ts +60 -0
- package/lib/libraries/email/library.json +12 -0
- package/lib/libraries/email/types/EmailAddress.ts +4 -0
- package/lib/libraries/email/types/EmailAttachment.ts +11 -0
- package/lib/libraries/email/types/EmailTag.ts +9 -0
- package/lib/libraries/email/types/EmailTemplate.ts +124 -0
- package/lib/libraries/email/types/SendBatchEmailsOptions.ts +9 -0
- package/lib/libraries/email/types/SendBatchEmailsResult.ts +9 -0
- package/lib/libraries/email/types/SendEmailOptions.ts +33 -0
- package/lib/libraries/email/types/SendEmailResult.ts +9 -0
- package/lib/libraries/email/types/index.ts +8 -0
- package/lib/libraries/weaviate/QueryBuilder.ts +292 -0
- package/lib/libraries/weaviate/README.md +284 -0
- package/lib/libraries/weaviate/Weaviate.ts +1419 -0
- package/lib/libraries/weaviate/WeaviateConfig.ts +268 -0
- package/lib/libraries/weaviate/docs/.gitkeep +1 -0
- package/lib/libraries/weaviate/docs/API_REFERENCE.md +1067 -0
- package/lib/libraries/weaviate/docs/CONFIGURATION.md +320 -0
- package/lib/libraries/weaviate/docs/ERROR_HANDLING.md +271 -0
- package/lib/libraries/weaviate/docs/MULTI_TENANCY.md +348 -0
- package/lib/libraries/weaviate/docs/PERFORMANCE.md +602 -0
- package/lib/libraries/weaviate/docs/PLUGIN_DEVELOPMENT.md +547 -0
- package/lib/libraries/weaviate/docs/QUICK_START.md +443 -0
- package/lib/libraries/weaviate/docs/README.md +269 -0
- package/lib/libraries/weaviate/docs/SCHEMA_GUIDE.md +630 -0
- package/lib/libraries/weaviate/docs/WEAVIATE_README.md +520 -0
- package/lib/libraries/weaviate/errors/WeaviateError.ts +92 -0
- package/lib/libraries/weaviate/errors/index.ts +1 -0
- package/lib/libraries/weaviate/index.ts +35 -0
- package/lib/libraries/weaviate/library.json +26 -0
- package/lib/libraries/weaviate/plugins/index.ts +2 -0
- package/lib/libraries/weaviate/schemas/SchemaRegistry.ts +284 -0
- package/lib/libraries/weaviate/schemas/index.ts +2 -0
- package/lib/libraries/weaviate/types/BM25SearchOptions.ts +9 -0
- package/lib/libraries/weaviate/types/ExtendedWeaviateClient.ts +7 -0
- package/lib/libraries/weaviate/types/HybridSearchOptions.ts +11 -0
- package/lib/libraries/weaviate/types/MultiTenancy.ts +81 -0
- package/lib/libraries/weaviate/types/Plugin.ts +17 -0
- package/lib/libraries/weaviate/types/SchemaConfig.ts +25 -0
- package/lib/libraries/weaviate/types/SearchMethod.ts +8 -0
- package/lib/libraries/weaviate/types/SearchOptions.ts +16 -0
- package/lib/libraries/weaviate/types/SearchRequest.ts +19 -0
- package/lib/libraries/weaviate/types/SearchResult.ts +16 -0
- package/lib/libraries/weaviate/types/SearchableField.ts +87 -0
- package/lib/libraries/weaviate/types/VectorIndexConfig.ts +19 -0
- package/lib/libraries/weaviate/types/VectorSearchOptions.ts +18 -0
- package/lib/libraries/weaviate/types/VectorizerConfig.ts +8 -0
- package/lib/libraries/weaviate/types/index.ts +29 -0
- package/lib/libraries/weaviate/utils/TenantContextManager.ts +94 -0
- package/lib/modules/accounts/index.ts +47 -0
- package/lib/modules/accounts/module.json +15 -0
- package/lib/modules/accounts/permissions.ts +33 -0
- package/lib/modules/accounts/routes.ts +200 -0
- package/lib/modules/accounts/schema.ts +219 -0
- package/lib/modules/accounts/services/AccountService.ts +44 -0
- package/lib/modules/accounts/validation/schemas.ts +70 -0
- package/lib/modules/oauth/adapters/GmailOAuthAdapter.ts +35 -0
- package/lib/modules/oauth/adapters/GoogleOAuthAdapter.ts +278 -0
- package/lib/modules/oauth/adapters/MicrosoftOAuthAdapter.ts +269 -0
- package/lib/modules/oauth/adapters/MockOAuthAdapter.ts +138 -0
- package/lib/modules/oauth/adapters/OAuthAdapter.ts +211 -0
- package/lib/modules/oauth/adapters/OAuthAdapterRegistry.ts +77 -0
- package/lib/modules/oauth/adapters/OutlookOAuthAdapter.ts +38 -0
- package/lib/modules/oauth/index.ts +79 -0
- package/lib/modules/oauth/module.json +23 -0
- package/lib/modules/oauth/permissions.ts +39 -0
- package/lib/modules/oauth/routes.ts +497 -0
- package/lib/modules/oauth/schema.ts +127 -0
- package/lib/modules/oauth/services/OAuthConnectionService.ts +147 -0
- package/lib/modules/oauth/state.ts +234 -0
- package/lib/modules/oauth/stateJtiCache.ts +85 -0
- package/lib/modules/oauth/verifyIdToken.ts +178 -0
- package/lib/modules/outbox/EventEmitter.ts +106 -0
- package/lib/modules/outbox/OutboxDrainer.ts +163 -0
- package/lib/modules/outbox/handlers/EventHandler.ts +115 -0
- package/lib/modules/outbox/index.ts +43 -0
- package/lib/modules/outbox/module.json +15 -0
- package/lib/modules/outbox/permissions.ts +36 -0
- package/lib/modules/outbox/routes.ts +219 -0
- package/lib/modules/outbox/schema.ts +207 -0
- package/lib/modules/outbox/services/OutboxEventService.ts +223 -0
- package/lib/observability/logger.d.ts +30 -0
- package/lib/observability/logger.d.ts.map +1 -0
- package/lib/observability/logger.js +110 -0
- package/lib/observability/logger.js.map +1 -0
- package/lib/observability/metrics.d.ts +3 -0
- package/lib/observability/metrics.d.ts.map +1 -0
- package/lib/observability/metrics.js +3 -0
- package/lib/observability/metrics.js.map +1 -0
- package/lib/observability/otel.d.ts +3 -0
- package/lib/observability/otel.d.ts.map +1 -0
- package/lib/observability/otel.js +3 -0
- package/lib/observability/otel.js.map +1 -0
- package/lib/observability/safeErrorFields.d.ts +14 -0
- package/lib/observability/safeErrorFields.d.ts.map +1 -0
- package/lib/observability/safeErrorFields.js +14 -0
- package/lib/observability/safeErrorFields.js.map +1 -0
- package/lib/observability/tracing.d.ts +3 -0
- package/lib/observability/tracing.d.ts.map +1 -0
- package/lib/observability/tracing.js +3 -0
- package/lib/observability/tracing.js.map +1 -0
- package/lib/package.json +4 -0
- package/lib/testing.d.ts +3 -0
- package/lib/testing.d.ts.map +1 -0
- package/lib/testing.js +3 -0
- package/lib/testing.js.map +1 -0
- package/package.json +193 -3
- package/templates/default/.claude/agents/qa-brief.md +106 -0
- package/templates/default/.claude/commands/sherpa-brief.md +23 -0
- package/templates/default/.cursor/rules/api.mdc +80 -0
- package/templates/default/.cursor/rules/commits.mdc +88 -0
- package/templates/default/.cursor/rules/security.mdc +92 -0
- package/templates/default/.cursor/rules/testing.mdc +123 -0
- package/templates/default/.cursor/rules/typescript.mdc +86 -0
- package/templates/default/.env.example +79 -0
- package/templates/default/.github/workflows/sherpa-brief.yml +180 -0
- package/templates/default/AGENTS.md +166 -0
- package/templates/default/CLAUDE.md +17 -0
- package/templates/default/README.md +97 -0
- package/templates/default/_gitignore +27 -0
- package/templates/default/docker-compose.yml +83 -0
- package/templates/default/drizzle.config.ts +34 -0
- package/templates/default/eslint.config.mjs +106 -0
- package/templates/default/package.json +57 -0
- package/templates/default/ship-api.config.ts +21 -0
- package/templates/default/src/client.ts +34 -0
- package/templates/default/src/config/modules.ts +23 -0
- package/templates/default/src/db/schema.ts +26 -0
- package/templates/default/src/environment.ts +81 -0
- package/templates/default/src/index.test.ts +53 -0
- package/templates/default/src/index.ts +11 -0
- package/templates/default/src/instrumentation.ts +13 -0
- package/templates/default/src/server.ts +90 -0
- package/templates/default/tsconfig.json +24 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AuthenticatedAccount,
|
|
3
|
+
AuthProvider,
|
|
4
|
+
} from "@sixthsummit/ship-api/app/auth/AuthProvider";
|
|
5
|
+
import type { AppEnv } from "@sixthsummit/ship-api/http/app/createApp";
|
|
6
|
+
import { createModuleApp } from "@sixthsummit/ship-api/http/app/createApp";
|
|
7
|
+
import { NotFoundError } from "@sixthsummit/ship-api/http/errors/NotFoundError";
|
|
8
|
+
import { requireAuth } from "@sixthsummit/ship-api/http/middleware/requireAuth";
|
|
9
|
+
import { requirePermission } from "@sixthsummit/ship-api/http/middleware/requirePermission";
|
|
10
|
+
import { validate } from "@sixthsummit/ship-api/http/utils/validate";
|
|
11
|
+
import type { Hono, Schema } from "hono";
|
|
12
|
+
import type { BlankSchema } from "hono/types";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
import type { OutboxDrainer } from "./OutboxDrainer.js";
|
|
16
|
+
import { OUTBOX_PERMISSIONS } from "./permissions.js";
|
|
17
|
+
import type { OutboxEvent } from "./schema.js";
|
|
18
|
+
import type { OutboxEventService } from "./services/OutboxEventService.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* v4 outbox routes — `defineOutboxRoutes(app, deps)`.
|
|
22
|
+
*
|
|
23
|
+
* Wires:
|
|
24
|
+
*
|
|
25
|
+
* GET /outbox list events (filterable)
|
|
26
|
+
* GET /outbox/stats per-status counts
|
|
27
|
+
* GET /outbox/count total count
|
|
28
|
+
* GET /outbox/:id single event
|
|
29
|
+
* POST /outbox/drain admin: trigger a drain pass
|
|
30
|
+
* POST /outbox/recover admin: reset stale processing
|
|
31
|
+
*
|
|
32
|
+
* Drain + recover are POST (mutating actions), gated by the admin
|
|
33
|
+
* `outbox:drain` / `outbox:recover` permissions. Drain returns the
|
|
34
|
+
* structured per-pass result so the operator sees what just
|
|
35
|
+
* happened. Read-only endpoints sit behind `outbox:read`.
|
|
36
|
+
*
|
|
37
|
+
* Drain by default does *one pass*. Pass `?untilEmpty=true` to flush
|
|
38
|
+
* the entire queue (catch-up after an outage). `batchSize` is also
|
|
39
|
+
* tunable via query param.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
export interface OutboxRoutesDeps<TAccount extends AuthenticatedAccount = AuthenticatedAccount> {
|
|
43
|
+
service: OutboxEventService;
|
|
44
|
+
drainer: OutboxDrainer;
|
|
45
|
+
provider: AuthProvider<TAccount>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const idParam = z.object({
|
|
49
|
+
id: z.string().uuid(),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const listQuery = z
|
|
53
|
+
.object({
|
|
54
|
+
search: z.string().min(1).optional(),
|
|
55
|
+
eventType: z.string().min(1).optional(),
|
|
56
|
+
status: z.enum(["pending", "processing", "published", "failed"]).optional(),
|
|
57
|
+
page: z.coerce.number().int().positive().default(1),
|
|
58
|
+
perPage: z.coerce.number().int().positive().max(200).default(50),
|
|
59
|
+
})
|
|
60
|
+
.strict();
|
|
61
|
+
|
|
62
|
+
const drainBody = z
|
|
63
|
+
.object({
|
|
64
|
+
batchSize: z.number().int().positive().max(500).optional(),
|
|
65
|
+
untilEmpty: z.boolean().optional(),
|
|
66
|
+
})
|
|
67
|
+
.strict();
|
|
68
|
+
|
|
69
|
+
const recoverBody = z
|
|
70
|
+
.object({
|
|
71
|
+
/** Threshold in ms; rows in 'processing' older than this get reset. */
|
|
72
|
+
staleThresholdMs: z.number().int().positive().optional(),
|
|
73
|
+
})
|
|
74
|
+
.strict();
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* ⚠️ FOOT-GUN: do NOT thread one shared `app` through several modules'
|
|
78
|
+
* `defineXxxRoutes` calls — it accumulates one giant Hono route-type and
|
|
79
|
+
* detonates `tsc` (TS2589) at scale. Prefer {@link buildOutboxApp} mounted via
|
|
80
|
+
* `root.route("/", buildOutboxApp(deps))`. This raw form is kept for advanced
|
|
81
|
+
* composition.
|
|
82
|
+
*/
|
|
83
|
+
// Generic over Hono's schema param `S` so an already-chained app keeps its
|
|
84
|
+
// previously registered route types — `Hono<AppEnv>` here would widen them
|
|
85
|
+
// away. See defineAccountsRoutes for the full rationale.
|
|
86
|
+
export function defineOutboxRoutes<
|
|
87
|
+
TAccount extends AuthenticatedAccount = AuthenticatedAccount,
|
|
88
|
+
S extends Schema = BlankSchema,
|
|
89
|
+
>(app: Hono<AppEnv, S>, deps: OutboxRoutesDeps<TAccount>) {
|
|
90
|
+
const auth = requireAuth({ provider: deps.provider });
|
|
91
|
+
|
|
92
|
+
return app
|
|
93
|
+
.get(
|
|
94
|
+
"/outbox",
|
|
95
|
+
auth,
|
|
96
|
+
requirePermission(OUTBOX_PERMISSIONS.outboxRead),
|
|
97
|
+
validate("query", listQuery),
|
|
98
|
+
async (c) => {
|
|
99
|
+
const q = c.req.valid("query");
|
|
100
|
+
const offset = (q.page - 1) * q.perPage;
|
|
101
|
+
const where: Record<string, unknown> = {};
|
|
102
|
+
if (q.eventType) where.eventType = q.eventType;
|
|
103
|
+
if (q.status) where.status = q.status;
|
|
104
|
+
const result = await deps.service.list({
|
|
105
|
+
search: q.search,
|
|
106
|
+
where: Object.keys(where).length > 0 ? where : undefined,
|
|
107
|
+
limit: q.perPage,
|
|
108
|
+
offset,
|
|
109
|
+
});
|
|
110
|
+
const sanitized = (result.rows as OutboxEvent[]).map(summarizeEvent);
|
|
111
|
+
return c.json(
|
|
112
|
+
{
|
|
113
|
+
rows: sanitized,
|
|
114
|
+
total: result.total,
|
|
115
|
+
page: q.page,
|
|
116
|
+
perPage: q.perPage,
|
|
117
|
+
},
|
|
118
|
+
200,
|
|
119
|
+
);
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
.get("/outbox/stats", auth, requirePermission(OUTBOX_PERMISSIONS.outboxRead), async (c) => {
|
|
123
|
+
const stats = await deps.service.getStatistics();
|
|
124
|
+
return c.json(stats, 200);
|
|
125
|
+
})
|
|
126
|
+
.get(
|
|
127
|
+
"/outbox/count",
|
|
128
|
+
auth,
|
|
129
|
+
requirePermission(OUTBOX_PERMISSIONS.outboxRead),
|
|
130
|
+
validate("query", listQuery),
|
|
131
|
+
async (c) => {
|
|
132
|
+
const q = c.req.valid("query");
|
|
133
|
+
const where: Record<string, unknown> = {};
|
|
134
|
+
if (q.eventType) where.eventType = q.eventType;
|
|
135
|
+
if (q.status) where.status = q.status;
|
|
136
|
+
const count = await deps.service.count({
|
|
137
|
+
where: Object.keys(where).length > 0 ? where : undefined,
|
|
138
|
+
});
|
|
139
|
+
return c.json({ count }, 200);
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
.get(
|
|
143
|
+
"/outbox/:id",
|
|
144
|
+
auth,
|
|
145
|
+
requirePermission(OUTBOX_PERMISSIONS.outboxRead),
|
|
146
|
+
validate("param", idParam),
|
|
147
|
+
async (c) => {
|
|
148
|
+
const { id } = c.req.valid("param");
|
|
149
|
+
const event = (await deps.service.get(id)) as OutboxEvent | null;
|
|
150
|
+
if (!event) throw new NotFoundError("Outbox event not found");
|
|
151
|
+
return c.json(summarizeEvent(event), 200);
|
|
152
|
+
},
|
|
153
|
+
)
|
|
154
|
+
.post(
|
|
155
|
+
"/outbox/drain",
|
|
156
|
+
auth,
|
|
157
|
+
requirePermission(OUTBOX_PERMISSIONS.outboxDrain),
|
|
158
|
+
validate("json", drainBody),
|
|
159
|
+
async (c) => {
|
|
160
|
+
const body = c.req.valid("json");
|
|
161
|
+
const result = body.untilEmpty
|
|
162
|
+
? await deps.drainer.runUntilEmpty({ batchSize: body.batchSize })
|
|
163
|
+
: await deps.drainer.runOnce({ batchSize: body.batchSize });
|
|
164
|
+
return c.json(result, 200);
|
|
165
|
+
},
|
|
166
|
+
)
|
|
167
|
+
.post(
|
|
168
|
+
"/outbox/recover",
|
|
169
|
+
auth,
|
|
170
|
+
requirePermission(OUTBOX_PERMISSIONS.outboxRecover),
|
|
171
|
+
validate("json", recoverBody),
|
|
172
|
+
async (c) => {
|
|
173
|
+
const body = c.req.valid("json");
|
|
174
|
+
const result = await deps.service.recoverStaleProcessing(body.staleThresholdMs);
|
|
175
|
+
return c.json(result, 200);
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Build the outbox module as its own sub-app, ready to mount on the root with
|
|
182
|
+
* `root.route("/", buildOutboxApp(deps))`. Canonical wiring — see
|
|
183
|
+
* {@link buildAccountsApp} for the rationale. Routes are tagged under the
|
|
184
|
+
* `outbox` module in `/dev/routes` / `list_routes`.
|
|
185
|
+
*/
|
|
186
|
+
export function buildOutboxApp<TAccount extends AuthenticatedAccount = AuthenticatedAccount>(
|
|
187
|
+
deps: OutboxRoutesDeps<TAccount>,
|
|
188
|
+
) {
|
|
189
|
+
return defineOutboxRoutes(createModuleApp("outbox"), deps);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Strip the heavy `payload` from list-view responses so admin UIs
|
|
194
|
+
* don't transfer megabytes of event bodies just to render a status
|
|
195
|
+
* dashboard. Single-event endpoint returns the full row including
|
|
196
|
+
* payload.
|
|
197
|
+
*/
|
|
198
|
+
function summarizeEvent(event: OutboxEvent) {
|
|
199
|
+
return {
|
|
200
|
+
id: event.id,
|
|
201
|
+
eventId: event.eventId,
|
|
202
|
+
eventType: event.eventType,
|
|
203
|
+
eventVersion: event.eventVersion,
|
|
204
|
+
aggregateType: event.aggregateType,
|
|
205
|
+
aggregateId: event.aggregateId,
|
|
206
|
+
ownerUserId: event.ownerUserId,
|
|
207
|
+
tenantId: event.tenantId,
|
|
208
|
+
correlationId: event.correlationId,
|
|
209
|
+
status: event.status,
|
|
210
|
+
publishAttempts: event.publishAttempts,
|
|
211
|
+
nextAttemptAt: event.nextAttemptAt,
|
|
212
|
+
publishedAt: event.publishedAt,
|
|
213
|
+
lastError: event.lastError,
|
|
214
|
+
occurredAt: event.occurredAt,
|
|
215
|
+
createdAt: event.createdAt,
|
|
216
|
+
updatedAt: event.updatedAt,
|
|
217
|
+
payload: event.payload,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { baseFields } from "@sixthsummit/ship-api/app/db/baseFields";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
import {
|
|
4
|
+
index,
|
|
5
|
+
integer,
|
|
6
|
+
jsonb,
|
|
7
|
+
pgEnum,
|
|
8
|
+
pgTable,
|
|
9
|
+
text,
|
|
10
|
+
timestamp,
|
|
11
|
+
uuid,
|
|
12
|
+
varchar,
|
|
13
|
+
} from "drizzle-orm/pg-core";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* v4 transactional outbox table — ports v3's `OutboxEvent` TypeORM
|
|
17
|
+
* entity. Implements the outbox pattern: domain operations write
|
|
18
|
+
* events to this table inside the same transaction as the business
|
|
19
|
+
* data; a separate worker drains pending rows and publishes to
|
|
20
|
+
* downstream systems (queue, webhook, log, etc.) with at-least-once
|
|
21
|
+
* delivery and exponential backoff on failure.
|
|
22
|
+
*
|
|
23
|
+
* Key v4 differences from v3:
|
|
24
|
+
*
|
|
25
|
+
* - `id` switches from `bigint identity` to `uuid` for consistency
|
|
26
|
+
* with the rest of the v4 framework. FIFO ordering uses the
|
|
27
|
+
* `(created_at, event_id)` index instead of monotonic bigint
|
|
28
|
+
* incrementing.
|
|
29
|
+
*
|
|
30
|
+
* - `status` becomes a Postgres `pgEnum` instead of a raw text
|
|
31
|
+
* column. Type-checked at the SQL boundary; cheaper indexes than
|
|
32
|
+
* text comparison.
|
|
33
|
+
*
|
|
34
|
+
* - Partial indexes preserved for the hot drain queries — the
|
|
35
|
+
* `pending` index covers only rows that haven't been published,
|
|
36
|
+
* and the `processing` index covers only in-flight rows. Both
|
|
37
|
+
* are tiny relative to the full table and stay fast as the
|
|
38
|
+
* published-events table grows.
|
|
39
|
+
*
|
|
40
|
+
* - Audit columns (`createdAt` / `updatedAt` / `deletedAt` /
|
|
41
|
+
* `createdBy` / `updatedBy`) standardized via `baseFields`. v3
|
|
42
|
+
* had createdAt + updatedAt only; v4 uniformity is worth the
|
|
43
|
+
* extra (nullable) columns.
|
|
44
|
+
*
|
|
45
|
+
* The v3 `Job` entity + JobController + job-queue subsystem are
|
|
46
|
+
* intentionally NOT ported. v4's BullMQ machinery (`defineJob` +
|
|
47
|
+
* `JobRegistry` from alpha-2 step 12) is the canonical job substrate;
|
|
48
|
+
* porting v3's competing TypeORM-backed queue would create two
|
|
49
|
+
* conflicting source-of-truth queues. Migration guide: move each
|
|
50
|
+
* v3 Job processor to a `defineJob({ queue, name, processor })` call.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
export const outboxEventStatus = pgEnum("outbox_event_status", [
|
|
54
|
+
"pending",
|
|
55
|
+
"processing",
|
|
56
|
+
"published",
|
|
57
|
+
"failed",
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
export const outboxEvents = pgTable(
|
|
61
|
+
"outbox_events",
|
|
62
|
+
{
|
|
63
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* External identifier for the event — the value downstream
|
|
67
|
+
* consumers see. Distinct from `id` to allow re-publishing the
|
|
68
|
+
* same logical event under a new row when a permanent failure
|
|
69
|
+
* gets manually resolved.
|
|
70
|
+
*/
|
|
71
|
+
eventId: uuid("event_id").notNull().defaultRandom(),
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Domain event type ("account.created", "post.published", ...).
|
|
75
|
+
* Matches the consumer's `EventType` discriminated union.
|
|
76
|
+
*/
|
|
77
|
+
eventType: text("event_type").notNull(),
|
|
78
|
+
|
|
79
|
+
/** Schema version for the payload. Bump when the payload shape changes. */
|
|
80
|
+
eventVersion: integer("event_version").notNull().default(1),
|
|
81
|
+
|
|
82
|
+
/** When the domain operation occurred (may differ from `createdAt`). */
|
|
83
|
+
occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull().default(sql`now()`),
|
|
84
|
+
|
|
85
|
+
/** Aggregate type (entity-class identifier) the event belongs to. */
|
|
86
|
+
aggregateType: text("aggregate_type"),
|
|
87
|
+
|
|
88
|
+
/** Aggregate id within `aggregateType`. UUID-shaped string for v4. */
|
|
89
|
+
aggregateId: uuid("aggregate_id"),
|
|
90
|
+
|
|
91
|
+
/** Owner of the aggregate (typically `accounts.id`). */
|
|
92
|
+
ownerUserId: uuid("owner_user_id"),
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Multi-tenant scoping (A2-1: `uuid` to match `RequestContext.tenantId` and
|
|
96
|
+
* every other v4 id). Nullable — the outbox also carries system/global
|
|
97
|
+
* events with no tenant. No FK: the outbox module doesn't own a `tenants`
|
|
98
|
+
* table, and system events legitimately have a null tenant.
|
|
99
|
+
*/
|
|
100
|
+
tenantId: uuid("tenant_id"),
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Stable key for upstream-deduplication. Set by the producer when
|
|
104
|
+
* the same logical event might be enqueued twice (idempotency
|
|
105
|
+
* boundary).
|
|
106
|
+
*/
|
|
107
|
+
dedupeKey: text("dedupe_key"),
|
|
108
|
+
|
|
109
|
+
/** Trace correlation id — flows through to downstream telemetry. */
|
|
110
|
+
correlationId: varchar("correlation_id", { length: 255 }),
|
|
111
|
+
|
|
112
|
+
/** Event payload. Consumer-shaped JSON. */
|
|
113
|
+
payload: jsonb("payload").$type<Record<string, unknown>>().notNull(),
|
|
114
|
+
|
|
115
|
+
/** Lifecycle state — see the `outboxEventStatus` enum. */
|
|
116
|
+
status: outboxEventStatus("status").notNull().default("pending"),
|
|
117
|
+
|
|
118
|
+
/** Number of publish attempts that have been made (incl. failed). */
|
|
119
|
+
publishAttempts: integer("publish_attempts").notNull().default(0),
|
|
120
|
+
|
|
121
|
+
/** When the next retry should fire. Null when not scheduled. */
|
|
122
|
+
nextAttemptAt: timestamp("next_attempt_at", { withTimezone: true }),
|
|
123
|
+
|
|
124
|
+
/** When the publish succeeded. Null until then. */
|
|
125
|
+
publishedAt: timestamp("published_at", { withTimezone: true }),
|
|
126
|
+
|
|
127
|
+
/** Last failure message (truncated to a reasonable length by callers). */
|
|
128
|
+
lastError: text("last_error"),
|
|
129
|
+
|
|
130
|
+
/** Maximum number of attempts before giving up and marking failed. */
|
|
131
|
+
maxRetries: integer("max_retries").notNull().default(10),
|
|
132
|
+
|
|
133
|
+
/** When the most recent attempt started. */
|
|
134
|
+
startedAt: timestamp("started_at", { withTimezone: true }),
|
|
135
|
+
|
|
136
|
+
...baseFields,
|
|
137
|
+
},
|
|
138
|
+
(table) => [
|
|
139
|
+
// Hot drain query: rows pending or processing that haven't been
|
|
140
|
+
// published yet, ordered by next-attempt → created. Partial index
|
|
141
|
+
// stays small relative to the full table even after years of
|
|
142
|
+
// published events accumulate.
|
|
143
|
+
index("outbox_events_pending_ix")
|
|
144
|
+
.on(table.nextAttemptAt, table.createdAt)
|
|
145
|
+
.where(sql`status IN ('pending','processing') AND published_at IS NULL`),
|
|
146
|
+
index("outbox_events_type_ix").on(table.eventType, table.createdAt),
|
|
147
|
+
index("outbox_events_owner_ix").on(table.ownerUserId),
|
|
148
|
+
index("outbox_events_status_ix").on(table.status),
|
|
149
|
+
// Stale-processing recovery: only rows in processing state. Tiny
|
|
150
|
+
// index — most events don't get stuck in processing.
|
|
151
|
+
index("outbox_events_processing_ix")
|
|
152
|
+
.on(table.startedAt)
|
|
153
|
+
.where(sql`status = 'processing'`),
|
|
154
|
+
// Aggregate-scoped lookups (e.g., "all events for this account").
|
|
155
|
+
index("outbox_events_aggregate_ix").on(table.aggregateType, table.aggregateId),
|
|
156
|
+
],
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
export type OutboxEvent = typeof outboxEvents.$inferSelect;
|
|
160
|
+
export type NewOutboxEvent = typeof outboxEvents.$inferInsert;
|
|
161
|
+
export type OutboxEventStatus = (typeof outboxEventStatus.enumValues)[number];
|
|
162
|
+
|
|
163
|
+
// ─── Status helpers (pure functions) ──────────────────────────────────
|
|
164
|
+
//
|
|
165
|
+
// v3 had these as instance methods on the TypeORM entity class. v4
|
|
166
|
+
// rows are plain objects; status logic moves to module-level pure
|
|
167
|
+
// functions the service / drain worker calls on the row.
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* True when a pending event is ready to publish: status is `pending`,
|
|
171
|
+
* no publishedAt set, and (if scheduled) the next-attempt time has
|
|
172
|
+
* passed. The drain query also filters by index — this helper is for
|
|
173
|
+
* service-layer assertions and tests.
|
|
174
|
+
*/
|
|
175
|
+
export function isReadyForPublish(
|
|
176
|
+
event: Pick<OutboxEvent, "status" | "publishedAt" | "nextAttemptAt">,
|
|
177
|
+
now: Date = new Date(),
|
|
178
|
+
): boolean {
|
|
179
|
+
if (event.status !== "pending") return false;
|
|
180
|
+
if (event.publishedAt) return false;
|
|
181
|
+
if (event.nextAttemptAt && event.nextAttemptAt > now) return false;
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function hasExhaustedRetries(
|
|
186
|
+
event: Pick<OutboxEvent, "publishAttempts" | "maxRetries">,
|
|
187
|
+
): boolean {
|
|
188
|
+
return event.publishAttempts >= event.maxRetries;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Compute the next-attempt time using exponential backoff with jitter.
|
|
193
|
+
* `baseMs * 2^(attempts - 1)` capped at `maxMs`. Used by the drain
|
|
194
|
+
* worker when a publish fails and the event is still under the retry
|
|
195
|
+
* budget.
|
|
196
|
+
*/
|
|
197
|
+
export function computeNextAttempt(
|
|
198
|
+
attempts: number,
|
|
199
|
+
baseMs: number = 1_000,
|
|
200
|
+
maxMs: number = 60 * 60 * 1_000,
|
|
201
|
+
): Date {
|
|
202
|
+
const exponential = baseMs * 2 ** Math.max(0, attempts - 1);
|
|
203
|
+
const capped = Math.min(exponential, maxMs);
|
|
204
|
+
// ±20% jitter to avoid thundering-herd on retries.
|
|
205
|
+
const jittered = capped * (0.8 + Math.random() * 0.4);
|
|
206
|
+
return new Date(Date.now() + jittered);
|
|
207
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { DrizzleEntityService } from "@sixthsummit/ship-api/app/services/DrizzleEntityService";
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports -- the drainer needs row-level locking + atomic `sql` status transitions that QueryOptions can't express
|
|
3
|
+
import { and, asc, eq, isNull, lte, or, sql } from "drizzle-orm";
|
|
4
|
+
import {
|
|
5
|
+
computeNextAttempt,
|
|
6
|
+
type OutboxEvent,
|
|
7
|
+
type OutboxEventStatus,
|
|
8
|
+
outboxEvents,
|
|
9
|
+
} from "../schema.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* v4 `OutboxEventService` — extends `DrizzleEntityService` for CRUD
|
|
13
|
+
* + the outbox-specific lifecycle transitions the drain worker needs.
|
|
14
|
+
*
|
|
15
|
+
* Surface inherited from the base:
|
|
16
|
+
* - `get` / `getAll` / `list` / `count` / `create` / `update` /
|
|
17
|
+
* `delete` with soft-delete + audit-column auto-stamping.
|
|
18
|
+
*
|
|
19
|
+
* Domain-specific methods added here:
|
|
20
|
+
*
|
|
21
|
+
* - `findReadyToPublish(limit)` — paginated query of rows where
|
|
22
|
+
* status='pending' AND publishedAt IS NULL AND
|
|
23
|
+
* (nextAttemptAt IS NULL OR nextAttemptAt <= now). FIFO ordered
|
|
24
|
+
* by `(createdAt, id)`. Driven by the drain worker.
|
|
25
|
+
*
|
|
26
|
+
* - `claimForProcessing(ids[])` — atomic status transition from
|
|
27
|
+
* 'pending' to 'processing' for the listed ids, incrementing
|
|
28
|
+
* `publishAttempts` and stamping `startedAt`. Returns only the
|
|
29
|
+
* ids that actually transitioned (compete with concurrent drain
|
|
30
|
+
* workers safely).
|
|
31
|
+
*
|
|
32
|
+
* - `markPublished(id)` — terminal success transition.
|
|
33
|
+
*
|
|
34
|
+
* - `markFailed(id, error)` — terminal failure (no more retries).
|
|
35
|
+
* Used by the drain worker when `hasExhaustedRetries()` is true
|
|
36
|
+
* after a failure.
|
|
37
|
+
*
|
|
38
|
+
* - `markForRetry(id, error, attempts)` — non-terminal failure;
|
|
39
|
+
* reverts status to 'pending', stamps `lastError`, and schedules
|
|
40
|
+
* `nextAttemptAt` via the exponential-backoff helper.
|
|
41
|
+
*
|
|
42
|
+
* - `recoverStaleProcessing(staleThresholdMs)` — admin tooling:
|
|
43
|
+
* finds rows stuck in 'processing' for longer than the threshold
|
|
44
|
+
* (worker died mid-publish) and resets them to 'pending' so the
|
|
45
|
+
* next drain picks them up.
|
|
46
|
+
*
|
|
47
|
+
* The drain orchestration logic itself (loop, batching, error
|
|
48
|
+
* handling, observability) lands in a separate `OutboxDrainer` class
|
|
49
|
+
* in a follow-up commit; the service only owns DB transitions.
|
|
50
|
+
*/
|
|
51
|
+
export class OutboxEventService extends DrizzleEntityService<
|
|
52
|
+
typeof outboxEvents,
|
|
53
|
+
{ outboxEvents: typeof outboxEvents }
|
|
54
|
+
> {
|
|
55
|
+
protected getTable() {
|
|
56
|
+
return outboxEvents;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
protected override getDefaultSearchFields(): readonly string[] {
|
|
60
|
+
return ["eventType", "correlationId"];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Read up to `limit` rows that are ready to publish, ordered FIFO.
|
|
65
|
+
* The pending partial index covers this query.
|
|
66
|
+
*/
|
|
67
|
+
async findReadyToPublish(limit: number = 100, now: Date = new Date()): Promise<OutboxEvent[]> {
|
|
68
|
+
const rows = await this.db
|
|
69
|
+
.select()
|
|
70
|
+
.from(outboxEvents)
|
|
71
|
+
.where(
|
|
72
|
+
and(
|
|
73
|
+
eq(outboxEvents.status, "pending"),
|
|
74
|
+
isNull(outboxEvents.publishedAt),
|
|
75
|
+
or(isNull(outboxEvents.nextAttemptAt), lte(outboxEvents.nextAttemptAt, now)),
|
|
76
|
+
),
|
|
77
|
+
)
|
|
78
|
+
.orderBy(asc(outboxEvents.createdAt), asc(outboxEvents.id))
|
|
79
|
+
.limit(limit);
|
|
80
|
+
return rows as OutboxEvent[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Atomically transition the listed rows from 'pending' to
|
|
85
|
+
* 'processing'. Increments publishAttempts and stamps startedAt.
|
|
86
|
+
* Returns only the ids that actually transitioned — concurrent
|
|
87
|
+
* drain workers compete safely; whichever worker's UPDATE wins gets
|
|
88
|
+
* the row.
|
|
89
|
+
*/
|
|
90
|
+
async claimForProcessing(ids: readonly string[]): Promise<string[]> {
|
|
91
|
+
if (ids.length === 0) return [];
|
|
92
|
+
const now = new Date();
|
|
93
|
+
const rows = await this.db
|
|
94
|
+
.update(outboxEvents)
|
|
95
|
+
.set({
|
|
96
|
+
status: "processing",
|
|
97
|
+
startedAt: now,
|
|
98
|
+
publishAttempts: sql`${outboxEvents.publishAttempts} + 1`,
|
|
99
|
+
updatedAt: now,
|
|
100
|
+
} as never)
|
|
101
|
+
.where(
|
|
102
|
+
and(
|
|
103
|
+
// Inline as one IN clause to avoid one update-per-id round trip.
|
|
104
|
+
sql`${outboxEvents.id} = ANY(ARRAY[${sql.join(
|
|
105
|
+
ids.map((id) => sql`${id}`),
|
|
106
|
+
sql`, `,
|
|
107
|
+
)}]::uuid[])`,
|
|
108
|
+
eq(outboxEvents.status, "pending"),
|
|
109
|
+
),
|
|
110
|
+
)
|
|
111
|
+
.returning({ id: outboxEvents.id as never });
|
|
112
|
+
return (rows as Array<{ id: string }>).map((r) => r.id);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async markPublished(id: string): Promise<OutboxEvent | null> {
|
|
116
|
+
const now = new Date();
|
|
117
|
+
const [row] = await this.db
|
|
118
|
+
.update(outboxEvents)
|
|
119
|
+
.set({
|
|
120
|
+
status: "published",
|
|
121
|
+
publishedAt: now,
|
|
122
|
+
lastError: null,
|
|
123
|
+
nextAttemptAt: null,
|
|
124
|
+
updatedAt: now,
|
|
125
|
+
} as never)
|
|
126
|
+
.where(eq(outboxEvents.id, id))
|
|
127
|
+
.returning();
|
|
128
|
+
return (row as OutboxEvent | undefined) ?? null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async markFailed(id: string, error: string): Promise<OutboxEvent | null> {
|
|
132
|
+
const now = new Date();
|
|
133
|
+
const [row] = await this.db
|
|
134
|
+
.update(outboxEvents)
|
|
135
|
+
.set({
|
|
136
|
+
status: "failed",
|
|
137
|
+
lastError: truncateError(error),
|
|
138
|
+
nextAttemptAt: null,
|
|
139
|
+
updatedAt: now,
|
|
140
|
+
} as never)
|
|
141
|
+
.where(eq(outboxEvents.id, id))
|
|
142
|
+
.returning();
|
|
143
|
+
return (row as OutboxEvent | undefined) ?? null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Non-terminal failure: schedule a retry with exponential backoff
|
|
148
|
+
* and revert status to 'pending' so the next drain picks it up.
|
|
149
|
+
* Caller owns the attempt-counting logic — typically calls
|
|
150
|
+
* `markForRetry` only when `hasExhaustedRetries(event)` is false.
|
|
151
|
+
*/
|
|
152
|
+
async markForRetry(id: string, error: string, attempts: number): Promise<OutboxEvent | null> {
|
|
153
|
+
const now = new Date();
|
|
154
|
+
const nextAt = computeNextAttempt(attempts);
|
|
155
|
+
const [row] = await this.db
|
|
156
|
+
.update(outboxEvents)
|
|
157
|
+
.set({
|
|
158
|
+
status: "pending",
|
|
159
|
+
lastError: truncateError(error),
|
|
160
|
+
nextAttemptAt: nextAt,
|
|
161
|
+
publishedAt: null,
|
|
162
|
+
updatedAt: now,
|
|
163
|
+
} as never)
|
|
164
|
+
.where(eq(outboxEvents.id, id))
|
|
165
|
+
.returning();
|
|
166
|
+
return (row as OutboxEvent | undefined) ?? null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Admin tooling — find rows stuck in 'processing' beyond the
|
|
171
|
+
* threshold and reset them to 'pending' so the next drain picks
|
|
172
|
+
* them up. Returns the count reset (callers report it).
|
|
173
|
+
*/
|
|
174
|
+
async recoverStaleProcessing(
|
|
175
|
+
staleThresholdMs: number = 30 * 60 * 1_000,
|
|
176
|
+
): Promise<{ recovered: number }> {
|
|
177
|
+
const cutoff = new Date(Date.now() - staleThresholdMs);
|
|
178
|
+
const now = new Date();
|
|
179
|
+
const rows = await this.db
|
|
180
|
+
.update(outboxEvents)
|
|
181
|
+
.set({
|
|
182
|
+
status: "pending",
|
|
183
|
+
startedAt: null,
|
|
184
|
+
nextAttemptAt: now,
|
|
185
|
+
updatedAt: now,
|
|
186
|
+
} as never)
|
|
187
|
+
.where(and(eq(outboxEvents.status, "processing"), lte(outboxEvents.startedAt, cutoff)))
|
|
188
|
+
.returning({ id: outboxEvents.id as never });
|
|
189
|
+
return { recovered: (rows as Array<{ id: string }>).length };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Aggregate counts by status — used by the stats endpoint and by
|
|
194
|
+
* monitoring dashboards. Returns 0 for missing buckets so the
|
|
195
|
+
* shape stays stable.
|
|
196
|
+
*/
|
|
197
|
+
async getStatistics(): Promise<Record<OutboxEventStatus, number>> {
|
|
198
|
+
const rows = (await this.db
|
|
199
|
+
.select({
|
|
200
|
+
status: outboxEvents.status,
|
|
201
|
+
count: sql<number>`count(*)::int`,
|
|
202
|
+
})
|
|
203
|
+
.from(outboxEvents)
|
|
204
|
+
.groupBy(outboxEvents.status)) as Array<{
|
|
205
|
+
status: OutboxEventStatus;
|
|
206
|
+
count: number;
|
|
207
|
+
}>;
|
|
208
|
+
const stats: Record<OutboxEventStatus, number> = {
|
|
209
|
+
pending: 0,
|
|
210
|
+
processing: 0,
|
|
211
|
+
published: 0,
|
|
212
|
+
failed: 0,
|
|
213
|
+
};
|
|
214
|
+
for (const row of rows) stats[row.status] = row.count;
|
|
215
|
+
return stats;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const MAX_ERROR_LENGTH = 4096;
|
|
220
|
+
function truncateError(message: string): string {
|
|
221
|
+
if (message.length <= MAX_ERROR_LENGTH) return message;
|
|
222
|
+
return message.slice(0, MAX_ERROR_LENGTH - 3) + "...";
|
|
223
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import pino, { type Logger } from "pino";
|
|
2
|
+
export { getRequestContext, type RequestContext, runWithRequestContext, setRequestContextField, } from "../app/context/RequestContext.js";
|
|
3
|
+
export interface CreateLoggerOptions {
|
|
4
|
+
/** Override log level. Defaults to `LOG_LEVEL` env then `"info"`. */
|
|
5
|
+
level?: pino.Level;
|
|
6
|
+
/**
|
|
7
|
+
* Custom destination (anything pino accepts: a stream, a file path via
|
|
8
|
+
* `pino.destination`, a sonic-boom instance, or any object with a `write`
|
|
9
|
+
* method). Useful for tests.
|
|
10
|
+
*/
|
|
11
|
+
destination?: pino.DestinationStream;
|
|
12
|
+
/**
|
|
13
|
+
* Force pino-pretty mode regardless of env. Set `false` to force ND-JSON
|
|
14
|
+
* in dev (e.g., when running under a log-aggregating supervisor).
|
|
15
|
+
*/
|
|
16
|
+
pretty?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Extra redaction paths to *add* to the framework defaults. Use this for
|
|
19
|
+
* domain-specific secret keys (e.g., third-party webhook signatures).
|
|
20
|
+
*/
|
|
21
|
+
extraRedactPaths?: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
export declare function createLogger(opts?: CreateLoggerOptions): Logger;
|
|
24
|
+
/**
|
|
25
|
+
* Default framework-wide logger. Most callsites should import this and either
|
|
26
|
+
* use it directly or call `logger.child({ module: "<name>" })` for a scoped
|
|
27
|
+
* sub-logger.
|
|
28
|
+
*/
|
|
29
|
+
export declare const logger: Logger;
|
|
30
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/observability/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,EAAE,EAAE,KAAK,MAAM,EAAsB,MAAM,MAAM,CAAC;AAM7D,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,EACnB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,kCAAkC,CAAC;AAmD1C,MAAM,WAAW,mBAAmB;IAClC,qEAAqE;IACrE,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC;IACrC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AA0BD,wBAAgB,YAAY,CAAC,IAAI,GAAE,mBAAwB,GAAG,MAAM,CA0BnE;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,MAAuB,CAAC"}
|