@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,94 @@
|
|
|
1
|
+
import type { TenantContext } from "../types/MultiTenancy.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Utility class for managing tenant context in multi-tenant operations
|
|
5
|
+
*/
|
|
6
|
+
export default class TenantContextManager {
|
|
7
|
+
private static currentContext: TenantContext | null = null;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Set the current tenant context
|
|
11
|
+
*/
|
|
12
|
+
static setContext(tenant: string, activityStatus?: "HOT" | "COLD" | "FROZEN"): void {
|
|
13
|
+
TenantContextManager.currentContext = {
|
|
14
|
+
tenant,
|
|
15
|
+
activityStatus: activityStatus || "HOT",
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get the current tenant context
|
|
21
|
+
*/
|
|
22
|
+
static getContext(): TenantContext | null {
|
|
23
|
+
return TenantContextManager.currentContext;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Clear the current tenant context
|
|
28
|
+
*/
|
|
29
|
+
static clearContext(): void {
|
|
30
|
+
TenantContextManager.currentContext = null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if a tenant context is set
|
|
35
|
+
*/
|
|
36
|
+
static hasContext(): boolean {
|
|
37
|
+
return TenantContextManager.currentContext !== null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the current tenant name
|
|
42
|
+
*/
|
|
43
|
+
static getCurrentTenant(): string | null {
|
|
44
|
+
return TenantContextManager.currentContext?.tenant || null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Execute a function with a specific tenant context
|
|
49
|
+
*/
|
|
50
|
+
static async withContext<T>(
|
|
51
|
+
tenant: string,
|
|
52
|
+
activityStatus: "HOT" | "COLD" | "FROZEN" | undefined,
|
|
53
|
+
fn: () => Promise<T>,
|
|
54
|
+
): Promise<T> {
|
|
55
|
+
const previousContext = TenantContextManager.currentContext;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
TenantContextManager.setContext(tenant, activityStatus);
|
|
59
|
+
return await fn();
|
|
60
|
+
} finally {
|
|
61
|
+
TenantContextManager.currentContext = previousContext;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Create a tenant context object
|
|
67
|
+
*/
|
|
68
|
+
static createContext(tenant: string, activityStatus?: "HOT" | "COLD" | "FROZEN"): TenantContext {
|
|
69
|
+
return {
|
|
70
|
+
tenant,
|
|
71
|
+
activityStatus: activityStatus || "HOT",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Validate tenant name format
|
|
77
|
+
*/
|
|
78
|
+
static validateTenantName(tenant: string): boolean {
|
|
79
|
+
// Weaviate tenant names must be lowercase and contain only alphanumeric characters and hyphens
|
|
80
|
+
return /^[a-z0-9-]+$/.test(tenant) && tenant.length > 0 && tenant.length <= 63;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Sanitize tenant name to meet Weaviate requirements
|
|
85
|
+
*/
|
|
86
|
+
static sanitizeTenantName(tenant: string): string {
|
|
87
|
+
return tenant
|
|
88
|
+
.toLowerCase()
|
|
89
|
+
.replace(/[^a-z0-9-]/g, "-")
|
|
90
|
+
.replace(/-+/g, "-")
|
|
91
|
+
.replace(/^-|-$/g, "")
|
|
92
|
+
.substring(0, 63);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accounts module — public barrel.
|
|
3
|
+
*
|
|
4
|
+
* Default account / role / permission CRUD over the module's own identity
|
|
5
|
+
* tables. Consumers wire it via `defineAccountsRoutes(app, { service, provider })`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
ACCOUNTS_PERMISSION_DEFINITIONS,
|
|
10
|
+
ACCOUNTS_PERMISSIONS,
|
|
11
|
+
type AccountsPermission,
|
|
12
|
+
} from "./permissions.js";
|
|
13
|
+
export { type AccountsRoutesDeps, buildAccountsApp, defineAccountsRoutes } from "./routes.js";
|
|
14
|
+
export {
|
|
15
|
+
type Account,
|
|
16
|
+
accounts,
|
|
17
|
+
accountsRelations,
|
|
18
|
+
accountsSchema,
|
|
19
|
+
type NewAccount,
|
|
20
|
+
type NewPermission,
|
|
21
|
+
type NewRole,
|
|
22
|
+
type NewRolePermission,
|
|
23
|
+
type NewTenant,
|
|
24
|
+
type Permission,
|
|
25
|
+
permissions,
|
|
26
|
+
permissionsRelations,
|
|
27
|
+
type Role,
|
|
28
|
+
type RolePermission,
|
|
29
|
+
rolePermissions,
|
|
30
|
+
rolePermissionsRelations,
|
|
31
|
+
roles,
|
|
32
|
+
rolesRelations,
|
|
33
|
+
type Tenant,
|
|
34
|
+
tenants,
|
|
35
|
+
tenantsSchema,
|
|
36
|
+
} from "./schema.js";
|
|
37
|
+
export { AccountService } from "./services/AccountService.js";
|
|
38
|
+
export {
|
|
39
|
+
type AccountIdParam,
|
|
40
|
+
accountIdParamSchema,
|
|
41
|
+
type CreateAccountInput,
|
|
42
|
+
createAccountSchema,
|
|
43
|
+
type ListAccountsQuery,
|
|
44
|
+
listAccountsQuerySchema,
|
|
45
|
+
type UpdateAccountInput,
|
|
46
|
+
updateAccountSchema,
|
|
47
|
+
} from "./validation/schemas.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "accounts",
|
|
3
|
+
"description": "Identity + RBAC on the v4 substrate — owns the `accounts`/`roles`/`permissions`/`refresh_tokens` schema (relocated out of core), DrizzleEntityService, Hono routes, pluggable AuthProvider. Compose its `accountsSchema` fragment into `createApp({ schema })` and customize as needed.",
|
|
4
|
+
"version": "2.0.0-alpha.1",
|
|
5
|
+
"dependencies": [],
|
|
6
|
+
"npmDependencies": {},
|
|
7
|
+
"requiredEnvVars": [],
|
|
8
|
+
"optionalEnvVars": [],
|
|
9
|
+
"postInstall": [
|
|
10
|
+
"Add the schema to your composed schema: `createApp({ schema: { ...accountsSchema } })`",
|
|
11
|
+
"Wire the routes in src/index.ts, capturing the chained return so hc() types survive: `const app = defineAccountsRoutes(createApp({ schema }), { service, provider })`",
|
|
12
|
+
"Provide a service constructed against your composed schema: `new AccountService(app.db)`",
|
|
13
|
+
"Provide an AuthProvider (Firebase by default; Better-Auth/Clerk/WorkOS in v4.x)"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission slugs for the accounts module.
|
|
3
|
+
*
|
|
4
|
+
* v3 exported `Permission` entity instances; v4 exports plain string
|
|
5
|
+
* constants because authorization is enforced by `requirePermission(slug)`
|
|
6
|
+
* middleware at the route, not by `@HasPermission` decorators on a
|
|
7
|
+
* controller method. The Permission DB rows themselves are seeded by
|
|
8
|
+
* the consuming app (typically in a custom bootstrapper) — the module
|
|
9
|
+
* declares the *names* it expects to exist.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { PermissionDefinition } from "@sixthsummit/ship-api";
|
|
13
|
+
|
|
14
|
+
export const ACCOUNTS_PERMISSIONS = {
|
|
15
|
+
read: "accounts:read",
|
|
16
|
+
create: "accounts:create",
|
|
17
|
+
update: "accounts:update",
|
|
18
|
+
delete: "accounts:delete",
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
export type AccountsPermission = (typeof ACCOUNTS_PERMISSIONS)[keyof typeof ACCOUNTS_PERMISSIONS];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The list form is what a seed script feeds to the Permission table.
|
|
25
|
+
* Each entry pairs the slug with a human-readable label that surfaces
|
|
26
|
+
* in admin UIs when assigning permissions to roles.
|
|
27
|
+
*/
|
|
28
|
+
export const ACCOUNTS_PERMISSION_DEFINITIONS = [
|
|
29
|
+
{ slug: ACCOUNTS_PERMISSIONS.read, label: "View Accounts" },
|
|
30
|
+
{ slug: ACCOUNTS_PERMISSIONS.create, label: "Create Accounts" },
|
|
31
|
+
{ slug: ACCOUNTS_PERMISSIONS.update, label: "Update Accounts" },
|
|
32
|
+
{ slug: ACCOUNTS_PERMISSIONS.delete, label: "Delete Accounts" },
|
|
33
|
+
] as const satisfies readonly PermissionDefinition[];
|
|
@@ -0,0 +1,200 @@
|
|
|
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
|
+
|
|
14
|
+
import { ACCOUNTS_PERMISSIONS } from "./permissions.js";
|
|
15
|
+
import type { AccountService } from "./services/AccountService.js";
|
|
16
|
+
import {
|
|
17
|
+
accountIdParamSchema,
|
|
18
|
+
createAccountSchema,
|
|
19
|
+
listAccountsQuerySchema,
|
|
20
|
+
updateAccountSchema,
|
|
21
|
+
} from "./validation/schemas.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* v4 routes — `defineAccountsRoutes(app, deps)`.
|
|
25
|
+
*
|
|
26
|
+
* Replaces v3's `Router`-based `routes.ts` + `initializeRoutes(em)`
|
|
27
|
+
* pattern. Differences:
|
|
28
|
+
* - Returns the chained Hono app so consumer composition keeps RPC
|
|
29
|
+
* types end-to-end (`hc<typeof app>()` sees every account route).
|
|
30
|
+
* - Authorization runs at the route via `requirePermission(slug)`
|
|
31
|
+
* middleware, not the v3 `@HasPermission` decorator on a controller
|
|
32
|
+
* method.
|
|
33
|
+
* - Validation runs via `validate('json' | 'query' | 'param', schema)`
|
|
34
|
+
* wrapping `zValidator`; handlers read parsed input via
|
|
35
|
+
* `c.req.valid('json' | ...)`.
|
|
36
|
+
* - 404s throw `NotFoundError` so `app.onError` (registered via
|
|
37
|
+
* `registerErrorHandlers`) produces the consistent JSON error
|
|
38
|
+
* shape — handlers don't shape error responses themselves.
|
|
39
|
+
* - The service is injected (not constructed inside the route file
|
|
40
|
+
* from an EntityManager) so consumers swap it for tests / custom
|
|
41
|
+
* subclasses.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
export interface AccountsRoutesDeps<TAccount extends AuthenticatedAccount = AuthenticatedAccount> {
|
|
45
|
+
service: AccountService;
|
|
46
|
+
provider: AuthProvider<TAccount>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* ⚠️ FOOT-GUN: do NOT thread one shared `app` through several modules'
|
|
51
|
+
* `defineXxxRoutes` calls. Chaining every module's routes onto a single app
|
|
52
|
+
* accumulates one giant Hono route-type and detonates `tsc` (TS2589 /
|
|
53
|
+
* "instantiation excessively deep") once you have enough modules. Prefer
|
|
54
|
+
* {@link buildAccountsApp} and mount it on the root with
|
|
55
|
+
* `root.route("/", buildAccountsApp(deps))` — each module then gets its own
|
|
56
|
+
* bounded sub-app. This raw `(app, deps)` form is kept for advanced
|
|
57
|
+
* composition (deliberately registering accounts routes onto an existing
|
|
58
|
+
* already-typed app).
|
|
59
|
+
*/
|
|
60
|
+
// Generic over Hono's schema param `S`: `.get()`/`.post()` resolve on the
|
|
61
|
+
// parameter's declared type, so taking `Hono<AppEnv>` (or `<T extends
|
|
62
|
+
// Hono<AppEnv>>`) widens an already-chained app and erases every previously
|
|
63
|
+
// registered route from the RPC type. `Hono<AppEnv, S>` accumulates instead —
|
|
64
|
+
// the return type is `Hono<AppEnv, S & <these routes>>`.
|
|
65
|
+
export function defineAccountsRoutes<
|
|
66
|
+
TAccount extends AuthenticatedAccount = AuthenticatedAccount,
|
|
67
|
+
S extends Schema = BlankSchema,
|
|
68
|
+
>(app: Hono<AppEnv, S>, deps: AccountsRoutesDeps<TAccount>) {
|
|
69
|
+
const auth = requireAuth({ provider: deps.provider });
|
|
70
|
+
|
|
71
|
+
return app
|
|
72
|
+
.post(
|
|
73
|
+
"/accounts",
|
|
74
|
+
auth,
|
|
75
|
+
requirePermission(ACCOUNTS_PERMISSIONS.create),
|
|
76
|
+
validate("json", createAccountSchema),
|
|
77
|
+
async (c) => {
|
|
78
|
+
const body = c.req.valid("json");
|
|
79
|
+
const account = await deps.service.create(body);
|
|
80
|
+
return c.json(account, 201);
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
.get(
|
|
84
|
+
"/accounts",
|
|
85
|
+
auth,
|
|
86
|
+
requirePermission(ACCOUNTS_PERMISSIONS.read),
|
|
87
|
+
validate("query", listAccountsQuerySchema),
|
|
88
|
+
async (c) => {
|
|
89
|
+
const q = c.req.valid("query");
|
|
90
|
+
const rows = await deps.service.getAll({
|
|
91
|
+
search: q.search,
|
|
92
|
+
where: filterFromQuery(q),
|
|
93
|
+
});
|
|
94
|
+
return c.json(rows, 200);
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
.get(
|
|
98
|
+
"/accounts/list",
|
|
99
|
+
auth,
|
|
100
|
+
requirePermission(ACCOUNTS_PERMISSIONS.read),
|
|
101
|
+
validate("query", listAccountsQuerySchema),
|
|
102
|
+
async (c) => {
|
|
103
|
+
const q = c.req.valid("query");
|
|
104
|
+
const offset = (q.page - 1) * q.perPage;
|
|
105
|
+
const result = await deps.service.list({
|
|
106
|
+
search: q.search,
|
|
107
|
+
where: filterFromQuery(q),
|
|
108
|
+
limit: q.perPage,
|
|
109
|
+
offset,
|
|
110
|
+
});
|
|
111
|
+
return c.json({ ...result, page: q.page, perPage: q.perPage }, 200);
|
|
112
|
+
},
|
|
113
|
+
)
|
|
114
|
+
.get(
|
|
115
|
+
"/accounts/count",
|
|
116
|
+
auth,
|
|
117
|
+
requirePermission(ACCOUNTS_PERMISSIONS.read),
|
|
118
|
+
validate("query", listAccountsQuerySchema),
|
|
119
|
+
async (c) => {
|
|
120
|
+
const q = c.req.valid("query");
|
|
121
|
+
const count = await deps.service.count({
|
|
122
|
+
search: q.search,
|
|
123
|
+
where: filterFromQuery(q),
|
|
124
|
+
});
|
|
125
|
+
return c.json({ count }, 200);
|
|
126
|
+
},
|
|
127
|
+
)
|
|
128
|
+
.get(
|
|
129
|
+
"/accounts/:id",
|
|
130
|
+
auth,
|
|
131
|
+
requirePermission(ACCOUNTS_PERMISSIONS.read),
|
|
132
|
+
validate("param", accountIdParamSchema),
|
|
133
|
+
async (c) => {
|
|
134
|
+
const { id } = c.req.valid("param");
|
|
135
|
+
const account = await deps.service.get(id);
|
|
136
|
+
if (account === null) throw new NotFoundError("Account not found");
|
|
137
|
+
return c.json(account, 200);
|
|
138
|
+
},
|
|
139
|
+
)
|
|
140
|
+
.put(
|
|
141
|
+
"/accounts/:id",
|
|
142
|
+
auth,
|
|
143
|
+
requirePermission(ACCOUNTS_PERMISSIONS.update),
|
|
144
|
+
validate("param", accountIdParamSchema),
|
|
145
|
+
validate("json", updateAccountSchema),
|
|
146
|
+
async (c) => {
|
|
147
|
+
const { id } = c.req.valid("param");
|
|
148
|
+
const body = c.req.valid("json");
|
|
149
|
+
const account = await deps.service.update(id, body);
|
|
150
|
+
if (account === null) throw new NotFoundError("Account not found");
|
|
151
|
+
return c.json(account, 200);
|
|
152
|
+
},
|
|
153
|
+
)
|
|
154
|
+
.delete(
|
|
155
|
+
"/accounts/:id",
|
|
156
|
+
auth,
|
|
157
|
+
requirePermission(ACCOUNTS_PERMISSIONS.delete),
|
|
158
|
+
validate("param", accountIdParamSchema),
|
|
159
|
+
async (c) => {
|
|
160
|
+
const { id } = c.req.valid("param");
|
|
161
|
+
const existing = await deps.service.get(id);
|
|
162
|
+
if (existing === null) throw new NotFoundError("Account not found");
|
|
163
|
+
await deps.service.delete(id);
|
|
164
|
+
return c.body(null, 204);
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Build the accounts module as its own sub-app, ready to mount on the root:
|
|
171
|
+
*
|
|
172
|
+
* ```ts
|
|
173
|
+
* const app = createApp({ cors }).route("/", buildAccountsApp({ service, provider }));
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* This is the canonical wiring — each module is an independent, bounded
|
|
177
|
+
* sub-app, so the composed `hc()` client type scales without `tsc` overflow.
|
|
178
|
+
* The module owns its registry tag (`createModuleApp("accounts")`), so its
|
|
179
|
+
* routes show up under the `accounts` module in `/dev/routes` and `list_routes`.
|
|
180
|
+
*/
|
|
181
|
+
export function buildAccountsApp<TAccount extends AuthenticatedAccount = AuthenticatedAccount>(
|
|
182
|
+
deps: AccountsRoutesDeps<TAccount>,
|
|
183
|
+
) {
|
|
184
|
+
return defineAccountsRoutes(createModuleApp("accounts"), deps);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Translates the strict-typed query options into the
|
|
189
|
+
* `DrizzleEntityService.QueryOptions['where']` shape — booleans coerced
|
|
190
|
+
* from "true" / "false", optional fields stripped when absent.
|
|
191
|
+
*/
|
|
192
|
+
function filterFromQuery(q: {
|
|
193
|
+
isActive?: "true" | "false";
|
|
194
|
+
roleId?: string;
|
|
195
|
+
}): Record<string, unknown> | undefined {
|
|
196
|
+
const where: Record<string, unknown> = {};
|
|
197
|
+
if (q.isActive !== undefined) where.isActive = q.isActive === "true";
|
|
198
|
+
if (q.roleId !== undefined) where.roleId = q.roleId;
|
|
199
|
+
return Object.keys(where).length > 0 ? where : undefined;
|
|
200
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { baseFields } from "@sixthsummit/ship-api/app/db/baseFields";
|
|
2
|
+
import { relations } from "drizzle-orm";
|
|
3
|
+
import {
|
|
4
|
+
boolean,
|
|
5
|
+
index,
|
|
6
|
+
pgTable,
|
|
7
|
+
timestamp,
|
|
8
|
+
uniqueIndex,
|
|
9
|
+
uuid,
|
|
10
|
+
varchar,
|
|
11
|
+
} from "drizzle-orm/pg-core";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Identity + RBAC schema for the accounts module.
|
|
15
|
+
*
|
|
16
|
+
* Relocated out of framework core (`@sixthsummit/ship-api/app/schema/*`) so the
|
|
17
|
+
* framework stays incrementally adoptable and each product owns / tailors its
|
|
18
|
+
* identity model (multi-tenant or not). Core ships the primitives — `baseFields`,
|
|
19
|
+
* the `AuthProvider` interface, `DrizzleEntityService`; this module owns the
|
|
20
|
+
* concrete tables.
|
|
21
|
+
*
|
|
22
|
+
* Spread `accountsSchema` into `createApp({ schema })` (and the test-DB harness)
|
|
23
|
+
* the way the old core `defaultSchema` was.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* `tenants` — opt-in multi-tenancy root table (A2-1).
|
|
28
|
+
*
|
|
29
|
+
* Tenancy is a per-product choice. This table + the `tenantsSchema` fragment
|
|
30
|
+
* ship with the accounts module but are NOT part of the default `accountsSchema`
|
|
31
|
+
* — a single-tenant product never composes them and never sees a `tenants`
|
|
32
|
+
* table. A multi-tenant product:
|
|
33
|
+
* 1. composes `tenantsSchema` into `createApp({ schema })`,
|
|
34
|
+
* 2. applies `...tenantScoped(tenants)` to the domain tables it wants scoped
|
|
35
|
+
* (and, for the one-tenant-per-account default, to `accounts` — see the
|
|
36
|
+
* commented field below),
|
|
37
|
+
* 3. wires `resolveTenant()` after `requireAuth`.
|
|
38
|
+
*
|
|
39
|
+
* Domain tables FK `tenants`, not `accounts`, so a future move to a membership
|
|
40
|
+
* model (Model A → B) is an identity-tables-only migration. See
|
|
41
|
+
* `docs/v4/concepts/tenancy.md`.
|
|
42
|
+
*/
|
|
43
|
+
export const tenants = pgTable("tenants", {
|
|
44
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
45
|
+
slug: varchar("slug", { length: 100 }).notNull().unique(),
|
|
46
|
+
name: varchar("name", { length: 200 }).notNull(),
|
|
47
|
+
...baseFields,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export type Tenant = typeof tenants.$inferSelect;
|
|
51
|
+
export type NewTenant = typeof tenants.$inferInsert;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Opt-in tenancy schema fragment — compose alongside `accountsSchema` when a
|
|
55
|
+
* product enables multi-tenancy:
|
|
56
|
+
* `createApp({ schema: { ...accountsSchema, ...tenantsSchema, ...domainTables } })`.
|
|
57
|
+
* Kept separate from `accountsSchema` so single-tenant products never get a
|
|
58
|
+
* `tenants` table.
|
|
59
|
+
*/
|
|
60
|
+
export const tenantsSchema = {
|
|
61
|
+
tenants,
|
|
62
|
+
} as const;
|
|
63
|
+
|
|
64
|
+
export const roles = pgTable("roles", {
|
|
65
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
66
|
+
slug: varchar("slug", { length: 100 }).notNull().unique(),
|
|
67
|
+
name: varchar("name", { length: 100 }).notNull(),
|
|
68
|
+
description: varchar("description", { length: 500 }),
|
|
69
|
+
...baseFields,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export const permissions = pgTable("permissions", {
|
|
73
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
74
|
+
slug: varchar("slug", { length: 200 }).notNull().unique(),
|
|
75
|
+
name: varchar("name", { length: 200 }).notNull(),
|
|
76
|
+
...baseFields,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export const rolePermissions = pgTable("role_permissions", {
|
|
80
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
81
|
+
roleId: uuid("role_id")
|
|
82
|
+
.notNull()
|
|
83
|
+
.references(() => roles.id, { onDelete: "cascade" }),
|
|
84
|
+
permissionId: uuid("permission_id")
|
|
85
|
+
.notNull()
|
|
86
|
+
.references(() => permissions.id, { onDelete: "cascade" }),
|
|
87
|
+
...baseFields,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export const accounts = pgTable(
|
|
91
|
+
"accounts",
|
|
92
|
+
{
|
|
93
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Stable subject identifier from the auth provider (Firebase UID by default;
|
|
97
|
+
* `sub` claim under any other `AuthProvider` adapter).
|
|
98
|
+
*/
|
|
99
|
+
firebaseUid: varchar("firebase_uid", { length: 128 }),
|
|
100
|
+
|
|
101
|
+
email: varchar("email", { length: 320 }).notNull(),
|
|
102
|
+
emailVerified: boolean("email_verified").notNull().default(false),
|
|
103
|
+
|
|
104
|
+
displayName: varchar("display_name", { length: 200 }),
|
|
105
|
+
|
|
106
|
+
/** Soft-disable without deleting (distinct from `deletedAt`). */
|
|
107
|
+
isActive: boolean("is_active").notNull().default(true),
|
|
108
|
+
|
|
109
|
+
/** Optional FK to a single primary role. Multi-role assignments are
|
|
110
|
+
* modeled in a join table by consumers who need them. */
|
|
111
|
+
roleId: uuid("role_id").references(() => roles.id, { onDelete: "set null" }),
|
|
112
|
+
|
|
113
|
+
// ─── Multi-tenancy (opt-in, A2-1) ────────────────────────────────
|
|
114
|
+
// Uncomment for the one-tenant-per-account model: adds a non-null
|
|
115
|
+
// `tenant_id` uuid FK → tenants.id. Then compose `tenantsSchema` into your
|
|
116
|
+
// app schema and wire `resolveTenant()` after `requireAuth`. Import the
|
|
117
|
+
// mixin from the barrel: `import { tenantScoped } from "@sixthsummit/ship-api"`.
|
|
118
|
+
// ...tenantScoped(tenants),
|
|
119
|
+
|
|
120
|
+
...baseFields,
|
|
121
|
+
},
|
|
122
|
+
(table) => [
|
|
123
|
+
uniqueIndex("accounts_email_unique").on(table.email),
|
|
124
|
+
uniqueIndex("accounts_firebase_uid_unique").on(table.firebaseUid),
|
|
125
|
+
],
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
export const rolesRelations = relations(roles, ({ many }) => ({
|
|
129
|
+
rolePermissions: many(rolePermissions),
|
|
130
|
+
}));
|
|
131
|
+
|
|
132
|
+
export const permissionsRelations = relations(permissions, ({ many }) => ({
|
|
133
|
+
rolePermissions: many(rolePermissions),
|
|
134
|
+
}));
|
|
135
|
+
|
|
136
|
+
export const rolePermissionsRelations = relations(rolePermissions, ({ one }) => ({
|
|
137
|
+
role: one(roles, {
|
|
138
|
+
fields: [rolePermissions.roleId],
|
|
139
|
+
references: [roles.id],
|
|
140
|
+
}),
|
|
141
|
+
permission: one(permissions, {
|
|
142
|
+
fields: [rolePermissions.permissionId],
|
|
143
|
+
references: [permissions.id],
|
|
144
|
+
}),
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
export const accountsRelations = relations(accounts, ({ one }) => ({
|
|
148
|
+
role: one(roles, {
|
|
149
|
+
fields: [accounts.roleId],
|
|
150
|
+
references: [roles.id],
|
|
151
|
+
}),
|
|
152
|
+
}));
|
|
153
|
+
|
|
154
|
+
export type Account = typeof accounts.$inferSelect;
|
|
155
|
+
export type NewAccount = typeof accounts.$inferInsert;
|
|
156
|
+
export type Role = typeof roles.$inferSelect;
|
|
157
|
+
export type NewRole = typeof roles.$inferInsert;
|
|
158
|
+
export type Permission = typeof permissions.$inferSelect;
|
|
159
|
+
export type NewPermission = typeof permissions.$inferInsert;
|
|
160
|
+
export type RolePermission = typeof rolePermissions.$inferSelect;
|
|
161
|
+
export type NewRolePermission = typeof rolePermissions.$inferInsert;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* `refresh_tokens` — server-side store for the JWT-cookie auth refresh-token
|
|
165
|
+
* rotation flow. `tokenHash` is a SHA-256 of the token (never the raw value);
|
|
166
|
+
* `revokedAt` supports immediate server-side revocation; `replacedById` tracks
|
|
167
|
+
* rotation history so refresh-token reuse (a theft signal) can revoke the whole
|
|
168
|
+
* chain. Consumed by the framework's generic `DrizzleRefreshTokenStore`, which
|
|
169
|
+
* takes this table via its constructor.
|
|
170
|
+
*/
|
|
171
|
+
export const refreshTokens = pgTable(
|
|
172
|
+
"refresh_tokens",
|
|
173
|
+
{
|
|
174
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
175
|
+
accountId: uuid("account_id")
|
|
176
|
+
.notNull()
|
|
177
|
+
.references(() => accounts.id, { onDelete: "cascade" }),
|
|
178
|
+
tokenHash: varchar("token_hash", { length: 128 }).notNull().unique(),
|
|
179
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
180
|
+
revokedAt: timestamp("revoked_at", { withTimezone: true }),
|
|
181
|
+
replacedById: uuid("replaced_by_id"),
|
|
182
|
+
/** User-agent / IP on issue, for audit + risk signals. */
|
|
183
|
+
userAgent: varchar("user_agent", { length: 500 }),
|
|
184
|
+
issuedFromIp: varchar("issued_from_ip", { length: 64 }),
|
|
185
|
+
...baseFields,
|
|
186
|
+
},
|
|
187
|
+
(table) => [
|
|
188
|
+
index("refresh_tokens_account_id_idx").on(table.accountId),
|
|
189
|
+
index("refresh_tokens_expires_at_idx").on(table.expiresAt),
|
|
190
|
+
],
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
export const refreshTokensRelations = relations(refreshTokens, ({ one }) => ({
|
|
194
|
+
account: one(accounts, {
|
|
195
|
+
fields: [refreshTokens.accountId],
|
|
196
|
+
references: [accounts.id],
|
|
197
|
+
}),
|
|
198
|
+
}));
|
|
199
|
+
|
|
200
|
+
export type RefreshToken = typeof refreshTokens.$inferSelect;
|
|
201
|
+
export type NewRefreshToken = typeof refreshTokens.$inferInsert;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Composable schema fragment — spread into `createApp({ schema })` and the
|
|
205
|
+
* integration-test DB harness. Replaces this module's slice of the old core
|
|
206
|
+
* `defaultSchema`.
|
|
207
|
+
*/
|
|
208
|
+
export const accountsSchema = {
|
|
209
|
+
accounts,
|
|
210
|
+
accountsRelations,
|
|
211
|
+
roles,
|
|
212
|
+
rolesRelations,
|
|
213
|
+
permissions,
|
|
214
|
+
permissionsRelations,
|
|
215
|
+
rolePermissions,
|
|
216
|
+
rolePermissionsRelations,
|
|
217
|
+
refreshTokens,
|
|
218
|
+
refreshTokensRelations,
|
|
219
|
+
} as const;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { DrizzleEntityService } from "@sixthsummit/ship-api/app/services/DrizzleEntityService";
|
|
2
|
+
import { accounts } from "../schema.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* v4 `AccountService` — thin extension of `DrizzleEntityService` against
|
|
6
|
+
* the framework's default `accounts` table.
|
|
7
|
+
*
|
|
8
|
+
* Replaces v3's `EntityService<Account>` subclass. Same surface
|
|
9
|
+
* (`get`/`getAll`/`list`/`count`/`create`/`update`/`delete`) inherited
|
|
10
|
+
* from the base; only the entity-specific overrides live here:
|
|
11
|
+
*
|
|
12
|
+
* - `getTable()` returns the framework's default `accounts` pgTable
|
|
13
|
+
* - `getDefaultSearchFields()` lists the columns the free-text
|
|
14
|
+
* `?search=` filter scans (email + displayName, the human-readable
|
|
15
|
+
* identifiers operators reach for in admin UIs)
|
|
16
|
+
* - `getDefaultRelations()` declares `role` so `?relations=role`
|
|
17
|
+
* loads a populated role
|
|
18
|
+
*
|
|
19
|
+
* Soft-delete + audit-column auto-stamping (createdAt / createdBy on
|
|
20
|
+
* insert; updatedAt / updatedBy on update) are inherited from the
|
|
21
|
+
* base — no per-service wiring required.
|
|
22
|
+
*
|
|
23
|
+
* Schema customization: consumers who extend the `accounts` table via
|
|
24
|
+
* `createApp({ schema })` should subclass this service (or replace it
|
|
25
|
+
* entirely) so `getDefaultSearchFields()` reflects any new searchable
|
|
26
|
+
* columns. The `TSchema` generic carries the full composed schema so
|
|
27
|
+
* Drizzle relational queries stay typed end-to-end.
|
|
28
|
+
*/
|
|
29
|
+
export class AccountService extends DrizzleEntityService<
|
|
30
|
+
typeof accounts,
|
|
31
|
+
{ accounts: typeof accounts }
|
|
32
|
+
> {
|
|
33
|
+
protected getTable() {
|
|
34
|
+
return accounts;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected override getDefaultSearchFields(): readonly string[] {
|
|
38
|
+
return ["email", "displayName"];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected override getDefaultRelations(): readonly string[] {
|
|
42
|
+
return ["role"];
|
|
43
|
+
}
|
|
44
|
+
}
|