@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,99 @@
|
|
|
1
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
2
|
+
import pg from "pg";
|
|
3
|
+
import { logger } from "../../observability/logger.js";
|
|
4
|
+
import { safeErrorFields } from "../../observability/safeErrorFields.js";
|
|
5
|
+
import { healthCheckRegistry, } from "../health/HealthCheck.js";
|
|
6
|
+
const DEFAULT_DB_CONFIG = {
|
|
7
|
+
max: 20,
|
|
8
|
+
idleTimeoutMillis: 30_000,
|
|
9
|
+
connectionTimeoutMillis: 5_000,
|
|
10
|
+
statementTimeoutMillis: 30_000,
|
|
11
|
+
};
|
|
12
|
+
export function createPool(config) {
|
|
13
|
+
const merged = { ...DEFAULT_DB_CONFIG, ...config };
|
|
14
|
+
const poolConfig = {
|
|
15
|
+
max: merged.max,
|
|
16
|
+
idleTimeoutMillis: merged.idleTimeoutMillis,
|
|
17
|
+
connectionTimeoutMillis: merged.connectionTimeoutMillis,
|
|
18
|
+
application_name: merged.applicationName,
|
|
19
|
+
ssl: merged.ssl,
|
|
20
|
+
};
|
|
21
|
+
if (merged.connectionString) {
|
|
22
|
+
poolConfig.connectionString = merged.connectionString;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
poolConfig.host = merged.host;
|
|
26
|
+
poolConfig.port = merged.port;
|
|
27
|
+
poolConfig.database = merged.database;
|
|
28
|
+
poolConfig.user = merged.user;
|
|
29
|
+
poolConfig.password = merged.password;
|
|
30
|
+
}
|
|
31
|
+
// Apply statement_timeout as a libpq startup option (`-c statement_timeout=…`)
|
|
32
|
+
// so Postgres sets it when each connection opens — no extra query. Doing this
|
|
33
|
+
// via a `pool.on('connect')` query instead trips pg's "client.query() called
|
|
34
|
+
// while the client is already executing a query" deprecation, because the pool
|
|
35
|
+
// hands the freshly-connected client to its first caller concurrently with the
|
|
36
|
+
// setter query. (A bare number is interpreted as milliseconds.)
|
|
37
|
+
if (merged.statementTimeoutMillis > 0) {
|
|
38
|
+
poolConfig.options = `-c statement_timeout=${merged.statementTimeoutMillis}`;
|
|
39
|
+
}
|
|
40
|
+
return handleIdleClientErrors(new pg.Pool(poolConfig));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Keep a broken idle connection from killing the process.
|
|
44
|
+
*
|
|
45
|
+
* `pg` emits `error` on the pool when an idle pooled client's connection fails. A Cloud SQL
|
|
46
|
+
* restart, failover or maintenance window ends every connection with `57P01 terminating
|
|
47
|
+
* connection due to administrator command`, and with no listener Node treats that event as an
|
|
48
|
+
* uncaught exception and exits. The pool has already discarded the broken client and the next
|
|
49
|
+
* checkout opens a fresh connection, so logging is all that is needed. Only the error's code,
|
|
50
|
+
* name and syscall are logged (the same fields `/readyz` logs for a thrown check error), because
|
|
51
|
+
* connection error messages can name the database host or user.
|
|
52
|
+
*
|
|
53
|
+
* `createPool` and `createDb` call this; call it yourself on any pool you build with
|
|
54
|
+
* `new pg.Pool()` (migration scripts, workers). A pool that already has an `error` listener is
|
|
55
|
+
* left alone, so a caller's own handling wins.
|
|
56
|
+
*/
|
|
57
|
+
export function handleIdleClientErrors(pool) {
|
|
58
|
+
if (pool.listenerCount("error") > 0)
|
|
59
|
+
return pool;
|
|
60
|
+
pool.on("error", (error) => {
|
|
61
|
+
logger.warn(safeErrorFields(error), "Idle Postgres connection failed; the pool discarded it");
|
|
62
|
+
});
|
|
63
|
+
return pool;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Readiness check that runs `select 1` on `pool`. The registry measures the
|
|
67
|
+
* latency and enforces the per-check timeout; a failure throws, so the raw
|
|
68
|
+
* error reaches the registry's failure callback (which `/readyz` logs as
|
|
69
|
+
* code/name/syscall only) rather than the response body. This is the
|
|
70
|
+
* recommended database check: a thrown driver error never puts its message in
|
|
71
|
+
* the log, where a hand-written check returning `error: err.message` would.
|
|
72
|
+
*/
|
|
73
|
+
export function dbHealthCheck(pool, opts = {}) {
|
|
74
|
+
return {
|
|
75
|
+
name: opts.name ?? "db.primary",
|
|
76
|
+
async check() {
|
|
77
|
+
const start = performance.now();
|
|
78
|
+
await pool.query("select 1");
|
|
79
|
+
return { ok: true, latencyMs: Math.round(performance.now() - start) };
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build a Drizzle client + pool. The `schema` is the composed schema record
|
|
85
|
+
* (`{ accounts, roles, permissions, ...customTables }`); `db.query.<key>` is
|
|
86
|
+
* typed against it.
|
|
87
|
+
*/
|
|
88
|
+
export function createDb(args) {
|
|
89
|
+
const pool = args.pool ? handleIdleClientErrors(args.pool) : createPool(args.config);
|
|
90
|
+
const db = drizzle(pool, { schema: args.schema, casing: "snake_case" });
|
|
91
|
+
if (args.healthCheck !== false) {
|
|
92
|
+
const opts = args.healthCheck ?? {};
|
|
93
|
+
(opts.registry ?? healthCheckRegistry).add(dbHealthCheck(pool, { name: opts.name }), {
|
|
94
|
+
replaceable: true,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return { pool, db };
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/app/db/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AnyPgColumn } from "drizzle-orm/pg-core";
|
|
2
|
+
/**
|
|
3
|
+
* `tenantScoped(tenants)` — opt-in multi-tenancy column primitive, the sibling
|
|
4
|
+
* of `baseFields`.
|
|
5
|
+
*
|
|
6
|
+
* Tenancy is never a core default. A multi-tenant product spreads this mixin
|
|
7
|
+
* into the domain tables it wants scoped; a single-tenant product simply never
|
|
8
|
+
* uses it. Core ships the *shape* — a non-null `tenant_id` uuid foreign key to a
|
|
9
|
+
* `tenants` root table, `onDelete: "restrict"` so a tenant can't be deleted out
|
|
10
|
+
* from under its rows — but forces nothing: the `tenants` table is
|
|
11
|
+
* consumer-owned, so this is a *factory* that takes it, rather than a static
|
|
12
|
+
* object referencing a table core doesn't have.
|
|
13
|
+
*
|
|
14
|
+
* Conventions (see `docs/v4/concepts/tenancy.md`):
|
|
15
|
+
* - Domain tables FK `tenants`, NOT `accounts` — so a future
|
|
16
|
+
* one-tenant-per-user → membership move (Model A → B) is an
|
|
17
|
+
* identity-tables-only migration.
|
|
18
|
+
* - Read the active tenant from `RequestContext.tenantId` (published by
|
|
19
|
+
* `resolveTenant()`), never from `account.tenantId` directly.
|
|
20
|
+
* - Index `tenant_id` leading on scoped tables — usually
|
|
21
|
+
* `(tenant_id, <natural key>)`.
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { index, pgTable, uuid, varchar } from "drizzle-orm/pg-core";
|
|
27
|
+
* import { baseFields, tenantScoped } from "@sixthsummit/ship-api";
|
|
28
|
+
* import { tenants } from "../accounts/schema.js";
|
|
29
|
+
*
|
|
30
|
+
* export const projects = pgTable(
|
|
31
|
+
* "projects",
|
|
32
|
+
* {
|
|
33
|
+
* id: uuid("id").primaryKey().defaultRandom(),
|
|
34
|
+
* name: varchar("name", { length: 200 }).notNull(),
|
|
35
|
+
* ...tenantScoped(tenants), // adds a non-null tenant_id FK → tenants.id
|
|
36
|
+
* ...baseFields,
|
|
37
|
+
* },
|
|
38
|
+
* (t) => [index("projects_tenant_ix").on(t.tenantId)],
|
|
39
|
+
* );
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Tenant *enforcement* — auto-injecting `WHERE tenant_id = ?` on every query via
|
|
43
|
+
* the `beforeQuery` lifecycle hook + `RequestContext.tenantId` — is deliberately
|
|
44
|
+
* deferred (see `V4_STATUS` V8). This primitive ships only the column shape and
|
|
45
|
+
* the resolution convention; it scopes nothing on its own.
|
|
46
|
+
*/
|
|
47
|
+
export declare function tenantScoped<TTenants extends {
|
|
48
|
+
id: AnyPgColumn;
|
|
49
|
+
}>(tenants: TTenants): {
|
|
50
|
+
readonly tenantId: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgUUIDBuilderInitial<"tenant_id">>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Row-shape contribution of `tenantScoped` (for service-level type
|
|
54
|
+
* constraints), mirroring `BaseFields`.
|
|
55
|
+
*/
|
|
56
|
+
export type TenantScoped = {
|
|
57
|
+
tenantId: string;
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=tenantScoped.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenantScoped.d.ts","sourceRoot":"","sources":["../../../src/app/db/tenantScoped.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,YAAY,CAAC,QAAQ,SAAS;IAAE,EAAE,EAAE,WAAW,CAAA;CAAE,EAAE,OAAO,EAAE,QAAQ;;EAMnF;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { uuid } from "drizzle-orm/pg-core";
|
|
2
|
+
/**
|
|
3
|
+
* `tenantScoped(tenants)` — opt-in multi-tenancy column primitive, the sibling
|
|
4
|
+
* of `baseFields`.
|
|
5
|
+
*
|
|
6
|
+
* Tenancy is never a core default. A multi-tenant product spreads this mixin
|
|
7
|
+
* into the domain tables it wants scoped; a single-tenant product simply never
|
|
8
|
+
* uses it. Core ships the *shape* — a non-null `tenant_id` uuid foreign key to a
|
|
9
|
+
* `tenants` root table, `onDelete: "restrict"` so a tenant can't be deleted out
|
|
10
|
+
* from under its rows — but forces nothing: the `tenants` table is
|
|
11
|
+
* consumer-owned, so this is a *factory* that takes it, rather than a static
|
|
12
|
+
* object referencing a table core doesn't have.
|
|
13
|
+
*
|
|
14
|
+
* Conventions (see `docs/v4/concepts/tenancy.md`):
|
|
15
|
+
* - Domain tables FK `tenants`, NOT `accounts` — so a future
|
|
16
|
+
* one-tenant-per-user → membership move (Model A → B) is an
|
|
17
|
+
* identity-tables-only migration.
|
|
18
|
+
* - Read the active tenant from `RequestContext.tenantId` (published by
|
|
19
|
+
* `resolveTenant()`), never from `account.tenantId` directly.
|
|
20
|
+
* - Index `tenant_id` leading on scoped tables — usually
|
|
21
|
+
* `(tenant_id, <natural key>)`.
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { index, pgTable, uuid, varchar } from "drizzle-orm/pg-core";
|
|
27
|
+
* import { baseFields, tenantScoped } from "@sixthsummit/ship-api";
|
|
28
|
+
* import { tenants } from "../accounts/schema.js";
|
|
29
|
+
*
|
|
30
|
+
* export const projects = pgTable(
|
|
31
|
+
* "projects",
|
|
32
|
+
* {
|
|
33
|
+
* id: uuid("id").primaryKey().defaultRandom(),
|
|
34
|
+
* name: varchar("name", { length: 200 }).notNull(),
|
|
35
|
+
* ...tenantScoped(tenants), // adds a non-null tenant_id FK → tenants.id
|
|
36
|
+
* ...baseFields,
|
|
37
|
+
* },
|
|
38
|
+
* (t) => [index("projects_tenant_ix").on(t.tenantId)],
|
|
39
|
+
* );
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Tenant *enforcement* — auto-injecting `WHERE tenant_id = ?` on every query via
|
|
43
|
+
* the `beforeQuery` lifecycle hook + `RequestContext.tenantId` — is deliberately
|
|
44
|
+
* deferred (see `V4_STATUS` V8). This primitive ships only the column shape and
|
|
45
|
+
* the resolution convention; it scopes nothing on its own.
|
|
46
|
+
*/
|
|
47
|
+
export function tenantScoped(tenants) {
|
|
48
|
+
return {
|
|
49
|
+
tenantId: uuid("tenant_id")
|
|
50
|
+
.notNull()
|
|
51
|
+
.references(() => tenants.id, { onDelete: "restrict" }),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=tenantScoped.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenantScoped.js","sourceRoot":"","sources":["../../../src/app/db/tenantScoped.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,UAAU,YAAY,CAAuC,OAAiB;IAClF,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;aACxB,OAAO,EAAE;aACT,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;KACjD,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { NodePgDatabase, NodePgQueryResultHKT } from "drizzle-orm/node-postgres";
|
|
2
|
+
import type { PgTransaction } from "drizzle-orm/pg-core";
|
|
3
|
+
import type { ExtractTablesWithRelations } from "drizzle-orm/relations";
|
|
4
|
+
/**
|
|
5
|
+
* `withTransaction` — opens a Drizzle transaction with framework value-add.
|
|
6
|
+
*
|
|
7
|
+
* Beyond Drizzle's bare `db.transaction(...)` this wrapper provides:
|
|
8
|
+
*
|
|
9
|
+
* 1. **OTel span** named `db.transaction` so transaction duration shows up in
|
|
10
|
+
* traces with the same correlation IDs as the surrounding request.
|
|
11
|
+
* 2. **Translation of `TransactionRollbackError`** into ShipAPI's
|
|
12
|
+
* `RollbackError` so `catch (Error)` blocks in callers don't accidentally
|
|
13
|
+
* swallow a rollback as a generic application failure. Raw Drizzle
|
|
14
|
+
* rollbacks are easy to misuse; this gives them a typed identity.
|
|
15
|
+
* 3. **Optional retry-on-deadlock** for serialization failures (Postgres SQLSTATE
|
|
16
|
+
* `40001`) and deadlocks (`40P01`). Off by default; opt in via
|
|
17
|
+
* `retryOnConflict: { attempts: 3, backoffMs: 50 }`.
|
|
18
|
+
* 4. **`RequestContext.tx` propagation** — while inside the callback, the
|
|
19
|
+
* canonical request context's `tx` field is set so lifecycle hooks
|
|
20
|
+
* (audit / CDC / multi-tenant) running in nested service calls know
|
|
21
|
+
* they're inside an active transaction without explicit threading.
|
|
22
|
+
*/
|
|
23
|
+
export declare class RollbackError extends Error {
|
|
24
|
+
readonly cause?: unknown;
|
|
25
|
+
constructor(message?: string, cause?: unknown);
|
|
26
|
+
}
|
|
27
|
+
type AnyDb<TSchema extends Record<string, unknown>> = NodePgDatabase<TSchema>;
|
|
28
|
+
export type ShipTx<TSchema extends Record<string, unknown>> = PgTransaction<NodePgQueryResultHKT, TSchema, ExtractTablesWithRelations<TSchema>>;
|
|
29
|
+
export interface WithTransactionOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Retry the transaction on Postgres serialization failures and deadlocks.
|
|
32
|
+
* Defaults to `undefined` (no retry).
|
|
33
|
+
*/
|
|
34
|
+
retryOnConflict?: {
|
|
35
|
+
attempts: number;
|
|
36
|
+
backoffMs: number;
|
|
37
|
+
};
|
|
38
|
+
/** Custom span name override. Defaults to `"db.transaction"`. */
|
|
39
|
+
spanName?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Run `fn` inside a Drizzle transaction. The `tx` argument is the same
|
|
43
|
+
* Drizzle transaction client your service code would receive from `db.transaction(...)` —
|
|
44
|
+
* use it for all writes inside the callback so they share the transaction
|
|
45
|
+
* scope.
|
|
46
|
+
*
|
|
47
|
+
* Throwing from the callback rolls back. Calling `tx.rollback()` also rolls
|
|
48
|
+
* back (translated to `RollbackError`).
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* await withTransaction(db, async (tx) => {
|
|
52
|
+
* await tx.insert(accounts).values(values);
|
|
53
|
+
* await tx.insert(auditLog).values(diff);
|
|
54
|
+
* });
|
|
55
|
+
*/
|
|
56
|
+
export declare function withTransaction<TSchema extends Record<string, unknown>, T>(db: AnyDb<TSchema>, fn: (tx: ShipTx<TSchema>) => Promise<T>, opts?: WithTransactionOptions): Promise<T>;
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../../src/app/db/transaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAIxE;;;;;;;;;;;;;;;;;;GAkBG;AAEH,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBACb,OAAO,SAA4B,EAAE,KAAK,CAAC,EAAE,OAAO;CAKjE;AAED,KAAK,KAAK,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;AAE9E,MAAM,MAAM,MAAM,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,aAAa,CACzE,oBAAoB,EACpB,OAAO,EACP,0BAA0B,CAAC,OAAO,CAAC,CACpC,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiBD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,EAC9E,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,EAClB,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EACvC,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,CAAC,CAAC,CAiDZ"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { TransactionRollbackError } from "drizzle-orm/errors";
|
|
2
|
+
import { withSpan } from "../../observability/tracing.js";
|
|
3
|
+
import { setRequestContextField } from "../context/RequestContext.js";
|
|
4
|
+
/**
|
|
5
|
+
* `withTransaction` — opens a Drizzle transaction with framework value-add.
|
|
6
|
+
*
|
|
7
|
+
* Beyond Drizzle's bare `db.transaction(...)` this wrapper provides:
|
|
8
|
+
*
|
|
9
|
+
* 1. **OTel span** named `db.transaction` so transaction duration shows up in
|
|
10
|
+
* traces with the same correlation IDs as the surrounding request.
|
|
11
|
+
* 2. **Translation of `TransactionRollbackError`** into ShipAPI's
|
|
12
|
+
* `RollbackError` so `catch (Error)` blocks in callers don't accidentally
|
|
13
|
+
* swallow a rollback as a generic application failure. Raw Drizzle
|
|
14
|
+
* rollbacks are easy to misuse; this gives them a typed identity.
|
|
15
|
+
* 3. **Optional retry-on-deadlock** for serialization failures (Postgres SQLSTATE
|
|
16
|
+
* `40001`) and deadlocks (`40P01`). Off by default; opt in via
|
|
17
|
+
* `retryOnConflict: { attempts: 3, backoffMs: 50 }`.
|
|
18
|
+
* 4. **`RequestContext.tx` propagation** — while inside the callback, the
|
|
19
|
+
* canonical request context's `tx` field is set so lifecycle hooks
|
|
20
|
+
* (audit / CDC / multi-tenant) running in nested service calls know
|
|
21
|
+
* they're inside an active transaction without explicit threading.
|
|
22
|
+
*/
|
|
23
|
+
export class RollbackError extends Error {
|
|
24
|
+
cause;
|
|
25
|
+
constructor(message = "Transaction rolled back", cause) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "RollbackError";
|
|
28
|
+
this.cause = cause;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const POSTGRES_RETRYABLE_CODES = new Set([
|
|
32
|
+
"40001", // serialization_failure
|
|
33
|
+
"40P01", // deadlock_detected
|
|
34
|
+
]);
|
|
35
|
+
function isRetryablePgError(err) {
|
|
36
|
+
if (typeof err !== "object" || err === null)
|
|
37
|
+
return false;
|
|
38
|
+
const code = err.code;
|
|
39
|
+
return typeof code === "string" && POSTGRES_RETRYABLE_CODES.has(code);
|
|
40
|
+
}
|
|
41
|
+
function delay(ms) {
|
|
42
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run `fn` inside a Drizzle transaction. The `tx` argument is the same
|
|
46
|
+
* Drizzle transaction client your service code would receive from `db.transaction(...)` —
|
|
47
|
+
* use it for all writes inside the callback so they share the transaction
|
|
48
|
+
* scope.
|
|
49
|
+
*
|
|
50
|
+
* Throwing from the callback rolls back. Calling `tx.rollback()` also rolls
|
|
51
|
+
* back (translated to `RollbackError`).
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* await withTransaction(db, async (tx) => {
|
|
55
|
+
* await tx.insert(accounts).values(values);
|
|
56
|
+
* await tx.insert(auditLog).values(diff);
|
|
57
|
+
* });
|
|
58
|
+
*/
|
|
59
|
+
export async function withTransaction(db, fn, opts = {}) {
|
|
60
|
+
const spanName = opts.spanName ?? "db.transaction";
|
|
61
|
+
const retry = opts.retryOnConflict;
|
|
62
|
+
const maxAttempts = retry?.attempts ?? 1;
|
|
63
|
+
const backoffMs = retry?.backoffMs ?? 0;
|
|
64
|
+
return withSpan(spanName, async (span) => {
|
|
65
|
+
let attempt = 0;
|
|
66
|
+
let lastErr;
|
|
67
|
+
while (attempt < maxAttempts) {
|
|
68
|
+
attempt += 1;
|
|
69
|
+
try {
|
|
70
|
+
return await db.transaction(async (tx) => {
|
|
71
|
+
// Make `tx` visible to lifecycle hooks running in nested service calls.
|
|
72
|
+
setRequestContextField("tx", tx);
|
|
73
|
+
try {
|
|
74
|
+
return await fn(tx);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
setRequestContextField("tx", undefined);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
lastErr = err;
|
|
83
|
+
// Drizzle marks intentional rollbacks via TransactionRollbackError.
|
|
84
|
+
if (err instanceof TransactionRollbackError) {
|
|
85
|
+
const wrapped = new RollbackError("Transaction rolled back via tx.rollback()", err);
|
|
86
|
+
span.setAttribute("db.rollback.kind", "explicit");
|
|
87
|
+
throw wrapped;
|
|
88
|
+
}
|
|
89
|
+
if (attempt < maxAttempts && retry && isRetryablePgError(err)) {
|
|
90
|
+
span.addEvent("db.transaction.retry", {
|
|
91
|
+
attempt,
|
|
92
|
+
"error.code": err.code ?? "unknown",
|
|
93
|
+
});
|
|
94
|
+
if (backoffMs > 0)
|
|
95
|
+
await delay(backoffMs * attempt);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Unreachable in practice — last attempt either returned or threw above.
|
|
102
|
+
/* c8 ignore next */
|
|
103
|
+
throw lastErr;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../src/app/db/transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable health-check primitive.
|
|
3
|
+
*
|
|
4
|
+
* The framework exposes two HTTP endpoints (`/livez` and `/readyz`) backed
|
|
5
|
+
* by a `HealthCheckRegistry`:
|
|
6
|
+
*
|
|
7
|
+
* - `/livez` — process is up. Always 200 with no checks. Used by load
|
|
8
|
+
* balancers / orchestrators to decide "should I restart this pod?"
|
|
9
|
+
* - `/readyz` — runs every registered check. 200 if all pass; 503 with
|
|
10
|
+
* a structured `{ checks: [...] }` body otherwise. Used to decide
|
|
11
|
+
* "should I send traffic to this pod?"
|
|
12
|
+
*
|
|
13
|
+
* `createApp()` mounts both routes by default (see `http/app/health.ts`).
|
|
14
|
+
* Modules / consumer code register checks via `healthCheckRegistry.add(...)`.
|
|
15
|
+
* Built-in checks: `createDb()` registers a `db.primary` check on its pool by
|
|
16
|
+
* default; `redisHealthCheck(provider)` is a factory you add yourself.
|
|
17
|
+
*
|
|
18
|
+
* Duplicate names: the first registration of a name wins and later ones are
|
|
19
|
+
* skipped (logged), except that a check added with `{ replaceable: true }`
|
|
20
|
+
* (what framework defaults such as `createDb`'s `db.primary` use) gives way
|
|
21
|
+
* to a later explicit registration of the same name. So a consumer that
|
|
22
|
+
* registers its own `db.primary` after `createDb()` gets exactly one check:
|
|
23
|
+
* its own.
|
|
24
|
+
*/
|
|
25
|
+
export interface HealthCheckResult {
|
|
26
|
+
ok: boolean;
|
|
27
|
+
/** Latency of the check itself, ms. */
|
|
28
|
+
latencyMs: number;
|
|
29
|
+
/**
|
|
30
|
+
* Free-form error message when ok=false. `/readyz` never sends it, but logs
|
|
31
|
+
* it server-side (truncated), so it must not contain secrets.
|
|
32
|
+
*/
|
|
33
|
+
error?: string;
|
|
34
|
+
/** Adapter-specific extras (versions, replication lag, etc.). */
|
|
35
|
+
details?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
export interface HealthCheck {
|
|
38
|
+
/** Stable name reported in the readyz response (e.g., `"redis"`, `"db.primary"`). */
|
|
39
|
+
readonly name: string;
|
|
40
|
+
/**
|
|
41
|
+
* Run the check. Should return within a few seconds; timeouts are the
|
|
42
|
+
* registry's responsibility (see `runAll`'s `timeoutMs`).
|
|
43
|
+
*/
|
|
44
|
+
check(): Promise<HealthCheckResult> | HealthCheckResult;
|
|
45
|
+
}
|
|
46
|
+
export interface AddHealthCheckOptions {
|
|
47
|
+
/**
|
|
48
|
+
* Mark this check as a default that a later `add()` of the same name may
|
|
49
|
+
* replace. Framework-registered checks (`createDb`'s `db.primary`) use
|
|
50
|
+
* this so a consumer's own check of that name takes over instead of being
|
|
51
|
+
* skipped. Default `false`.
|
|
52
|
+
*/
|
|
53
|
+
replaceable?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/** One failed check, as reported to `RunAllOptions.onCheckFailure`. */
|
|
56
|
+
export interface HealthCheckFailure {
|
|
57
|
+
name: string;
|
|
58
|
+
/** The thrown value, or the `error` string the check returned (may be `undefined`). */
|
|
59
|
+
error: unknown;
|
|
60
|
+
/**
|
|
61
|
+
* The `error` string the check *returned* with `ok: false`. Absent when the
|
|
62
|
+
* check threw, timed out, or returned no string. Unlike a thrown error's
|
|
63
|
+
* message, this text was written by the app author, so `/readyz` logs it.
|
|
64
|
+
*/
|
|
65
|
+
reason?: string;
|
|
66
|
+
/** `true` when the check was cut off by the registry's per-check timeout. */
|
|
67
|
+
timedOut: boolean;
|
|
68
|
+
}
|
|
69
|
+
export interface RunAllOptions {
|
|
70
|
+
/**
|
|
71
|
+
* Per-check timeout in milliseconds. Default 3_000 (3 s). Checks that
|
|
72
|
+
* exceed this are reported as failed with `error: "timeout"`.
|
|
73
|
+
*/
|
|
74
|
+
timeoutMs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Called once per failed check with the raw error, before `runAll`
|
|
77
|
+
* resolves. `/readyz` uses it to log failures server-side while keeping
|
|
78
|
+
* the raw error out of the public response body. Exceptions thrown by the
|
|
79
|
+
* callback are swallowed.
|
|
80
|
+
*/
|
|
81
|
+
onCheckFailure?: (failure: HealthCheckFailure) => void;
|
|
82
|
+
}
|
|
83
|
+
export interface RunAllResult {
|
|
84
|
+
ok: boolean;
|
|
85
|
+
checks: Array<{
|
|
86
|
+
name: string;
|
|
87
|
+
ok: boolean;
|
|
88
|
+
latencyMs: number;
|
|
89
|
+
error?: string;
|
|
90
|
+
details?: Record<string, unknown>;
|
|
91
|
+
}>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Container for registered checks. One framework-wide singleton (below);
|
|
95
|
+
* tests construct their own via `new HealthCheckRegistry()`.
|
|
96
|
+
*/
|
|
97
|
+
export declare class HealthCheckRegistry {
|
|
98
|
+
private checks;
|
|
99
|
+
private replaceable;
|
|
100
|
+
/**
|
|
101
|
+
* Register a check. Returns `true` when the check is now registered,
|
|
102
|
+
* `false` when it was skipped because a check of that name already exists.
|
|
103
|
+
*
|
|
104
|
+
* Duplicate names never throw and never run twice:
|
|
105
|
+
* - existing check is `replaceable` and the new one is not → the new
|
|
106
|
+
* check replaces it (debug log);
|
|
107
|
+
* - otherwise the existing check wins and the new one is skipped (debug
|
|
108
|
+
* log when either side is `replaceable`, warn log when both are
|
|
109
|
+
* explicit registrations, since that is usually a consumer bug).
|
|
110
|
+
*/
|
|
111
|
+
add(check: HealthCheck, opts?: AddHealthCheckOptions): boolean;
|
|
112
|
+
/** Test / admin helper. */
|
|
113
|
+
remove(name: string): boolean;
|
|
114
|
+
list(): readonly HealthCheck[];
|
|
115
|
+
size(): number;
|
|
116
|
+
clear(): void;
|
|
117
|
+
runAll(opts?: RunAllOptions): Promise<RunAllResult>;
|
|
118
|
+
}
|
|
119
|
+
/** Framework-wide registry. Bootstrappers / modules add checks here. */
|
|
120
|
+
export declare const healthCheckRegistry: HealthCheckRegistry;
|
|
121
|
+
//# sourceMappingURL=HealthCheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HealthCheck.d.ts","sourceRoot":"","sources":["../../../src/app/health/HealthCheck.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,qFAAqF;IACrF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,CAAC;CACzD;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,KAAK,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,OAAO,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,CAAC,CAAC;CACJ;AAED;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,WAAW,CAA0B;IAE7C;;;;;;;;;;OAUG;IACH,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO;IA0BlE,2BAA2B;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU7B,IAAI,IAAI,SAAS,WAAW,EAAE;IAI9B,IAAI,IAAI,MAAM;IAId,KAAK,IAAI,IAAI;IAKP,MAAM,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC;CA6D9D;AAED,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}
|