@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,148 @@
|
|
|
1
|
+
import type { EmailTemplate } from "./types/index.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TemplateRegistry - Registry for managing email templates
|
|
5
|
+
*
|
|
6
|
+
* Provides centralized storage and retrieval of email templates.
|
|
7
|
+
* Templates can be registered at application startup and retrieved by ID.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const registry = new TemplateRegistry();
|
|
12
|
+
*
|
|
13
|
+
* // Register a template
|
|
14
|
+
* registry.register({
|
|
15
|
+
* id: 'welcome',
|
|
16
|
+
* name: 'Welcome Email',
|
|
17
|
+
* subject: 'Welcome to {{appName}}!',
|
|
18
|
+
* html: '<h1>Hello {{firstName}}!</h1>',
|
|
19
|
+
* text: 'Hello {{firstName}}!'
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Get a template
|
|
23
|
+
* const template = registry.get('welcome');
|
|
24
|
+
*
|
|
25
|
+
* // List all templates
|
|
26
|
+
* const templates = registry.list();
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export default class TemplateRegistry {
|
|
30
|
+
private templates: Map<string, EmailTemplate<any>>;
|
|
31
|
+
|
|
32
|
+
constructor() {
|
|
33
|
+
this.templates = new Map();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Register a new email template
|
|
38
|
+
* @param template - Template to register
|
|
39
|
+
* @throws Error if template with same ID already exists
|
|
40
|
+
*/
|
|
41
|
+
register<T = Record<string, any>>(template: EmailTemplate<T>): void {
|
|
42
|
+
if (this.templates.has(template.id)) {
|
|
43
|
+
throw new Error(`Template with ID '${template.id}' already exists`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Validate template has at least subject and one body type
|
|
47
|
+
if (!template.subject) {
|
|
48
|
+
throw new Error(`Template '${template.id}' must have a subject`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!template.html && !template.text) {
|
|
52
|
+
throw new Error(`Template '${template.id}' must have either html or text content`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.templates.set(template.id, template as EmailTemplate<any>);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Register multiple templates at once
|
|
60
|
+
* @param templates - Array of templates to register
|
|
61
|
+
*/
|
|
62
|
+
registerMany(templates: EmailTemplate<any>[]): void {
|
|
63
|
+
for (const template of templates) {
|
|
64
|
+
this.register(template);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get a template by ID
|
|
70
|
+
* @param id - Template ID
|
|
71
|
+
* @returns Template or undefined if not found
|
|
72
|
+
*/
|
|
73
|
+
get(id: string): EmailTemplate<any> | undefined {
|
|
74
|
+
return this.templates.get(id);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get a template by ID or throw error if not found
|
|
79
|
+
* @param id - Template ID
|
|
80
|
+
* @returns Template
|
|
81
|
+
* @throws Error if template not found
|
|
82
|
+
*/
|
|
83
|
+
getOrThrow(id: string): EmailTemplate<any> {
|
|
84
|
+
const template = this.templates.get(id);
|
|
85
|
+
if (!template) {
|
|
86
|
+
throw new Error(`Template with ID '${id}' not found`);
|
|
87
|
+
}
|
|
88
|
+
return template;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Check if a template exists
|
|
93
|
+
* @param id - Template ID
|
|
94
|
+
* @returns True if template exists
|
|
95
|
+
*/
|
|
96
|
+
has(id: string): boolean {
|
|
97
|
+
return this.templates.has(id);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Remove a template from the registry
|
|
102
|
+
* @param id - Template ID
|
|
103
|
+
* @returns True if template was removed
|
|
104
|
+
*/
|
|
105
|
+
unregister(id: string): boolean {
|
|
106
|
+
return this.templates.delete(id);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Clear all templates from the registry
|
|
111
|
+
*/
|
|
112
|
+
clear(): void {
|
|
113
|
+
this.templates.clear();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* List all registered templates
|
|
118
|
+
* @returns Array of all templates
|
|
119
|
+
*/
|
|
120
|
+
list(): EmailTemplate<any>[] {
|
|
121
|
+
return Array.from(this.templates.values());
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get all template IDs
|
|
126
|
+
* @returns Array of template IDs
|
|
127
|
+
*/
|
|
128
|
+
listIds(): string[] {
|
|
129
|
+
return Array.from(this.templates.keys());
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get count of registered templates
|
|
134
|
+
* @returns Number of templates
|
|
135
|
+
*/
|
|
136
|
+
count(): number {
|
|
137
|
+
return this.templates.size;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Find templates by tag
|
|
142
|
+
* @param tag - Tag to search for
|
|
143
|
+
* @returns Array of templates with the specified tag
|
|
144
|
+
*/
|
|
145
|
+
findByTag(tag: string): EmailTemplate[] {
|
|
146
|
+
return Array.from(this.templates.values()).filter((template) => template.tags?.includes(tag));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import type { EmailTemplate, RenderedTemplate } from "./types/index.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TemplateRenderer - Renders email templates with variable substitution
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - Variable substitution using {{variableName}} syntax
|
|
8
|
+
* - Nested object access using dot notation: {{user.firstName}}
|
|
9
|
+
* - Array indexing: {{items.0.name}}
|
|
10
|
+
* - Conditional rendering: {{#if condition}}...{{/if}}
|
|
11
|
+
* - Loops: {{#each items}}...{{/each}}
|
|
12
|
+
* - Helper functions: {{formatDate date}}
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const renderer = new TemplateRenderer();
|
|
17
|
+
* const result = renderer.render(template, {
|
|
18
|
+
* firstName: 'John',
|
|
19
|
+
* lastName: 'Doe',
|
|
20
|
+
* importCount: 100
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export default class TemplateRenderer {
|
|
25
|
+
/**
|
|
26
|
+
* Render a template with the provided variables
|
|
27
|
+
* @param template - Template to render
|
|
28
|
+
* @param variables - Variables to substitute in the template
|
|
29
|
+
* @returns Rendered template
|
|
30
|
+
*/
|
|
31
|
+
render<T extends Record<string, any> = Record<string, any>>(
|
|
32
|
+
template: EmailTemplate<T>,
|
|
33
|
+
variables: T,
|
|
34
|
+
): RenderedTemplate {
|
|
35
|
+
// Render subject
|
|
36
|
+
const subject = this.renderString(template.subject, variables as Record<string, any>);
|
|
37
|
+
|
|
38
|
+
// Render HTML body (if present)
|
|
39
|
+
const html = template.html
|
|
40
|
+
? this.renderString(template.html, variables as Record<string, any>)
|
|
41
|
+
: undefined;
|
|
42
|
+
|
|
43
|
+
// Render text body (if present)
|
|
44
|
+
const text = template.text
|
|
45
|
+
? this.renderString(template.text, variables as Record<string, any>)
|
|
46
|
+
: undefined;
|
|
47
|
+
|
|
48
|
+
// Process tags
|
|
49
|
+
const tags = template.tags?.map((tag) => ({
|
|
50
|
+
name: tag,
|
|
51
|
+
value: this.renderString(tag, variables as Record<string, any>),
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
templateId: template.id,
|
|
56
|
+
subject,
|
|
57
|
+
html,
|
|
58
|
+
text,
|
|
59
|
+
from: template.from,
|
|
60
|
+
replyTo: template.replyTo,
|
|
61
|
+
tags,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Render a string with variable substitution
|
|
67
|
+
* @param content - String content with {{variable}} placeholders
|
|
68
|
+
* @param variables - Variables to substitute
|
|
69
|
+
* @returns Rendered string
|
|
70
|
+
*/
|
|
71
|
+
private renderString(content: string, variables: Record<string, any>): string {
|
|
72
|
+
let result = content;
|
|
73
|
+
|
|
74
|
+
// Handle loops FIRST {{#each items}}...{{/each}}
|
|
75
|
+
// Loops need to be processed before conditionals because they create context variables like @first, @last
|
|
76
|
+
result = this.renderLoops(result, variables);
|
|
77
|
+
|
|
78
|
+
// Handle conditional blocks {{#if condition}}...{{/if}}
|
|
79
|
+
result = this.renderConditionals(result, variables);
|
|
80
|
+
|
|
81
|
+
// Handle helper functions {{helperName arg1 arg2}} - BEFORE simple variables
|
|
82
|
+
result = this.renderHelpers(result, variables);
|
|
83
|
+
|
|
84
|
+
// Handle simple variable substitution {{variableName}}
|
|
85
|
+
result = this.renderVariables(result, variables);
|
|
86
|
+
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Render simple variable substitutions
|
|
92
|
+
* Supports:
|
|
93
|
+
* - {{variableName}}
|
|
94
|
+
* - {{user.firstName}} (nested objects)
|
|
95
|
+
* - {{items.0.name}} (array indexing)
|
|
96
|
+
*/
|
|
97
|
+
private renderVariables(content: string, variables: Record<string, any>): string {
|
|
98
|
+
return content.replace(/\{\{([^#/}]+)\}\}/g, (match, variablePath) => {
|
|
99
|
+
const trimmedPath = variablePath.trim();
|
|
100
|
+
const value = this.getNestedValue(variables, trimmedPath);
|
|
101
|
+
|
|
102
|
+
if (value === undefined || value === null) {
|
|
103
|
+
return "";
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return String(value);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Render conditional blocks
|
|
112
|
+
* Syntax: {{#if variableName}}content{{/if}}
|
|
113
|
+
*/
|
|
114
|
+
private renderConditionals(content: string, variables: Record<string, any>): string {
|
|
115
|
+
const conditionalRegex = /\{\{#if\s+([^}]+)\}\}([\s\S]*?)\{\{\/if\}\}/g;
|
|
116
|
+
|
|
117
|
+
return content.replace(conditionalRegex, (match, condition, innerContent) => {
|
|
118
|
+
const trimmedCondition = condition.trim();
|
|
119
|
+
|
|
120
|
+
// Direct property access for variables starting with @
|
|
121
|
+
const value = trimmedCondition.startsWith("@")
|
|
122
|
+
? variables[trimmedCondition]
|
|
123
|
+
: this.getNestedValue(variables, trimmedCondition);
|
|
124
|
+
|
|
125
|
+
// Evaluate truthiness
|
|
126
|
+
const isTruthy = this.isTruthy(value);
|
|
127
|
+
|
|
128
|
+
return isTruthy ? innerContent : "";
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Render loop blocks
|
|
134
|
+
* Syntax: {{#each items}}{{this.name}}{{/each}}
|
|
135
|
+
*/
|
|
136
|
+
private renderLoops(content: string, variables: Record<string, any>): string {
|
|
137
|
+
const loopRegex = /\{\{#each\s+([^}]+)\}\}([\s\S]*?)\{\{\/each\}\}/g;
|
|
138
|
+
|
|
139
|
+
return content.replace(loopRegex, (match, arrayPath, innerContent) => {
|
|
140
|
+
const trimmedPath = arrayPath.trim();
|
|
141
|
+
const array = this.getNestedValue(variables, trimmedPath);
|
|
142
|
+
|
|
143
|
+
if (!Array.isArray(array)) {
|
|
144
|
+
return "";
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return array
|
|
148
|
+
.map((item, index) => {
|
|
149
|
+
// Create context with 'this' pointing to current item
|
|
150
|
+
const itemContext = {
|
|
151
|
+
...variables,
|
|
152
|
+
this: item,
|
|
153
|
+
"@index": index,
|
|
154
|
+
"@first": index === 0,
|
|
155
|
+
"@last": index === array.length - 1,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Render inner content with full processing (conditionals, helpers, and variables)
|
|
159
|
+
let renderedContent = innerContent;
|
|
160
|
+
renderedContent = this.renderConditionals(renderedContent, itemContext);
|
|
161
|
+
renderedContent = this.renderHelpers(renderedContent, itemContext);
|
|
162
|
+
renderedContent = this.renderVariables(renderedContent, itemContext);
|
|
163
|
+
return renderedContent;
|
|
164
|
+
})
|
|
165
|
+
.join("");
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Render helper functions
|
|
171
|
+
* Supports:
|
|
172
|
+
* - {{formatNumber value}} - Format number with commas
|
|
173
|
+
* - {{formatDate date}} - Format date
|
|
174
|
+
* - {{pluralize count singular plural}} - Pluralize based on count
|
|
175
|
+
*/
|
|
176
|
+
private renderHelpers(content: string, variables: Record<string, any>): string {
|
|
177
|
+
// Match helper functions that don't use # or /
|
|
178
|
+
const helperRegex = /\{\{(?!#|\/)(formatNumber|formatDate|pluralize)\s+([^}]+)\}\}/g;
|
|
179
|
+
|
|
180
|
+
return content.replace(helperRegex, (match, helperName, args) => {
|
|
181
|
+
const argsList = args.split(/\s+/).map((arg: string) => {
|
|
182
|
+
// Check if it's a variable reference or a literal
|
|
183
|
+
if (arg.startsWith("'") || arg.startsWith('"')) {
|
|
184
|
+
return arg.slice(1, -1); // Remove quotes
|
|
185
|
+
}
|
|
186
|
+
return this.getNestedValue(variables, arg);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
switch (helperName) {
|
|
190
|
+
case "formatNumber":
|
|
191
|
+
return this.formatNumber(argsList[0]);
|
|
192
|
+
case "formatDate":
|
|
193
|
+
return this.formatDate(argsList[0]);
|
|
194
|
+
case "pluralize":
|
|
195
|
+
return this.pluralize(argsList[0], argsList[1], argsList[2]);
|
|
196
|
+
default:
|
|
197
|
+
return match; // Return original if helper not found
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Get nested value from object using dot notation
|
|
204
|
+
* @param obj - Object to traverse
|
|
205
|
+
* @param path - Dot-notation path (e.g., "user.firstName" or "items.0.name")
|
|
206
|
+
* @returns Value at path or undefined
|
|
207
|
+
*/
|
|
208
|
+
private getNestedValue(obj: any, path: string): any {
|
|
209
|
+
const parts = path.split(".");
|
|
210
|
+
let current = obj;
|
|
211
|
+
|
|
212
|
+
for (const part of parts) {
|
|
213
|
+
if (current === undefined || current === null) {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Handle array indexing
|
|
218
|
+
const arrayIndex = parseInt(part, 10);
|
|
219
|
+
if (!Number.isNaN(arrayIndex)) {
|
|
220
|
+
current = current[arrayIndex];
|
|
221
|
+
} else {
|
|
222
|
+
current = current[part];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return current;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Check if a value is truthy
|
|
231
|
+
*/
|
|
232
|
+
private isTruthy(value: any): boolean {
|
|
233
|
+
if (value === undefined || value === null) return false;
|
|
234
|
+
if (typeof value === "boolean") return value;
|
|
235
|
+
if (typeof value === "number") return value !== 0;
|
|
236
|
+
if (typeof value === "string") return value.length > 0;
|
|
237
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Format a number with comma separators
|
|
243
|
+
*/
|
|
244
|
+
private formatNumber(value: any): string {
|
|
245
|
+
const num = Number(value);
|
|
246
|
+
if (Number.isNaN(num)) return String(value);
|
|
247
|
+
return num.toLocaleString();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Format a date
|
|
252
|
+
*/
|
|
253
|
+
private formatDate(value: any): string {
|
|
254
|
+
if (!value) return "";
|
|
255
|
+
|
|
256
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
257
|
+
if (Number.isNaN(date.getTime())) return String(value);
|
|
258
|
+
|
|
259
|
+
return date.toLocaleDateString("en-US", {
|
|
260
|
+
year: "numeric",
|
|
261
|
+
month: "long",
|
|
262
|
+
day: "numeric",
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Pluralize based on count
|
|
268
|
+
*/
|
|
269
|
+
private pluralize(count: any, singular: string, plural: string): string {
|
|
270
|
+
const num = Number(count);
|
|
271
|
+
return num === 1 ? singular : plural;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import Logger from "../app/utils/Logger.js";
|
|
2
|
+
import EmailService from "./EmailService.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Singleton EmailService instance with registered templates
|
|
6
|
+
* Available globally after initialization
|
|
7
|
+
*/
|
|
8
|
+
let emailServiceInstance: EmailService | null = null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the singleton EmailService instance and register all email templates
|
|
12
|
+
* This function can be called from scripts or tests that need email functionality
|
|
13
|
+
*
|
|
14
|
+
* @returns The initialized EmailService instance
|
|
15
|
+
* @throws Error if initialization fails
|
|
16
|
+
*/
|
|
17
|
+
export async function initializeEmailService(): Promise<EmailService> {
|
|
18
|
+
// Return existing instance if already initialized
|
|
19
|
+
if (emailServiceInstance) {
|
|
20
|
+
return emailServiceInstance;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Logger.log("Initializing email templates...");
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Create singleton EmailService instance
|
|
27
|
+
// Uses RESEND_API_KEY and RESEND_DEFAULT_FROM environment variables
|
|
28
|
+
emailServiceInstance = new EmailService();
|
|
29
|
+
|
|
30
|
+
// Register templates from all modules
|
|
31
|
+
//emailServiceInstance.registerTemplates(...);
|
|
32
|
+
|
|
33
|
+
Logger.log(`Registered ${emailServiceInstance.listTemplates().length} email templates:`, {
|
|
34
|
+
templateIds: emailServiceInstance.listTemplates().map((t) => t.id),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
Logger.log("Email templates initialized successfully");
|
|
38
|
+
|
|
39
|
+
return emailServiceInstance;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
Logger.error("Error initializing email templates:", error);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get the singleton EmailService instance
|
|
48
|
+
*
|
|
49
|
+
* @returns EmailService instance with all templates registered
|
|
50
|
+
* @throws Error if called before initialization
|
|
51
|
+
*/
|
|
52
|
+
export function getEmailService(): EmailService {
|
|
53
|
+
if (!emailServiceInstance) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
"EmailService not initialized. Call initializeEmailService() first or ensure InitEmailTemplates bootstrapper has run.",
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return emailServiceInstance;
|
|
60
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "email",
|
|
3
|
+
"description": "Email sending utilities with template support",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"dependencies": [],
|
|
6
|
+
"npmDependencies": {
|
|
7
|
+
"resend": "^6.7.0"
|
|
8
|
+
},
|
|
9
|
+
"requiredEnvVars": ["RESEND_API_KEY", "RESEND_DEFAULT_FROM"],
|
|
10
|
+
"optionalEnvVars": [],
|
|
11
|
+
"postInstall": ["Configure Resend API key and default from address in .env"]
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email attachment
|
|
3
|
+
*/
|
|
4
|
+
export interface EmailAttachment {
|
|
5
|
+
/** Attachment filename */
|
|
6
|
+
filename: string;
|
|
7
|
+
/** Attachment content (Buffer or base64 string) */
|
|
8
|
+
content: Buffer | string;
|
|
9
|
+
/** Content type (MIME type) */
|
|
10
|
+
contentType?: string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email template definition
|
|
3
|
+
*/
|
|
4
|
+
export interface EmailTemplate<T = Record<string, any>> {
|
|
5
|
+
/**
|
|
6
|
+
* Unique identifier for the template
|
|
7
|
+
*/
|
|
8
|
+
id: string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Human-readable name for the template
|
|
12
|
+
*/
|
|
13
|
+
name: string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Description of the template purpose
|
|
17
|
+
*/
|
|
18
|
+
description?: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Email subject line (supports variable substitution)
|
|
22
|
+
*/
|
|
23
|
+
subject: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* HTML email body (supports variable substitution)
|
|
27
|
+
*/
|
|
28
|
+
html?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Plain text email body (supports variable substitution)
|
|
32
|
+
*/
|
|
33
|
+
text?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Optional default "from" address for this template
|
|
37
|
+
*/
|
|
38
|
+
from?: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Optional reply-to address for this template
|
|
42
|
+
*/
|
|
43
|
+
replyTo?: string;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Template variables schema (for validation)
|
|
47
|
+
*/
|
|
48
|
+
variables?: (keyof T)[];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Optional tags for the template
|
|
52
|
+
*/
|
|
53
|
+
tags?: string[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Options for rendering a template
|
|
58
|
+
*/
|
|
59
|
+
export interface RenderTemplateOptions<T = Record<string, any>> {
|
|
60
|
+
/**
|
|
61
|
+
* Template ID to render
|
|
62
|
+
*/
|
|
63
|
+
templateId: string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Variables to substitute in the template
|
|
67
|
+
*/
|
|
68
|
+
variables: T;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Optional: Override the default "from" address
|
|
72
|
+
*/
|
|
73
|
+
from?: string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Optional: Override the default "reply-to" address
|
|
77
|
+
*/
|
|
78
|
+
replyTo?: string;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Optional: Additional tags to add
|
|
82
|
+
*/
|
|
83
|
+
tags?: string[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Result of rendering a template
|
|
88
|
+
*/
|
|
89
|
+
export interface RenderedTemplate {
|
|
90
|
+
/**
|
|
91
|
+
* Template ID that was rendered
|
|
92
|
+
*/
|
|
93
|
+
templateId: string;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Rendered subject line
|
|
97
|
+
*/
|
|
98
|
+
subject: string;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Rendered HTML body (if template has HTML)
|
|
102
|
+
*/
|
|
103
|
+
html?: string;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Rendered plain text body (if template has text)
|
|
107
|
+
*/
|
|
108
|
+
text?: string;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* From address
|
|
112
|
+
*/
|
|
113
|
+
from?: string;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Reply-to address
|
|
117
|
+
*/
|
|
118
|
+
replyTo?: string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Tags for the email
|
|
122
|
+
*/
|
|
123
|
+
tags?: Array<{ name: string; value: string }>;
|
|
124
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { EmailAddress } from "./EmailAddress.js";
|
|
2
|
+
import type { EmailAttachment } from "./EmailAttachment.js";
|
|
3
|
+
import type { EmailTag } from "./EmailTag.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for sending a single email
|
|
7
|
+
*/
|
|
8
|
+
export interface SendEmailOptions {
|
|
9
|
+
/** Sender email address */
|
|
10
|
+
from?: string;
|
|
11
|
+
/** Recipient email address(es) */
|
|
12
|
+
to: EmailAddress | EmailAddress[];
|
|
13
|
+
/** Email subject */
|
|
14
|
+
subject: string;
|
|
15
|
+
/** Plain text content */
|
|
16
|
+
text?: string;
|
|
17
|
+
/** HTML content */
|
|
18
|
+
html?: string;
|
|
19
|
+
/** CC recipients */
|
|
20
|
+
cc?: EmailAddress | EmailAddress[];
|
|
21
|
+
/** BCC recipients */
|
|
22
|
+
bcc?: EmailAddress | EmailAddress[];
|
|
23
|
+
/** Reply-to address(es) */
|
|
24
|
+
replyTo?: EmailAddress | EmailAddress[];
|
|
25
|
+
/** Email attachments */
|
|
26
|
+
attachments?: EmailAttachment[];
|
|
27
|
+
/** Email tags for tracking */
|
|
28
|
+
tags?: EmailTag[];
|
|
29
|
+
/** Custom headers */
|
|
30
|
+
headers?: Record<string, string>;
|
|
31
|
+
/** Schedule email to be sent at a specific time (ISO 8601 format) */
|
|
32
|
+
scheduledAt?: string;
|
|
33
|
+
}
|