@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,389 @@
|
|
|
1
|
+
import { encoding_for_model, get_encoding, type Tiktoken } from "tiktoken";
|
|
2
|
+
import type { SemanticChunkingOptions, TextChunk } from "../types/index.js";
|
|
3
|
+
import type { ChunkingStrategy } from "./ChunkingStrategy.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Semantic chunking strategy that creates chunks based on document structure
|
|
7
|
+
*
|
|
8
|
+
* Industry Best Practices Implemented:
|
|
9
|
+
* - Content-aware chunking using document structure
|
|
10
|
+
* - Preserves semantic units (paragraphs, sections, lists)
|
|
11
|
+
* - Handles code blocks, headers, and lists specially
|
|
12
|
+
* - Merges small chunks to avoid fragmentation
|
|
13
|
+
* - Maintains context through structural boundaries
|
|
14
|
+
*
|
|
15
|
+
* This approach is superior for RAG and embedding applications as it:
|
|
16
|
+
* - Preserves meaning and context better than fixed-size chunking
|
|
17
|
+
* - Avoids splitting related content
|
|
18
|
+
* - Improves retrieval accuracy
|
|
19
|
+
* - Maintains document hierarchy
|
|
20
|
+
*/
|
|
21
|
+
export class SemanticChunkingStrategy implements ChunkingStrategy {
|
|
22
|
+
private encoder: Tiktoken;
|
|
23
|
+
private maxTokens: number;
|
|
24
|
+
private minTokens: number;
|
|
25
|
+
private mergeSmallChunks: boolean;
|
|
26
|
+
|
|
27
|
+
// Document structure patterns
|
|
28
|
+
private static readonly HEADER_PATTERN = /^#{1,6}\s+.+$|^.+\n[=-]{3,}$/gm;
|
|
29
|
+
private static readonly PARAGRAPH_BREAK = /\n\s*\n/g;
|
|
30
|
+
private static readonly CODE_BLOCK = /```[\s\S]*?```/g;
|
|
31
|
+
private static readonly LIST_PATTERN =
|
|
32
|
+
/(?:^|\n)(?:[\s]*[-*+•]\s+.+(?:\n(?![\s]*[-*+•]\s+).+)*)+/gm;
|
|
33
|
+
private static readonly NUMBERED_LIST =
|
|
34
|
+
/(?:^|\n)(?:[\s]*\d+\.\s+.+(?:\n(?![\s]*\d+\.\s+).+)*)+/gm;
|
|
35
|
+
|
|
36
|
+
constructor(options: SemanticChunkingOptions) {
|
|
37
|
+
this.maxTokens = options.maxTokens;
|
|
38
|
+
this.minTokens = options.minTokens ?? 100;
|
|
39
|
+
this.mergeSmallChunks = options.mergeSmallChunks ?? true;
|
|
40
|
+
|
|
41
|
+
// Validate options
|
|
42
|
+
if (this.minTokens >= this.maxTokens) {
|
|
43
|
+
throw new Error("minTokens must be less than maxTokens");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Initialize the tokenizer
|
|
47
|
+
const encodingName = options.encoding || "cl100k_base";
|
|
48
|
+
try {
|
|
49
|
+
this.encoder = get_encoding(encodingName as any);
|
|
50
|
+
} catch {
|
|
51
|
+
this.encoder = encoding_for_model("gpt-3.5-turbo");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Chunks the text based on semantic/structural boundaries
|
|
57
|
+
* @param text - The text to chunk
|
|
58
|
+
* @returns An array of semantically coherent chunks
|
|
59
|
+
*/
|
|
60
|
+
async chunk(text: string): Promise<TextChunk[]> {
|
|
61
|
+
// Parse the document into semantic units
|
|
62
|
+
const semanticUnits = this.parseSemanticUnits(text);
|
|
63
|
+
|
|
64
|
+
// Group semantic units into chunks
|
|
65
|
+
const chunks = this.groupIntoChunks(semanticUnits, text);
|
|
66
|
+
|
|
67
|
+
return chunks;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Parses the document into semantic units (paragraphs, headers, code blocks, lists)
|
|
72
|
+
* @param text - The text to parse
|
|
73
|
+
* @returns Array of semantic units with their positions
|
|
74
|
+
*/
|
|
75
|
+
private parseSemanticUnits(
|
|
76
|
+
text: string,
|
|
77
|
+
): Array<{ content: string; startIndex: number; endIndex: number; type: string }> {
|
|
78
|
+
const units: Array<{ content: string; startIndex: number; endIndex: number; type: string }> =
|
|
79
|
+
[];
|
|
80
|
+
|
|
81
|
+
// Track which parts of text have been processed
|
|
82
|
+
const processed = new Array(text.length).fill(false);
|
|
83
|
+
|
|
84
|
+
// Extract code blocks first (highest priority to avoid splitting)
|
|
85
|
+
const codeBlocks = Array.from(text.matchAll(SemanticChunkingStrategy.CODE_BLOCK));
|
|
86
|
+
for (const match of codeBlocks) {
|
|
87
|
+
const startIndex = match.index!;
|
|
88
|
+
const content = match[0];
|
|
89
|
+
const endIndex = startIndex + content.length;
|
|
90
|
+
|
|
91
|
+
units.push({
|
|
92
|
+
content,
|
|
93
|
+
startIndex,
|
|
94
|
+
endIndex,
|
|
95
|
+
type: "code",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Mark as processed
|
|
99
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
100
|
+
processed[i] = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Extract numbered lists
|
|
105
|
+
const numberedLists = Array.from(text.matchAll(SemanticChunkingStrategy.NUMBERED_LIST));
|
|
106
|
+
for (const match of numberedLists) {
|
|
107
|
+
const startIndex = match.index!;
|
|
108
|
+
const content = match[0];
|
|
109
|
+
const endIndex = startIndex + content.length;
|
|
110
|
+
|
|
111
|
+
// Check if already processed (e.g., in code block)
|
|
112
|
+
if (!processed[startIndex]) {
|
|
113
|
+
units.push({
|
|
114
|
+
content: content.trim(),
|
|
115
|
+
startIndex,
|
|
116
|
+
endIndex,
|
|
117
|
+
type: "numbered_list",
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
121
|
+
processed[i] = true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Extract bullet lists
|
|
127
|
+
const lists = Array.from(text.matchAll(SemanticChunkingStrategy.LIST_PATTERN));
|
|
128
|
+
for (const match of lists) {
|
|
129
|
+
const startIndex = match.index!;
|
|
130
|
+
const content = match[0];
|
|
131
|
+
const endIndex = startIndex + content.length;
|
|
132
|
+
|
|
133
|
+
if (!processed[startIndex]) {
|
|
134
|
+
units.push({
|
|
135
|
+
content: content.trim(),
|
|
136
|
+
startIndex,
|
|
137
|
+
endIndex,
|
|
138
|
+
type: "list",
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
142
|
+
processed[i] = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Split remaining text by paragraphs
|
|
148
|
+
let currentIndex = 0;
|
|
149
|
+
const paragraphs = text.split(SemanticChunkingStrategy.PARAGRAPH_BREAK);
|
|
150
|
+
|
|
151
|
+
for (const paragraph of paragraphs) {
|
|
152
|
+
const startIndex = text.indexOf(paragraph, currentIndex);
|
|
153
|
+
if (startIndex === -1) continue;
|
|
154
|
+
|
|
155
|
+
const endIndex = startIndex + paragraph.length;
|
|
156
|
+
|
|
157
|
+
// Check if this paragraph is already processed
|
|
158
|
+
const alreadyProcessed = processed.slice(startIndex, endIndex).some((p) => p);
|
|
159
|
+
|
|
160
|
+
if (!alreadyProcessed && paragraph.trim().length > 0) {
|
|
161
|
+
// Check if it's a header
|
|
162
|
+
const isHeader = SemanticChunkingStrategy.HEADER_PATTERN.test(paragraph);
|
|
163
|
+
|
|
164
|
+
units.push({
|
|
165
|
+
content: paragraph.trim(),
|
|
166
|
+
startIndex,
|
|
167
|
+
endIndex,
|
|
168
|
+
type: isHeader ? "header" : "paragraph",
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
172
|
+
processed[i] = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
currentIndex = endIndex;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Sort by start index
|
|
180
|
+
return units.sort((a, b) => a.startIndex - b.startIndex);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Groups semantic units into chunks that respect token limits
|
|
185
|
+
* @param units - The semantic units to group
|
|
186
|
+
* @param fullText - The full document text
|
|
187
|
+
* @returns Array of text chunks
|
|
188
|
+
*/
|
|
189
|
+
private groupIntoChunks(
|
|
190
|
+
units: Array<{ content: string; startIndex: number; endIndex: number; type: string }>,
|
|
191
|
+
fullText: string,
|
|
192
|
+
): TextChunk[] {
|
|
193
|
+
const chunks: TextChunk[] = [];
|
|
194
|
+
let currentChunk: string[] = [];
|
|
195
|
+
let currentTokenCount = 0;
|
|
196
|
+
let chunkStartIndex = 0;
|
|
197
|
+
let chunkIndex = 0;
|
|
198
|
+
|
|
199
|
+
for (let i = 0; i < units.length; i++) {
|
|
200
|
+
const unit = units[i];
|
|
201
|
+
const unitTokens = this.encoder.encode(unit.content).length;
|
|
202
|
+
|
|
203
|
+
// If this unit alone exceeds maxTokens, split it
|
|
204
|
+
if (unitTokens > this.maxTokens) {
|
|
205
|
+
// Save current chunk if not empty
|
|
206
|
+
if (currentChunk.length > 0) {
|
|
207
|
+
const chunkContent = currentChunk.join("\n\n");
|
|
208
|
+
chunks.push({
|
|
209
|
+
content: chunkContent,
|
|
210
|
+
startIndex: chunkStartIndex,
|
|
211
|
+
endIndex: chunkStartIndex + chunkContent.length,
|
|
212
|
+
tokenCount: currentTokenCount,
|
|
213
|
+
chunkIndex: chunkIndex++,
|
|
214
|
+
});
|
|
215
|
+
currentChunk = [];
|
|
216
|
+
currentTokenCount = 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Split the large unit
|
|
220
|
+
const subChunks = this.splitLargeUnit(unit, fullText);
|
|
221
|
+
subChunks.forEach((subChunk) => {
|
|
222
|
+
chunks.push({
|
|
223
|
+
...subChunk,
|
|
224
|
+
chunkIndex: chunkIndex++,
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
chunkStartIndex = unit.endIndex;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Check if adding this unit would exceed maxTokens
|
|
233
|
+
if (currentTokenCount + unitTokens > this.maxTokens && currentChunk.length > 0) {
|
|
234
|
+
// Save current chunk
|
|
235
|
+
const chunkContent = currentChunk.join("\n\n");
|
|
236
|
+
chunks.push({
|
|
237
|
+
content: chunkContent,
|
|
238
|
+
startIndex: chunkStartIndex,
|
|
239
|
+
endIndex: chunkStartIndex + chunkContent.length,
|
|
240
|
+
tokenCount: currentTokenCount,
|
|
241
|
+
chunkIndex: chunkIndex++,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Start new chunk
|
|
245
|
+
currentChunk = [unit.content];
|
|
246
|
+
currentTokenCount = unitTokens;
|
|
247
|
+
chunkStartIndex = unit.startIndex;
|
|
248
|
+
} else {
|
|
249
|
+
// Add to current chunk
|
|
250
|
+
if (currentChunk.length === 0) {
|
|
251
|
+
chunkStartIndex = unit.startIndex;
|
|
252
|
+
}
|
|
253
|
+
currentChunk.push(unit.content);
|
|
254
|
+
currentTokenCount += unitTokens;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Add final chunk
|
|
259
|
+
if (currentChunk.length > 0) {
|
|
260
|
+
const chunkContent = currentChunk.join("\n\n");
|
|
261
|
+
chunks.push({
|
|
262
|
+
content: chunkContent,
|
|
263
|
+
startIndex: chunkStartIndex,
|
|
264
|
+
endIndex: chunkStartIndex + chunkContent.length,
|
|
265
|
+
tokenCount: currentTokenCount,
|
|
266
|
+
chunkIndex: chunkIndex++,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Merge small chunks if enabled
|
|
271
|
+
if (this.mergeSmallChunks) {
|
|
272
|
+
return this.mergeSmallChunksInternal(chunks);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return chunks;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Splits a large semantic unit into smaller chunks
|
|
280
|
+
* @param unit - The unit to split
|
|
281
|
+
* @param fullText - The full document text
|
|
282
|
+
* @returns Array of chunks
|
|
283
|
+
*/
|
|
284
|
+
private splitLargeUnit(
|
|
285
|
+
unit: { content: string; startIndex: number; endIndex: number; type: string },
|
|
286
|
+
_fullText: string,
|
|
287
|
+
): Omit<TextChunk, "chunkIndex">[] {
|
|
288
|
+
const chunks: Omit<TextChunk, "chunkIndex">[] = [];
|
|
289
|
+
|
|
290
|
+
// Split by sentences for large units
|
|
291
|
+
const sentences = unit.content.split(/(?<=[.!?])\s+/);
|
|
292
|
+
let currentChunk: string[] = [];
|
|
293
|
+
let currentTokenCount = 0;
|
|
294
|
+
let sentenceStartIndex = unit.startIndex;
|
|
295
|
+
|
|
296
|
+
for (const sentence of sentences) {
|
|
297
|
+
const sentenceTokens = this.encoder.encode(sentence).length;
|
|
298
|
+
|
|
299
|
+
if (currentTokenCount + sentenceTokens > this.maxTokens && currentChunk.length > 0) {
|
|
300
|
+
const chunkContent = currentChunk.join(" ");
|
|
301
|
+
chunks.push({
|
|
302
|
+
content: chunkContent,
|
|
303
|
+
startIndex: sentenceStartIndex,
|
|
304
|
+
endIndex: sentenceStartIndex + chunkContent.length,
|
|
305
|
+
tokenCount: currentTokenCount,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
currentChunk = [sentence];
|
|
309
|
+
currentTokenCount = sentenceTokens;
|
|
310
|
+
sentenceStartIndex += chunkContent.length + 1;
|
|
311
|
+
} else {
|
|
312
|
+
currentChunk.push(sentence);
|
|
313
|
+
currentTokenCount += sentenceTokens;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (currentChunk.length > 0) {
|
|
318
|
+
const chunkContent = currentChunk.join(" ");
|
|
319
|
+
chunks.push({
|
|
320
|
+
content: chunkContent,
|
|
321
|
+
startIndex: sentenceStartIndex,
|
|
322
|
+
endIndex: sentenceStartIndex + chunkContent.length,
|
|
323
|
+
tokenCount: currentTokenCount,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return chunks;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Merges small chunks with adjacent chunks to avoid fragmentation
|
|
332
|
+
* Industry Best Practice: Avoid chunks smaller than minTokens
|
|
333
|
+
*
|
|
334
|
+
* @param chunks - The chunks to merge
|
|
335
|
+
* @returns Merged chunks
|
|
336
|
+
*/
|
|
337
|
+
private mergeSmallChunksInternal(chunks: TextChunk[]): TextChunk[] {
|
|
338
|
+
if (chunks.length <= 1) return chunks;
|
|
339
|
+
|
|
340
|
+
const merged: TextChunk[] = [];
|
|
341
|
+
let i = 0;
|
|
342
|
+
|
|
343
|
+
while (i < chunks.length) {
|
|
344
|
+
const chunk = chunks[i];
|
|
345
|
+
|
|
346
|
+
// If chunk is too small and not the last one, try to merge with next
|
|
347
|
+
if (chunk.tokenCount < this.minTokens && i < chunks.length - 1) {
|
|
348
|
+
const nextChunk = chunks[i + 1];
|
|
349
|
+
const combinedTokenCount = chunk.tokenCount + nextChunk.tokenCount;
|
|
350
|
+
|
|
351
|
+
// Merge if combined size is acceptable
|
|
352
|
+
if (combinedTokenCount <= this.maxTokens) {
|
|
353
|
+
const mergedContent = `${chunk.content}\n\n${nextChunk.content}`;
|
|
354
|
+
merged.push({
|
|
355
|
+
content: mergedContent,
|
|
356
|
+
startIndex: chunk.startIndex,
|
|
357
|
+
endIndex: nextChunk.endIndex,
|
|
358
|
+
tokenCount: combinedTokenCount,
|
|
359
|
+
chunkIndex: merged.length,
|
|
360
|
+
});
|
|
361
|
+
i += 2; // Skip both chunks
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Add chunk as is
|
|
367
|
+
merged.push({
|
|
368
|
+
...chunk,
|
|
369
|
+
chunkIndex: merged.length,
|
|
370
|
+
});
|
|
371
|
+
i++;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return merged;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Cleanup method to free the encoder
|
|
379
|
+
*/
|
|
380
|
+
dispose(): void {
|
|
381
|
+
try {
|
|
382
|
+
if (this.encoder) {
|
|
383
|
+
this.encoder.free();
|
|
384
|
+
}
|
|
385
|
+
} catch {
|
|
386
|
+
// Encoder may have already been freed
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { encoding_for_model, get_encoding, type Tiktoken } from "tiktoken";
|
|
2
|
+
import type { SlidingWindowChunkingOptions, TextChunk } from "../types/index.js";
|
|
3
|
+
import type { ChunkingStrategy } from "./ChunkingStrategy.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sliding window chunking strategy that creates overlapping chunks and respects semantic boundaries
|
|
7
|
+
*
|
|
8
|
+
* Industry Best Practices:
|
|
9
|
+
* - Respects paragraph boundaries (primary)
|
|
10
|
+
* - Respects sentence boundaries (fallback)
|
|
11
|
+
* - Improved sentence detection handling abbreviations, URLs, numbers
|
|
12
|
+
* - Configurable minimum chunk size
|
|
13
|
+
* - Avoids splitting semantic units
|
|
14
|
+
*/
|
|
15
|
+
export class SlidingWindowChunkingStrategy implements ChunkingStrategy {
|
|
16
|
+
private encoder: Tiktoken;
|
|
17
|
+
|
|
18
|
+
// Paragraph boundary patterns (double newline or more)
|
|
19
|
+
private static readonly PARAGRAPH_ENDINGS = /\n\s*\n/g;
|
|
20
|
+
|
|
21
|
+
// Improved sentence boundary patterns that handle edge cases
|
|
22
|
+
// Handles: abbreviations, numbers, URLs, quotes, ellipsis
|
|
23
|
+
private static readonly SENTENCE_ENDINGS =
|
|
24
|
+
/(?<=[.!?])\s+(?=[A-Z])|(?<=[.!?]["'])\s+(?=[A-Z])|(?<=[.!?])\s*$/gm;
|
|
25
|
+
|
|
26
|
+
// Patterns for content that should not be split
|
|
27
|
+
private static readonly CODE_BLOCK = /```[\s\S]*?```|`[^`]+`/g;
|
|
28
|
+
|
|
29
|
+
private minChunkRatio: number;
|
|
30
|
+
private preferParagraphBoundaries: boolean;
|
|
31
|
+
|
|
32
|
+
constructor(private options: SlidingWindowChunkingOptions) {
|
|
33
|
+
// Validate options
|
|
34
|
+
if (options.overlapTokens >= options.maxTokens) {
|
|
35
|
+
throw new Error("overlapTokens must be less than maxTokens");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Set configurable options with defaults
|
|
39
|
+
this.minChunkRatio = options.minChunkRatio ?? 0.5;
|
|
40
|
+
this.preferParagraphBoundaries = options.preferParagraphBoundaries ?? true;
|
|
41
|
+
|
|
42
|
+
// Validate minChunkRatio
|
|
43
|
+
if (this.minChunkRatio < 0.1 || this.minChunkRatio > 0.9) {
|
|
44
|
+
throw new Error("minChunkRatio must be between 0.1 and 0.9");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Initialize the tokenizer with the specified encoding
|
|
48
|
+
const encodingName = options.encoding || "cl100k_base";
|
|
49
|
+
try {
|
|
50
|
+
this.encoder = get_encoding(encodingName as any);
|
|
51
|
+
} catch {
|
|
52
|
+
// Fallback to GPT-3.5/4 encoding
|
|
53
|
+
this.encoder = encoding_for_model("gpt-3.5-turbo");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Chunks the text with sliding window approach and sentence boundary respect
|
|
59
|
+
* @param text - The text to chunk
|
|
60
|
+
* @returns An array of text chunks
|
|
61
|
+
*/
|
|
62
|
+
async chunk(text: string): Promise<TextChunk[]> {
|
|
63
|
+
const chunks: TextChunk[] = [];
|
|
64
|
+
|
|
65
|
+
// Tokenize the entire text
|
|
66
|
+
const tokens = this.encoder.encode(text);
|
|
67
|
+
const maxTokens = this.options.maxTokens;
|
|
68
|
+
const overlapTokens = this.options.overlapTokens;
|
|
69
|
+
const stepSize = maxTokens - overlapTokens;
|
|
70
|
+
|
|
71
|
+
let chunkIndex = 0;
|
|
72
|
+
let currentPosition = 0;
|
|
73
|
+
|
|
74
|
+
while (currentPosition < tokens.length) {
|
|
75
|
+
// Get the chunk tokens
|
|
76
|
+
const chunkEndPosition = Math.min(currentPosition + maxTokens, tokens.length);
|
|
77
|
+
let chunkTokens: Uint32Array = tokens.slice(currentPosition, chunkEndPosition);
|
|
78
|
+
|
|
79
|
+
// Decode to text
|
|
80
|
+
const decoded = this.encoder.decode(chunkTokens);
|
|
81
|
+
let chunkText = typeof decoded === "string" ? decoded : new TextDecoder().decode(decoded);
|
|
82
|
+
|
|
83
|
+
// If this is not the last chunk, adjust to end at sentence boundary
|
|
84
|
+
if (chunkEndPosition < tokens.length) {
|
|
85
|
+
const adjustedChunk = this.adjustToSentenceBoundary(
|
|
86
|
+
chunkText,
|
|
87
|
+
chunkTokens,
|
|
88
|
+
text,
|
|
89
|
+
currentPosition,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (adjustedChunk) {
|
|
93
|
+
chunkText = adjustedChunk.text;
|
|
94
|
+
chunkTokens = adjustedChunk.tokens as Uint32Array;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Calculate character indices
|
|
99
|
+
const startIndex = this.getCharacterIndex(text, tokens, currentPosition);
|
|
100
|
+
const endIndex = startIndex + chunkText.length;
|
|
101
|
+
|
|
102
|
+
chunks.push({
|
|
103
|
+
content: chunkText,
|
|
104
|
+
startIndex,
|
|
105
|
+
endIndex,
|
|
106
|
+
tokenCount: chunkTokens.length,
|
|
107
|
+
chunkIndex: chunkIndex++,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Move to next position with overlap
|
|
111
|
+
if (chunkEndPosition >= tokens.length) {
|
|
112
|
+
break; // We've reached the end
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
currentPosition += stepSize;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return chunks;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Adjusts the chunk to end at a semantic boundary (paragraph or sentence)
|
|
123
|
+
* Industry Best Practice: Prefer paragraph > sentence > word boundaries
|
|
124
|
+
*
|
|
125
|
+
* @param chunkText - The current chunk text
|
|
126
|
+
* @param chunkTokens - The current chunk tokens
|
|
127
|
+
* @param fullText - The full document text
|
|
128
|
+
* @param tokenStartPosition - The starting token position
|
|
129
|
+
* @returns Adjusted chunk or null if no adjustment needed
|
|
130
|
+
*/
|
|
131
|
+
private adjustToSentenceBoundary(
|
|
132
|
+
chunkText: string,
|
|
133
|
+
_chunkTokens: Uint32Array,
|
|
134
|
+
_fullText: string,
|
|
135
|
+
_tokenStartPosition: number,
|
|
136
|
+
): { text: string; tokens: Uint32Array } | null {
|
|
137
|
+
let boundaryPosition: number | null = null;
|
|
138
|
+
|
|
139
|
+
// Try to find a paragraph boundary first (best practice for semantic coherence)
|
|
140
|
+
if (this.preferParagraphBoundaries) {
|
|
141
|
+
boundaryPosition = this.findLastParagraphBoundary(chunkText);
|
|
142
|
+
if (boundaryPosition !== null && this.isValidBoundaryPosition(chunkText, boundaryPosition)) {
|
|
143
|
+
const adjustedText = chunkText.substring(0, boundaryPosition).trim();
|
|
144
|
+
const adjustedTokens = this.encoder.encode(adjustedText);
|
|
145
|
+
return {
|
|
146
|
+
text: adjustedText,
|
|
147
|
+
tokens: adjustedTokens,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Fall back to sentence boundary if no paragraph boundary found
|
|
153
|
+
boundaryPosition = this.findLastSentenceBoundary(chunkText);
|
|
154
|
+
if (boundaryPosition !== null && this.isValidBoundaryPosition(chunkText, boundaryPosition)) {
|
|
155
|
+
const adjustedText = chunkText.substring(0, boundaryPosition).trim();
|
|
156
|
+
const adjustedTokens = this.encoder.encode(adjustedText);
|
|
157
|
+
return {
|
|
158
|
+
text: adjustedText,
|
|
159
|
+
tokens: adjustedTokens,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// No suitable boundary found, return original
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Finds the last paragraph boundary in the text
|
|
169
|
+
* @param text - The text to search
|
|
170
|
+
* @returns The position of the last paragraph boundary, or null if none found
|
|
171
|
+
*/
|
|
172
|
+
private findLastParagraphBoundary(text: string): number | null {
|
|
173
|
+
const matches = Array.from(text.matchAll(SlidingWindowChunkingStrategy.PARAGRAPH_ENDINGS));
|
|
174
|
+
if (matches.length === 0) return null;
|
|
175
|
+
|
|
176
|
+
const lastMatch = matches[matches.length - 1];
|
|
177
|
+
return lastMatch.index! + lastMatch[0].length;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Finds the last sentence boundary in the text
|
|
182
|
+
* Uses improved regex that handles abbreviations, URLs, and other edge cases
|
|
183
|
+
*
|
|
184
|
+
* @param text - The text to search
|
|
185
|
+
* @returns The position of the last sentence boundary, or null if none found
|
|
186
|
+
*/
|
|
187
|
+
private findLastSentenceBoundary(text: string): number | null {
|
|
188
|
+
// Check if we're in the middle of a code block (should not split)
|
|
189
|
+
const codeBlocks = Array.from(text.matchAll(SlidingWindowChunkingStrategy.CODE_BLOCK));
|
|
190
|
+
const inCodeBlock = codeBlocks.some((match) => {
|
|
191
|
+
const matchEnd = match.index! + match[0].length;
|
|
192
|
+
return matchEnd > text.length * 0.8; // Last 20% is in code block
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
if (inCodeBlock) return null;
|
|
196
|
+
|
|
197
|
+
// Find sentence boundaries
|
|
198
|
+
const matches = Array.from(text.matchAll(SlidingWindowChunkingStrategy.SENTENCE_ENDINGS));
|
|
199
|
+
if (matches.length === 0) return null;
|
|
200
|
+
|
|
201
|
+
// Get the last match
|
|
202
|
+
const lastMatch = matches[matches.length - 1];
|
|
203
|
+
return lastMatch.index! + lastMatch[0].length;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Validates if a boundary position results in a chunk of acceptable size
|
|
208
|
+
* Industry Best Practice: Chunks should be at least minChunkRatio of target size
|
|
209
|
+
*
|
|
210
|
+
* @param text - The full chunk text
|
|
211
|
+
* @param boundaryPosition - The proposed boundary position
|
|
212
|
+
* @returns True if the boundary position is valid
|
|
213
|
+
*/
|
|
214
|
+
private isValidBoundaryPosition(text: string, boundaryPosition: number): boolean {
|
|
215
|
+
// Ensure the resulting chunk is not too small
|
|
216
|
+
if (boundaryPosition < text.length * this.minChunkRatio) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Ensure we're not cutting off a tiny amount (less than 10 characters)
|
|
221
|
+
if (text.length - boundaryPosition < 10) {
|
|
222
|
+
return true; // Close enough to the end
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Helper method to get the character index from a token index
|
|
230
|
+
* @param text - The original text
|
|
231
|
+
* @param tokens - All tokens
|
|
232
|
+
* @param tokenIndex - The token index to convert
|
|
233
|
+
* @returns The character index
|
|
234
|
+
*/
|
|
235
|
+
private getCharacterIndex(text: string, tokens: Uint32Array, tokenIndex: number): number {
|
|
236
|
+
if (tokenIndex === 0) return 0;
|
|
237
|
+
|
|
238
|
+
// Decode tokens up to the target index to find character position
|
|
239
|
+
const tokensUpToIndex = tokens.slice(0, tokenIndex);
|
|
240
|
+
const decoded = this.encoder.decode(tokensUpToIndex);
|
|
241
|
+
const decodedUpToIndex =
|
|
242
|
+
typeof decoded === "string" ? decoded : new TextDecoder().decode(decoded);
|
|
243
|
+
return decodedUpToIndex.length;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Cleanup method to free the encoder
|
|
248
|
+
*/
|
|
249
|
+
dispose(): void {
|
|
250
|
+
try {
|
|
251
|
+
if (this.encoder) {
|
|
252
|
+
this.encoder.free();
|
|
253
|
+
}
|
|
254
|
+
} catch {
|
|
255
|
+
// Encoder may have already been freed
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a chunk of text with metadata
|
|
3
|
+
*/
|
|
4
|
+
export interface TextChunk {
|
|
5
|
+
/** The text content of the chunk */
|
|
6
|
+
content: string;
|
|
7
|
+
/** The starting character index in the original document */
|
|
8
|
+
startIndex: number;
|
|
9
|
+
/** The ending character index in the original document */
|
|
10
|
+
endIndex: number;
|
|
11
|
+
/** The token count of the chunk */
|
|
12
|
+
tokenCount: number;
|
|
13
|
+
/** The chunk number (0-indexed) */
|
|
14
|
+
chunkIndex: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Configuration options for fixed length chunking
|
|
19
|
+
*/
|
|
20
|
+
export interface FixedLengthChunkingOptions {
|
|
21
|
+
/** The maximum number of tokens per chunk */
|
|
22
|
+
maxTokens: number;
|
|
23
|
+
/** The encoding to use for token counting (default: 'cl100k_base' for GPT-3.5/4) */
|
|
24
|
+
encoding?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Configuration options for sliding window chunking
|
|
29
|
+
*/
|
|
30
|
+
export interface SlidingWindowChunkingOptions {
|
|
31
|
+
/** The maximum number of tokens per chunk */
|
|
32
|
+
maxTokens: number;
|
|
33
|
+
/** The number of overlapping tokens between chunks */
|
|
34
|
+
overlapTokens: number;
|
|
35
|
+
/** The encoding to use for token counting (default: 'cl100k_base' for GPT-3.5/4) */
|
|
36
|
+
encoding?: string;
|
|
37
|
+
/** Minimum chunk size as a ratio of maxTokens (default: 0.5 = 50%) */
|
|
38
|
+
minChunkRatio?: number;
|
|
39
|
+
/** Prefer paragraph boundaries over sentence boundaries (default: true) */
|
|
40
|
+
preferParagraphBoundaries?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Configuration options for semantic chunking
|
|
45
|
+
*/
|
|
46
|
+
export interface SemanticChunkingOptions {
|
|
47
|
+
/** The maximum number of tokens per chunk */
|
|
48
|
+
maxTokens: number;
|
|
49
|
+
/** The minimum number of tokens per chunk (default: 100) */
|
|
50
|
+
minTokens?: number;
|
|
51
|
+
/** The encoding to use for token counting (default: 'cl100k_base') */
|
|
52
|
+
encoding?: string;
|
|
53
|
+
/** Whether to merge small chunks with adjacent chunks (default: true) */
|
|
54
|
+
mergeSmallChunks?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Union type for all chunking options
|
|
59
|
+
*/
|
|
60
|
+
export type ChunkingOptions =
|
|
61
|
+
| FixedLengthChunkingOptions
|
|
62
|
+
| SlidingWindowChunkingOptions
|
|
63
|
+
| SemanticChunkingOptions;
|