@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.
Files changed (556) hide show
  1. package/CHANGELOG.md +605 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +4 -0
  4. package/README.md +58 -2
  5. package/cli/commands/add.js +537 -0
  6. package/cli/commands/contract.js +2 -0
  7. package/cli/commands/create.js +250 -0
  8. package/cli/commands/dev.js +227 -0
  9. package/cli/commands/doctor.js +286 -0
  10. package/cli/commands/generate.js +937 -0
  11. package/cli/commands/graph.js +2 -0
  12. package/cli/commands/migrate-orm.js +1171 -0
  13. package/cli/commands/update.js +37 -0
  14. package/cli/ship-api.js +285 -0
  15. package/lib/app/auth/AuthProvider.d.ts +91 -0
  16. package/lib/app/auth/AuthProvider.d.ts.map +1 -0
  17. package/lib/app/auth/AuthProvider.js +13 -0
  18. package/lib/app/auth/AuthProvider.js.map +1 -0
  19. package/lib/app/auth/adapters/firebase.d.ts +79 -0
  20. package/lib/app/auth/adapters/firebase.d.ts.map +1 -0
  21. package/lib/app/auth/adapters/firebase.js +122 -0
  22. package/lib/app/auth/adapters/firebase.js.map +1 -0
  23. package/lib/app/auth/adapters/jwtCookie.d.ts +55 -0
  24. package/lib/app/auth/adapters/jwtCookie.d.ts.map +1 -0
  25. package/lib/app/auth/adapters/jwtCookie.js +120 -0
  26. package/lib/app/auth/adapters/jwtCookie.js.map +1 -0
  27. package/lib/app/auth/index.d.ts +8 -0
  28. package/lib/app/auth/index.d.ts.map +1 -0
  29. package/lib/app/auth/index.js +7 -0
  30. package/lib/app/auth/index.js.map +1 -0
  31. package/lib/app/auth/jwt/AuthFlow.d.ts +94 -0
  32. package/lib/app/auth/jwt/AuthFlow.d.ts.map +1 -0
  33. package/lib/app/auth/jwt/AuthFlow.js +127 -0
  34. package/lib/app/auth/jwt/AuthFlow.js.map +1 -0
  35. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts +80 -0
  36. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts.map +1 -0
  37. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js +134 -0
  38. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js.map +1 -0
  39. package/lib/app/auth/jwt/JwtSigner.d.ts +123 -0
  40. package/lib/app/auth/jwt/JwtSigner.d.ts.map +1 -0
  41. package/lib/app/auth/jwt/JwtSigner.js +118 -0
  42. package/lib/app/auth/jwt/JwtSigner.js.map +1 -0
  43. package/lib/app/auth/jwt/RefreshTokenStore.d.ts +97 -0
  44. package/lib/app/auth/jwt/RefreshTokenStore.d.ts.map +1 -0
  45. package/lib/app/auth/jwt/RefreshTokenStore.js +122 -0
  46. package/lib/app/auth/jwt/RefreshTokenStore.js.map +1 -0
  47. package/lib/app/auth/permissionDefinition.d.ts +20 -0
  48. package/lib/app/auth/permissionDefinition.d.ts.map +1 -0
  49. package/lib/app/auth/permissionDefinition.js +2 -0
  50. package/lib/app/auth/permissionDefinition.js.map +1 -0
  51. package/lib/app/context/RequestContext.d.ts +59 -0
  52. package/lib/app/context/RequestContext.d.ts.map +1 -0
  53. package/lib/app/context/RequestContext.js +25 -0
  54. package/lib/app/context/RequestContext.js.map +1 -0
  55. package/lib/app/db/QueryOptions.d.ts +82 -0
  56. package/lib/app/db/QueryOptions.d.ts.map +1 -0
  57. package/lib/app/db/QueryOptions.js +37 -0
  58. package/lib/app/db/QueryOptions.js.map +1 -0
  59. package/lib/app/db/baseFields.d.ts +60 -0
  60. package/lib/app/db/baseFields.d.ts.map +1 -0
  61. package/lib/app/db/baseFields.js +54 -0
  62. package/lib/app/db/baseFields.js.map +1 -0
  63. package/lib/app/db/buildWhere.d.ts +22 -0
  64. package/lib/app/db/buildWhere.d.ts.map +1 -0
  65. package/lib/app/db/buildWhere.js +75 -0
  66. package/lib/app/db/buildWhere.js.map +1 -0
  67. package/lib/app/db/client.d.ts +111 -0
  68. package/lib/app/db/client.d.ts.map +1 -0
  69. package/lib/app/db/client.js +99 -0
  70. package/lib/app/db/client.js.map +1 -0
  71. package/lib/app/db/tenantScoped.d.ts +59 -0
  72. package/lib/app/db/tenantScoped.d.ts.map +1 -0
  73. package/lib/app/db/tenantScoped.js +54 -0
  74. package/lib/app/db/tenantScoped.js.map +1 -0
  75. package/lib/app/db/transaction.d.ts +58 -0
  76. package/lib/app/db/transaction.d.ts.map +1 -0
  77. package/lib/app/db/transaction.js +106 -0
  78. package/lib/app/db/transaction.js.map +1 -0
  79. package/lib/app/health/HealthCheck.d.ts +121 -0
  80. package/lib/app/health/HealthCheck.d.ts.map +1 -0
  81. package/lib/app/health/HealthCheck.js +151 -0
  82. package/lib/app/health/HealthCheck.js.map +1 -0
  83. package/lib/app/health/redisHealthCheck.d.ts +14 -0
  84. package/lib/app/health/redisHealthCheck.d.ts.map +1 -0
  85. package/lib/app/health/redisHealthCheck.js +21 -0
  86. package/lib/app/health/redisHealthCheck.js.map +1 -0
  87. package/lib/app/lifecycle/Bootstrapper.d.ts +92 -0
  88. package/lib/app/lifecycle/Bootstrapper.d.ts.map +1 -0
  89. package/lib/app/lifecycle/Bootstrapper.js +99 -0
  90. package/lib/app/lifecycle/Bootstrapper.js.map +1 -0
  91. package/lib/app/registry/routes.d.ts +89 -0
  92. package/lib/app/registry/routes.d.ts.map +1 -0
  93. package/lib/app/registry/routes.js +72 -0
  94. package/lib/app/registry/routes.js.map +1 -0
  95. package/lib/app/services/DrizzleEntityService.d.ts +123 -0
  96. package/lib/app/services/DrizzleEntityService.d.ts.map +1 -0
  97. package/lib/app/services/DrizzleEntityService.js +342 -0
  98. package/lib/app/services/DrizzleEntityService.js.map +1 -0
  99. package/lib/app/services/RedisProvider.d.ts +52 -0
  100. package/lib/app/services/RedisProvider.d.ts.map +1 -0
  101. package/lib/app/services/RedisProvider.js +75 -0
  102. package/lib/app/services/RedisProvider.js.map +1 -0
  103. package/lib/app/services/cache/Cache.d.ts +70 -0
  104. package/lib/app/services/cache/Cache.d.ts.map +1 -0
  105. package/lib/app/services/cache/Cache.js +18 -0
  106. package/lib/app/services/cache/Cache.js.map +1 -0
  107. package/lib/app/services/cache/InMemoryCache.d.ts +35 -0
  108. package/lib/app/services/cache/InMemoryCache.d.ts.map +1 -0
  109. package/lib/app/services/cache/InMemoryCache.js +76 -0
  110. package/lib/app/services/cache/InMemoryCache.js.map +1 -0
  111. package/lib/app/services/cache/RedisCache.d.ts +99 -0
  112. package/lib/app/services/cache/RedisCache.d.ts.map +1 -0
  113. package/lib/app/services/cache/RedisCache.js +150 -0
  114. package/lib/app/services/cache/RedisCache.js.map +1 -0
  115. package/lib/app/services/cache/cached.d.ts +30 -0
  116. package/lib/app/services/cache/cached.d.ts.map +1 -0
  117. package/lib/app/services/cache/cached.js +38 -0
  118. package/lib/app/services/cache/cached.js.map +1 -0
  119. package/lib/app/services/cache/index.d.ts +5 -0
  120. package/lib/app/services/cache/index.d.ts.map +1 -0
  121. package/lib/app/services/cache/index.js +4 -0
  122. package/lib/app/services/cache/index.js.map +1 -0
  123. package/lib/app/services/cron/defineCron.d.ts +57 -0
  124. package/lib/app/services/cron/defineCron.d.ts.map +1 -0
  125. package/lib/app/services/cron/defineCron.js +15 -0
  126. package/lib/app/services/cron/defineCron.js.map +1 -0
  127. package/lib/app/services/cron/index.d.ts +2 -0
  128. package/lib/app/services/cron/index.d.ts.map +1 -0
  129. package/lib/app/services/cron/index.js +2 -0
  130. package/lib/app/services/cron/index.js.map +1 -0
  131. package/lib/app/services/hooks/LifecycleHooks.d.ts +61 -0
  132. package/lib/app/services/hooks/LifecycleHooks.d.ts.map +1 -0
  133. package/lib/app/services/hooks/LifecycleHooks.js +85 -0
  134. package/lib/app/services/hooks/LifecycleHooks.js.map +1 -0
  135. package/lib/app/services/jobs/JobsManager.d.ts +67 -0
  136. package/lib/app/services/jobs/JobsManager.d.ts.map +1 -0
  137. package/lib/app/services/jobs/JobsManager.js +121 -0
  138. package/lib/app/services/jobs/JobsManager.js.map +1 -0
  139. package/lib/app/services/jobs/bullBoard.d.ts +72 -0
  140. package/lib/app/services/jobs/bullBoard.d.ts.map +1 -0
  141. package/lib/app/services/jobs/bullBoard.js +96 -0
  142. package/lib/app/services/jobs/bullBoard.js.map +1 -0
  143. package/lib/app/services/jobs/defineJob.d.ts +81 -0
  144. package/lib/app/services/jobs/defineJob.d.ts.map +1 -0
  145. package/lib/app/services/jobs/defineJob.js +49 -0
  146. package/lib/app/services/jobs/defineJob.js.map +1 -0
  147. package/lib/app/services/jobs/index.d.ts +4 -0
  148. package/lib/app/services/jobs/index.d.ts.map +1 -0
  149. package/lib/app/services/jobs/index.js +4 -0
  150. package/lib/app/services/jobs/index.js.map +1 -0
  151. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts +23 -0
  152. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts.map +1 -0
  153. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js +51 -0
  154. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js.map +1 -0
  155. package/lib/app/services/rateLimit/RateLimitBackend.d.ts +41 -0
  156. package/lib/app/services/rateLimit/RateLimitBackend.d.ts.map +1 -0
  157. package/lib/app/services/rateLimit/RateLimitBackend.js +19 -0
  158. package/lib/app/services/rateLimit/RateLimitBackend.js.map +1 -0
  159. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts +16 -0
  160. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts.map +1 -0
  161. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js +80 -0
  162. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js.map +1 -0
  163. package/lib/app/services/rateLimit/index.d.ts +4 -0
  164. package/lib/app/services/rateLimit/index.d.ts.map +1 -0
  165. package/lib/app/services/rateLimit/index.js +3 -0
  166. package/lib/app/services/rateLimit/index.js.map +1 -0
  167. package/lib/app/services/storage/DiskStorageAdapter.d.ts +62 -0
  168. package/lib/app/services/storage/DiskStorageAdapter.d.ts.map +1 -0
  169. package/lib/app/services/storage/DiskStorageAdapter.js +295 -0
  170. package/lib/app/services/storage/DiskStorageAdapter.js.map +1 -0
  171. package/lib/app/services/storage/GCSStorageAdapter.d.ts +44 -0
  172. package/lib/app/services/storage/GCSStorageAdapter.d.ts.map +1 -0
  173. package/lib/app/services/storage/GCSStorageAdapter.js +133 -0
  174. package/lib/app/services/storage/GCSStorageAdapter.js.map +1 -0
  175. package/lib/app/services/storage/S3StorageAdapter.d.ts +57 -0
  176. package/lib/app/services/storage/S3StorageAdapter.d.ts.map +1 -0
  177. package/lib/app/services/storage/S3StorageAdapter.js +162 -0
  178. package/lib/app/services/storage/S3StorageAdapter.js.map +1 -0
  179. package/lib/app/services/storage/StorageService.d.ts +88 -0
  180. package/lib/app/services/storage/StorageService.d.ts.map +1 -0
  181. package/lib/app/services/storage/StorageService.js +18 -0
  182. package/lib/app/services/storage/StorageService.js.map +1 -0
  183. package/lib/app/services/storage/index.d.ts +5 -0
  184. package/lib/app/services/storage/index.d.ts.map +1 -0
  185. package/lib/app/services/storage/index.js +4 -0
  186. package/lib/app/services/storage/index.js.map +1 -0
  187. package/lib/app/utils/ContextValidators.d.ts +46 -0
  188. package/lib/app/utils/ContextValidators.d.ts.map +1 -0
  189. package/lib/app/utils/ContextValidators.js +81 -0
  190. package/lib/app/utils/ContextValidators.js.map +1 -0
  191. package/lib/app/utils/defineEnv.d.ts +80 -0
  192. package/lib/app/utils/defineEnv.d.ts.map +1 -0
  193. package/lib/app/utils/defineEnv.js +95 -0
  194. package/lib/app/utils/defineEnv.js.map +1 -0
  195. package/lib/client.d.ts +139 -0
  196. package/lib/client.d.ts.map +1 -0
  197. package/lib/client.js +98 -0
  198. package/lib/client.js.map +1 -0
  199. package/lib/contract/application.d.ts +3 -0
  200. package/lib/contract/application.d.ts.map +1 -0
  201. package/lib/contract/application.js +2 -0
  202. package/lib/contract/application.js.map +1 -0
  203. package/lib/contract/client.d.ts +3 -0
  204. package/lib/contract/client.d.ts.map +1 -0
  205. package/lib/contract/client.js +3 -0
  206. package/lib/contract/client.js.map +1 -0
  207. package/lib/contract/index.d.ts +3 -0
  208. package/lib/contract/index.d.ts.map +1 -0
  209. package/lib/contract/index.js +3 -0
  210. package/lib/contract/index.js.map +1 -0
  211. package/lib/contract/manifest.d.ts +3 -0
  212. package/lib/contract/manifest.d.ts.map +1 -0
  213. package/lib/contract/manifest.js +2 -0
  214. package/lib/contract/manifest.js.map +1 -0
  215. package/lib/contract/openapi.d.ts +3 -0
  216. package/lib/contract/openapi.d.ts.map +1 -0
  217. package/lib/contract/openapi.js +3 -0
  218. package/lib/contract/openapi.js.map +1 -0
  219. package/lib/contract/project.d.ts +3 -0
  220. package/lib/contract/project.d.ts.map +1 -0
  221. package/lib/contract/project.js +3 -0
  222. package/lib/contract/project.js.map +1 -0
  223. package/lib/contract/schema.d.ts +3 -0
  224. package/lib/contract/schema.d.ts.map +1 -0
  225. package/lib/contract/schema.js +3 -0
  226. package/lib/contract/schema.js.map +1 -0
  227. package/lib/drizzle/index.d.ts +3 -0
  228. package/lib/drizzle/index.d.ts.map +1 -0
  229. package/lib/drizzle/index.js +3 -0
  230. package/lib/drizzle/index.js.map +1 -0
  231. package/lib/hono/auth.d.ts +6 -0
  232. package/lib/hono/auth.d.ts.map +1 -0
  233. package/lib/hono/auth.js +54 -0
  234. package/lib/hono/auth.js.map +1 -0
  235. package/lib/hono/index.d.ts +4 -0
  236. package/lib/hono/index.d.ts.map +1 -0
  237. package/lib/hono/index.js +4 -0
  238. package/lib/hono/index.js.map +1 -0
  239. package/lib/http/app/createApp.d.ts +132 -0
  240. package/lib/http/app/createApp.d.ts.map +1 -0
  241. package/lib/http/app/createApp.js +215 -0
  242. package/lib/http/app/createApp.js.map +1 -0
  243. package/lib/http/app/devRoutes.d.ts +31 -0
  244. package/lib/http/app/devRoutes.d.ts.map +1 -0
  245. package/lib/http/app/devRoutes.js +145 -0
  246. package/lib/http/app/devRoutes.js.map +1 -0
  247. package/lib/http/app/errors.d.ts +45 -0
  248. package/lib/http/app/errors.d.ts.map +1 -0
  249. package/lib/http/app/errors.js +93 -0
  250. package/lib/http/app/errors.js.map +1 -0
  251. package/lib/http/app/health.d.ts +66 -0
  252. package/lib/http/app/health.d.ts.map +1 -0
  253. package/lib/http/app/health.js +104 -0
  254. package/lib/http/app/health.js.map +1 -0
  255. package/lib/http/errors/AppError.d.ts +10 -0
  256. package/lib/http/errors/AppError.d.ts.map +1 -0
  257. package/lib/http/errors/AppError.js +19 -0
  258. package/lib/http/errors/AppError.js.map +1 -0
  259. package/lib/http/errors/AuthenticationError.d.ts +8 -0
  260. package/lib/http/errors/AuthenticationError.d.ts.map +1 -0
  261. package/lib/http/errors/AuthenticationError.js +10 -0
  262. package/lib/http/errors/AuthenticationError.js.map +1 -0
  263. package/lib/http/errors/AuthorizationError.d.ts +8 -0
  264. package/lib/http/errors/AuthorizationError.d.ts.map +1 -0
  265. package/lib/http/errors/AuthorizationError.js +10 -0
  266. package/lib/http/errors/AuthorizationError.js.map +1 -0
  267. package/lib/http/errors/BadRequestError.d.ts +8 -0
  268. package/lib/http/errors/BadRequestError.d.ts.map +1 -0
  269. package/lib/http/errors/BadRequestError.js +10 -0
  270. package/lib/http/errors/BadRequestError.js.map +1 -0
  271. package/lib/http/errors/ConflictError.d.ts +8 -0
  272. package/lib/http/errors/ConflictError.d.ts.map +1 -0
  273. package/lib/http/errors/ConflictError.js +10 -0
  274. package/lib/http/errors/ConflictError.js.map +1 -0
  275. package/lib/http/errors/InternalServerError.d.ts +8 -0
  276. package/lib/http/errors/InternalServerError.d.ts.map +1 -0
  277. package/lib/http/errors/InternalServerError.js +10 -0
  278. package/lib/http/errors/InternalServerError.js.map +1 -0
  279. package/lib/http/errors/NotFoundError.d.ts +8 -0
  280. package/lib/http/errors/NotFoundError.d.ts.map +1 -0
  281. package/lib/http/errors/NotFoundError.js +10 -0
  282. package/lib/http/errors/NotFoundError.js.map +1 -0
  283. package/lib/http/errors/RateLimitError.d.ts +13 -0
  284. package/lib/http/errors/RateLimitError.d.ts.map +1 -0
  285. package/lib/http/errors/RateLimitError.js +16 -0
  286. package/lib/http/errors/RateLimitError.js.map +1 -0
  287. package/lib/http/errors/ServiceUnavailableError.d.ts +8 -0
  288. package/lib/http/errors/ServiceUnavailableError.d.ts.map +1 -0
  289. package/lib/http/errors/ServiceUnavailableError.js +10 -0
  290. package/lib/http/errors/ServiceUnavailableError.js.map +1 -0
  291. package/lib/http/errors/ValidationError.d.ts +9 -0
  292. package/lib/http/errors/ValidationError.d.ts.map +1 -0
  293. package/lib/http/errors/ValidationError.js +12 -0
  294. package/lib/http/errors/ValidationError.js.map +1 -0
  295. package/lib/http/errors/index.d.ts +11 -0
  296. package/lib/http/errors/index.d.ts.map +1 -0
  297. package/lib/http/errors/index.js +12 -0
  298. package/lib/http/errors/index.js.map +1 -0
  299. package/lib/http/middleware/apiKey.d.ts +9 -0
  300. package/lib/http/middleware/apiKey.d.ts.map +1 -0
  301. package/lib/http/middleware/apiKey.js +71 -0
  302. package/lib/http/middleware/apiKey.js.map +1 -0
  303. package/lib/http/middleware/csrf.d.ts +63 -0
  304. package/lib/http/middleware/csrf.d.ts.map +1 -0
  305. package/lib/http/middleware/csrf.js +169 -0
  306. package/lib/http/middleware/csrf.js.map +1 -0
  307. package/lib/http/middleware/httpLogger.d.ts +39 -0
  308. package/lib/http/middleware/httpLogger.d.ts.map +1 -0
  309. package/lib/http/middleware/httpLogger.js +118 -0
  310. package/lib/http/middleware/httpLogger.js.map +1 -0
  311. package/lib/http/middleware/idempotency.d.ts +48 -0
  312. package/lib/http/middleware/idempotency.d.ts.map +1 -0
  313. package/lib/http/middleware/idempotency.js +180 -0
  314. package/lib/http/middleware/idempotency.js.map +1 -0
  315. package/lib/http/middleware/rateLimit.d.ts +105 -0
  316. package/lib/http/middleware/rateLimit.d.ts.map +1 -0
  317. package/lib/http/middleware/rateLimit.js +84 -0
  318. package/lib/http/middleware/rateLimit.js.map +1 -0
  319. package/lib/http/middleware/requireAuth.d.ts +58 -0
  320. package/lib/http/middleware/requireAuth.d.ts.map +1 -0
  321. package/lib/http/middleware/requireAuth.js +63 -0
  322. package/lib/http/middleware/requireAuth.js.map +1 -0
  323. package/lib/http/middleware/requirePermission.d.ts +23 -0
  324. package/lib/http/middleware/requirePermission.d.ts.map +1 -0
  325. package/lib/http/middleware/requirePermission.js +50 -0
  326. package/lib/http/middleware/requirePermission.js.map +1 -0
  327. package/lib/http/middleware/resolveTenant.d.ts +41 -0
  328. package/lib/http/middleware/resolveTenant.d.ts.map +1 -0
  329. package/lib/http/middleware/resolveTenant.js +17 -0
  330. package/lib/http/middleware/resolveTenant.js.map +1 -0
  331. package/lib/http/streaming/sse.d.ts +31 -0
  332. package/lib/http/streaming/sse.d.ts.map +1 -0
  333. package/lib/http/streaming/sse.js +11 -0
  334. package/lib/http/streaming/sse.js.map +1 -0
  335. package/lib/http/streaming/streamLLM.d.ts +94 -0
  336. package/lib/http/streaming/streamLLM.d.ts.map +1 -0
  337. package/lib/http/streaming/streamLLM.js +94 -0
  338. package/lib/http/streaming/streamLLM.js.map +1 -0
  339. package/lib/http/utils/authCookies.d.ts +74 -0
  340. package/lib/http/utils/authCookies.d.ts.map +1 -0
  341. package/lib/http/utils/authCookies.js +102 -0
  342. package/lib/http/utils/authCookies.js.map +1 -0
  343. package/lib/http/utils/clientIp.d.ts +85 -0
  344. package/lib/http/utils/clientIp.d.ts.map +1 -0
  345. package/lib/http/utils/clientIp.js +249 -0
  346. package/lib/http/utils/clientIp.js.map +1 -0
  347. package/lib/http/utils/index.d.ts +4 -0
  348. package/lib/http/utils/index.d.ts.map +1 -0
  349. package/lib/http/utils/index.js +5 -0
  350. package/lib/http/utils/index.js.map +1 -0
  351. package/lib/http/utils/metaTags.d.ts +49 -0
  352. package/lib/http/utils/metaTags.d.ts.map +1 -0
  353. package/lib/http/utils/metaTags.js +32 -0
  354. package/lib/http/utils/metaTags.js.map +1 -0
  355. package/lib/http/utils/publicSuffix.d.ts +34 -0
  356. package/lib/http/utils/publicSuffix.d.ts.map +1 -0
  357. package/lib/http/utils/publicSuffix.js +276 -0
  358. package/lib/http/utils/publicSuffix.js.map +1 -0
  359. package/lib/http/utils/uploads.d.ts +92 -0
  360. package/lib/http/utils/uploads.d.ts.map +1 -0
  361. package/lib/http/utils/uploads.js +126 -0
  362. package/lib/http/utils/uploads.js.map +1 -0
  363. package/lib/http/utils/validate.d.ts +41 -0
  364. package/lib/http/utils/validate.d.ts.map +1 -0
  365. package/lib/http/utils/validate.js +55 -0
  366. package/lib/http/utils/validate.js.map +1 -0
  367. package/lib/http/utils/webhooks.d.ts +63 -0
  368. package/lib/http/utils/webhooks.d.ts.map +1 -0
  369. package/lib/http/utils/webhooks.js +133 -0
  370. package/lib/http/utils/webhooks.js.map +1 -0
  371. package/lib/http/ws/auth.d.ts +46 -0
  372. package/lib/http/ws/auth.d.ts.map +1 -0
  373. package/lib/http/ws/auth.js +123 -0
  374. package/lib/http/ws/auth.js.map +1 -0
  375. package/lib/index.d.ts +80 -0
  376. package/lib/index.d.ts.map +1 -0
  377. package/lib/index.js +61 -0
  378. package/lib/index.js.map +1 -0
  379. package/lib/kernel/index.d.ts +3 -0
  380. package/lib/kernel/index.d.ts.map +1 -0
  381. package/lib/kernel/index.js +3 -0
  382. package/lib/kernel/index.js.map +1 -0
  383. package/lib/libraries/.gitkeep +0 -0
  384. package/lib/libraries/ai/CHANGELOG.md +17 -0
  385. package/lib/libraries/ai/README.md +164 -0
  386. package/lib/libraries/ai/adapters/AnthropicAdapter.ts +382 -0
  387. package/lib/libraries/ai/adapters/LLMProvider.ts +76 -0
  388. package/lib/libraries/ai/adapters/OpenAIAdapter.ts +466 -0
  389. package/lib/libraries/ai/experimental/index.ts +20 -0
  390. package/lib/libraries/ai/index.ts +128 -0
  391. package/lib/libraries/ai/library.json +19 -0
  392. package/lib/libraries/ai/loop/agentLoop.ts +377 -0
  393. package/lib/libraries/ai/prompts/definePrompt.ts +0 -0
  394. package/lib/libraries/ai/rag/retrieveAndAnswer.ts +177 -0
  395. package/lib/libraries/ai/streaming/streamLLM.ts +94 -0
  396. package/lib/libraries/ai/structured/completeStructured.ts +143 -0
  397. package/lib/libraries/ai/tokens/Tokenizer.ts +216 -0
  398. package/lib/libraries/ai/tools/defineTool.ts +208 -0
  399. package/lib/libraries/ai/types.ts +260 -0
  400. package/lib/libraries/chunking/ChunkingService.ts +103 -0
  401. package/lib/libraries/chunking/README.md +104 -0
  402. package/lib/libraries/chunking/docs/api-reference.md +549 -0
  403. package/lib/libraries/chunking/docs/best-practices.md +321 -0
  404. package/lib/libraries/chunking/docs/code-organization.md +538 -0
  405. package/lib/libraries/chunking/docs/configuration.md +418 -0
  406. package/lib/libraries/chunking/docs/index.md +236 -0
  407. package/lib/libraries/chunking/docs/quick-start.md +298 -0
  408. package/lib/libraries/chunking/docs/strategies.md +407 -0
  409. package/lib/libraries/chunking/docs/summary.md +258 -0
  410. package/lib/libraries/chunking/docs/troubleshooting.md +527 -0
  411. package/lib/libraries/chunking/index.ts +17 -0
  412. package/lib/libraries/chunking/library.json +16 -0
  413. package/lib/libraries/chunking/strategies/ChunkingStrategy.ts +13 -0
  414. package/lib/libraries/chunking/strategies/FixedLengthChunkingStrategy.ts +88 -0
  415. package/lib/libraries/chunking/strategies/SemanticChunkingStrategy.ts +389 -0
  416. package/lib/libraries/chunking/strategies/SlidingWindowChunkingStrategy.ts +258 -0
  417. package/lib/libraries/chunking/types/index.ts +63 -0
  418. package/lib/libraries/email/EmailService.ts +591 -0
  419. package/lib/libraries/email/README.md +777 -0
  420. package/lib/libraries/email/TemplateRegistry.ts +148 -0
  421. package/lib/libraries/email/TemplateRenderer.ts +273 -0
  422. package/lib/libraries/email/index.ts +4 -0
  423. package/lib/libraries/email/initializeEmailService.ts +60 -0
  424. package/lib/libraries/email/library.json +12 -0
  425. package/lib/libraries/email/types/EmailAddress.ts +4 -0
  426. package/lib/libraries/email/types/EmailAttachment.ts +11 -0
  427. package/lib/libraries/email/types/EmailTag.ts +9 -0
  428. package/lib/libraries/email/types/EmailTemplate.ts +124 -0
  429. package/lib/libraries/email/types/SendBatchEmailsOptions.ts +9 -0
  430. package/lib/libraries/email/types/SendBatchEmailsResult.ts +9 -0
  431. package/lib/libraries/email/types/SendEmailOptions.ts +33 -0
  432. package/lib/libraries/email/types/SendEmailResult.ts +9 -0
  433. package/lib/libraries/email/types/index.ts +8 -0
  434. package/lib/libraries/weaviate/QueryBuilder.ts +292 -0
  435. package/lib/libraries/weaviate/README.md +284 -0
  436. package/lib/libraries/weaviate/Weaviate.ts +1419 -0
  437. package/lib/libraries/weaviate/WeaviateConfig.ts +268 -0
  438. package/lib/libraries/weaviate/docs/.gitkeep +1 -0
  439. package/lib/libraries/weaviate/docs/API_REFERENCE.md +1067 -0
  440. package/lib/libraries/weaviate/docs/CONFIGURATION.md +320 -0
  441. package/lib/libraries/weaviate/docs/ERROR_HANDLING.md +271 -0
  442. package/lib/libraries/weaviate/docs/MULTI_TENANCY.md +348 -0
  443. package/lib/libraries/weaviate/docs/PERFORMANCE.md +602 -0
  444. package/lib/libraries/weaviate/docs/PLUGIN_DEVELOPMENT.md +547 -0
  445. package/lib/libraries/weaviate/docs/QUICK_START.md +443 -0
  446. package/lib/libraries/weaviate/docs/README.md +269 -0
  447. package/lib/libraries/weaviate/docs/SCHEMA_GUIDE.md +630 -0
  448. package/lib/libraries/weaviate/docs/WEAVIATE_README.md +520 -0
  449. package/lib/libraries/weaviate/errors/WeaviateError.ts +92 -0
  450. package/lib/libraries/weaviate/errors/index.ts +1 -0
  451. package/lib/libraries/weaviate/index.ts +35 -0
  452. package/lib/libraries/weaviate/library.json +26 -0
  453. package/lib/libraries/weaviate/plugins/index.ts +2 -0
  454. package/lib/libraries/weaviate/schemas/SchemaRegistry.ts +284 -0
  455. package/lib/libraries/weaviate/schemas/index.ts +2 -0
  456. package/lib/libraries/weaviate/types/BM25SearchOptions.ts +9 -0
  457. package/lib/libraries/weaviate/types/ExtendedWeaviateClient.ts +7 -0
  458. package/lib/libraries/weaviate/types/HybridSearchOptions.ts +11 -0
  459. package/lib/libraries/weaviate/types/MultiTenancy.ts +81 -0
  460. package/lib/libraries/weaviate/types/Plugin.ts +17 -0
  461. package/lib/libraries/weaviate/types/SchemaConfig.ts +25 -0
  462. package/lib/libraries/weaviate/types/SearchMethod.ts +8 -0
  463. package/lib/libraries/weaviate/types/SearchOptions.ts +16 -0
  464. package/lib/libraries/weaviate/types/SearchRequest.ts +19 -0
  465. package/lib/libraries/weaviate/types/SearchResult.ts +16 -0
  466. package/lib/libraries/weaviate/types/SearchableField.ts +87 -0
  467. package/lib/libraries/weaviate/types/VectorIndexConfig.ts +19 -0
  468. package/lib/libraries/weaviate/types/VectorSearchOptions.ts +18 -0
  469. package/lib/libraries/weaviate/types/VectorizerConfig.ts +8 -0
  470. package/lib/libraries/weaviate/types/index.ts +29 -0
  471. package/lib/libraries/weaviate/utils/TenantContextManager.ts +94 -0
  472. package/lib/modules/accounts/index.ts +47 -0
  473. package/lib/modules/accounts/module.json +15 -0
  474. package/lib/modules/accounts/permissions.ts +33 -0
  475. package/lib/modules/accounts/routes.ts +200 -0
  476. package/lib/modules/accounts/schema.ts +219 -0
  477. package/lib/modules/accounts/services/AccountService.ts +44 -0
  478. package/lib/modules/accounts/validation/schemas.ts +70 -0
  479. package/lib/modules/oauth/adapters/GmailOAuthAdapter.ts +35 -0
  480. package/lib/modules/oauth/adapters/GoogleOAuthAdapter.ts +278 -0
  481. package/lib/modules/oauth/adapters/MicrosoftOAuthAdapter.ts +269 -0
  482. package/lib/modules/oauth/adapters/MockOAuthAdapter.ts +138 -0
  483. package/lib/modules/oauth/adapters/OAuthAdapter.ts +211 -0
  484. package/lib/modules/oauth/adapters/OAuthAdapterRegistry.ts +77 -0
  485. package/lib/modules/oauth/adapters/OutlookOAuthAdapter.ts +38 -0
  486. package/lib/modules/oauth/index.ts +79 -0
  487. package/lib/modules/oauth/module.json +23 -0
  488. package/lib/modules/oauth/permissions.ts +39 -0
  489. package/lib/modules/oauth/routes.ts +497 -0
  490. package/lib/modules/oauth/schema.ts +127 -0
  491. package/lib/modules/oauth/services/OAuthConnectionService.ts +147 -0
  492. package/lib/modules/oauth/state.ts +234 -0
  493. package/lib/modules/oauth/stateJtiCache.ts +85 -0
  494. package/lib/modules/oauth/verifyIdToken.ts +178 -0
  495. package/lib/modules/outbox/EventEmitter.ts +106 -0
  496. package/lib/modules/outbox/OutboxDrainer.ts +163 -0
  497. package/lib/modules/outbox/handlers/EventHandler.ts +115 -0
  498. package/lib/modules/outbox/index.ts +43 -0
  499. package/lib/modules/outbox/module.json +15 -0
  500. package/lib/modules/outbox/permissions.ts +36 -0
  501. package/lib/modules/outbox/routes.ts +219 -0
  502. package/lib/modules/outbox/schema.ts +207 -0
  503. package/lib/modules/outbox/services/OutboxEventService.ts +223 -0
  504. package/lib/observability/logger.d.ts +30 -0
  505. package/lib/observability/logger.d.ts.map +1 -0
  506. package/lib/observability/logger.js +110 -0
  507. package/lib/observability/logger.js.map +1 -0
  508. package/lib/observability/metrics.d.ts +3 -0
  509. package/lib/observability/metrics.d.ts.map +1 -0
  510. package/lib/observability/metrics.js +3 -0
  511. package/lib/observability/metrics.js.map +1 -0
  512. package/lib/observability/otel.d.ts +3 -0
  513. package/lib/observability/otel.d.ts.map +1 -0
  514. package/lib/observability/otel.js +3 -0
  515. package/lib/observability/otel.js.map +1 -0
  516. package/lib/observability/safeErrorFields.d.ts +14 -0
  517. package/lib/observability/safeErrorFields.d.ts.map +1 -0
  518. package/lib/observability/safeErrorFields.js +14 -0
  519. package/lib/observability/safeErrorFields.js.map +1 -0
  520. package/lib/observability/tracing.d.ts +3 -0
  521. package/lib/observability/tracing.d.ts.map +1 -0
  522. package/lib/observability/tracing.js +3 -0
  523. package/lib/observability/tracing.js.map +1 -0
  524. package/lib/package.json +4 -0
  525. package/lib/testing.d.ts +3 -0
  526. package/lib/testing.d.ts.map +1 -0
  527. package/lib/testing.js +3 -0
  528. package/lib/testing.js.map +1 -0
  529. package/package.json +193 -3
  530. package/templates/default/.claude/agents/qa-brief.md +106 -0
  531. package/templates/default/.claude/commands/sherpa-brief.md +23 -0
  532. package/templates/default/.cursor/rules/api.mdc +80 -0
  533. package/templates/default/.cursor/rules/commits.mdc +88 -0
  534. package/templates/default/.cursor/rules/security.mdc +92 -0
  535. package/templates/default/.cursor/rules/testing.mdc +123 -0
  536. package/templates/default/.cursor/rules/typescript.mdc +86 -0
  537. package/templates/default/.env.example +79 -0
  538. package/templates/default/.github/workflows/sherpa-brief.yml +180 -0
  539. package/templates/default/AGENTS.md +166 -0
  540. package/templates/default/CLAUDE.md +17 -0
  541. package/templates/default/README.md +97 -0
  542. package/templates/default/_gitignore +27 -0
  543. package/templates/default/docker-compose.yml +83 -0
  544. package/templates/default/drizzle.config.ts +34 -0
  545. package/templates/default/eslint.config.mjs +106 -0
  546. package/templates/default/package.json +57 -0
  547. package/templates/default/ship-api.config.ts +21 -0
  548. package/templates/default/src/client.ts +34 -0
  549. package/templates/default/src/config/modules.ts +23 -0
  550. package/templates/default/src/db/schema.ts +26 -0
  551. package/templates/default/src/environment.ts +81 -0
  552. package/templates/default/src/index.test.ts +53 -0
  553. package/templates/default/src/index.ts +11 -0
  554. package/templates/default/src/instrumentation.ts +13 -0
  555. package/templates/default/src/server.ts +90 -0
  556. package/templates/default/tsconfig.json +24 -0
@@ -0,0 +1,1419 @@
1
+ import Logger from "@sixthsummit/ship-api/app/utils/Logger";
2
+ import { WeaviateError, WeaviateErrorCode } from "./errors/index.js";
3
+ import { createQueryBuilder, type QueryBuilder, QueryPatterns } from "./QueryBuilder.js";
4
+ import SchemaRegistry from "./schemas/SchemaRegistry.js";
5
+ import type {
6
+ BM25SearchOptions,
7
+ CreateTenantOptions,
8
+ ExtendedWeaviateClient,
9
+ HybridSearchOptions,
10
+ Plugin,
11
+ SchemaConfig,
12
+ SearchableField,
13
+ SearchOptions,
14
+ SearchRequest,
15
+ SearchResult,
16
+ Tenant,
17
+ TenantManagementResult,
18
+ TenantStats,
19
+ UpdateTenantOptions,
20
+ Vectorizer,
21
+ VectorSearchOptions,
22
+ } from "./types/index.js";
23
+ import TenantContextManager from "./utils/TenantContextManager.js";
24
+ import { WeaviateConfigService } from "./WeaviateConfig.js";
25
+
26
+ /**
27
+ * Options for initializing a Weaviate instance
28
+ */
29
+ export interface WeaviateOptions {
30
+ /** Optional schema registry to use. If not provided, a new one will be created. */
31
+ registry?: SchemaRegistry;
32
+ /** Optional custom plugins to register. */
33
+ plugins?: Plugin[];
34
+ }
35
+
36
+ /**
37
+ * Main Weaviate class for vector database operations
38
+ */
39
+ export default class Weaviate {
40
+ private client: ExtendedWeaviateClient | null = null;
41
+ private readonly registry: SchemaRegistry;
42
+ private readonly defaultLimit = 25;
43
+
44
+ /**
45
+ * Create a new Weaviate instance
46
+ * Client will be lazily initialized on first use
47
+ * @param options - Optional configuration for the instance
48
+ * @example
49
+ * // Simple usage
50
+ * const weaviate = new Weaviate();
51
+ *
52
+ * // With custom plugins
53
+ * const weaviate = new Weaviate({
54
+ * plugins: [new MyCustomPlugin()]
55
+ * });
56
+ *
57
+ * // For testing with mock registry
58
+ * const mockRegistry = new SchemaRegistry();
59
+ * const weaviate = new Weaviate({ registry: mockRegistry });
60
+ */
61
+ constructor(options: WeaviateOptions = {}) {
62
+ // Use provided registry or create new one
63
+ this.registry = options.registry || new SchemaRegistry();
64
+
65
+ // Register custom plugins if provided
66
+ if (options.plugins) {
67
+ options.plugins.forEach((plugin) => {
68
+ this.registry.registerPlugin(plugin);
69
+ });
70
+ Logger.log(`Weaviate initialized with ${options.plugins.length} custom plugin(s)`);
71
+ }
72
+
73
+ Logger.log("Weaviate instance created (client will be initialized on first use)");
74
+ }
75
+
76
+ /**
77
+ * Get the Weaviate client, lazily initializing if needed
78
+ * @private
79
+ */
80
+ private async getClient(skipHealthCheck = false): Promise<ExtendedWeaviateClient> {
81
+ if (!this.client) {
82
+ this.client = (await WeaviateConfigService.getClient(
83
+ skipHealthCheck,
84
+ )) as ExtendedWeaviateClient;
85
+ }
86
+ return this.client;
87
+ }
88
+
89
+ /**
90
+ * Reset the client connection (useful after connection errors)
91
+ * Next getClient() call will re-establish the connection
92
+ */
93
+ resetClient(): void {
94
+ this.client = null;
95
+ }
96
+
97
+ /**
98
+ * Initialize Weaviate schemas (call this during app startup)
99
+ *
100
+ * This method registers the schemas in the registry and creates them in Weaviate.
101
+ *
102
+ * @param schemas - Array of schema configurations to initialize
103
+ * @example
104
+ * const schemas = [PersonSchema, OrganizationSchema];
105
+ * await weaviate.initializeSchemas(schemas);
106
+ */
107
+ async initializeSchemas(schemas: SchemaConfig[]): Promise<void> {
108
+ try {
109
+ Logger.log("Initializing schemas...");
110
+
111
+ // Register schemas in the registry
112
+ schemas.forEach((schema) => {
113
+ this.registry.registerSchema(schema);
114
+ });
115
+
116
+ // Create schemas in Weaviate database
117
+ for (const schema of schemas) {
118
+ await this.createSchema(schema);
119
+ }
120
+
121
+ Logger.log(`Initialized ${schemas.length} schemas successfully`);
122
+ } catch (error) {
123
+ Logger.log("Error initializing schemas:", error);
124
+ throw WeaviateError.from(
125
+ error,
126
+ WeaviateErrorCode.SCHEMA_CREATION_ERROR,
127
+ "Failed to initialize schemas",
128
+ );
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Create a schema in Weaviate
134
+ * Note: Schema validation happens in SchemaRegistry.registerSchema (fail-fast principle)
135
+ */
136
+ async createSchema(schema: SchemaConfig): Promise<void> {
137
+ try {
138
+ // Convert to Weaviate format
139
+ const weaviateSchema = this.convertToWeaviateSchema(schema);
140
+
141
+ const client = await this.getClient();
142
+ await client.collections.createFromSchema(weaviateSchema);
143
+ Logger.log(`Schema created for class: ${schema.name}`);
144
+ } catch (error) {
145
+ if (error.message?.includes("already exists")) {
146
+ Logger.log(`Schema for class ${schema.name} already exists`);
147
+ } else {
148
+ throw error;
149
+ }
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Add a property to an existing schema/collection
155
+ *
156
+ * Use this for schema migrations when you need to add new fields
157
+ * without recreating the entire collection.
158
+ *
159
+ * @param collectionName - Name of the collection (e.g., "Person")
160
+ * @param property - Property configuration matching SearchableField interface
161
+ * @throws Error if the property already exists or collection not found
162
+ *
163
+ * @example
164
+ * await weaviate.addProperty("Person", {
165
+ * name: "networkUserIds",
166
+ * dataType: ["text[]"],
167
+ * description: "User IDs who have this person in their network",
168
+ * indexInverted: true,
169
+ * });
170
+ */
171
+ async addProperty(collectionName: string, property: SearchableField): Promise<void> {
172
+ try {
173
+ const client = await this.getClient();
174
+ const collection = client.collections.get(collectionName);
175
+
176
+ // Convert SearchableField to Weaviate v3 property format
177
+ // Note: collection.config.addProperty expects dataType as a single string, not an array
178
+ // e.g., "text[]" not ["text[]"]
179
+ const dataType = Array.isArray(property.dataType) ? property.dataType[0] : property.dataType;
180
+
181
+ const weaviateProperty: Record<string, unknown> = {
182
+ name: property.name,
183
+ dataType,
184
+ description: property.description,
185
+ // Index settings - v4 uses indexFilterable/indexSearchable
186
+ // indexInverted is legacy but may still be accepted by some versions
187
+ indexFilterable: property.indexFilterable ?? property.indexInverted ?? true,
188
+ indexSearchable: property.indexSearchable ?? false,
189
+ };
190
+
191
+ if (property.tokenization !== undefined) {
192
+ weaviateProperty.tokenization = property.tokenization;
193
+ }
194
+
195
+ await collection.config.addProperty(weaviateProperty as any);
196
+ Logger.log(`Property '${property.name}' added to collection '${collectionName}'`);
197
+ } catch (error: any) {
198
+ if (error.message?.includes("already exists")) {
199
+ Logger.log(`Property '${property.name}' already exists in '${collectionName}'`);
200
+ throw error;
201
+ }
202
+ Logger.log(`Error adding property '${property.name}' to '${collectionName}':`, error);
203
+ throw WeaviateError.from(
204
+ error,
205
+ WeaviateErrorCode.SCHEMA_CREATION_ERROR,
206
+ `Failed to add property '${property.name}' to collection '${collectionName}'`,
207
+ );
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Type guard to check if vectorizer is a string ("none")
213
+ */
214
+ private isStringVectorizer(vectorizer: Vectorizer | undefined): vectorizer is "none" {
215
+ return typeof vectorizer === "string";
216
+ }
217
+
218
+ /**
219
+ * Convert schema config to Weaviate format
220
+ */
221
+ private convertToWeaviateSchema(schema: SchemaConfig): any {
222
+ const weaviateSchema: any = {
223
+ class: schema.name,
224
+ description: schema.description,
225
+ vectorizer: this.isStringVectorizer(schema.vectorizer)
226
+ ? schema.vectorizer
227
+ : schema.vectorizer?.name,
228
+ vectorIndexConfig: schema.vectorIndexConfig,
229
+ properties: schema.properties.map((prop) => ({
230
+ name: prop.name,
231
+ dataType: prop.dataType,
232
+ description: prop.description,
233
+ indexInverted: prop.indexInverted,
234
+ indexFilterable: prop.indexFilterable,
235
+ indexSearchable: prop.indexSearchable,
236
+ })),
237
+ };
238
+
239
+ // Add multi-tenancy configuration if enabled
240
+ if (schema.multiTenancy?.enabled) {
241
+ weaviateSchema.multiTenancyConfig = {
242
+ enabled: true,
243
+ autoTenantCreation: schema.multiTenancy.autoTenantCreation ?? true,
244
+ autoTenantActivation: schema.multiTenancy.autoTenantActivation ?? true,
245
+ };
246
+ }
247
+
248
+ return weaviateSchema;
249
+ }
250
+
251
+ // ==================== SEARCH METHODS ====================
252
+
253
+ /**
254
+ * Generic search method with type-safe discriminated union
255
+ *
256
+ * @param schemaName - Name of the schema to search
257
+ * @param request - Search request with method and options
258
+ * @returns Search results with matching objects
259
+ * @example
260
+ * // Vector search
261
+ * const results = await weaviate.search('Person', {
262
+ * method: 'vector',
263
+ * options: { nearText: { concepts: ['engineer'] }, limit: 10 }
264
+ * });
265
+ *
266
+ * // BM25 search
267
+ * const results = await weaviate.search('Person', {
268
+ * method: 'bm25',
269
+ * options: { bm25: { query: 'John Smith' }, limit: 10 }
270
+ * });
271
+ *
272
+ * // Hybrid search
273
+ * const results = await weaviate.search('Person', {
274
+ * method: 'hybrid',
275
+ * options: { hybrid: { query: 'engineer', alpha: 0.5 }, limit: 10 }
276
+ * });
277
+ */
278
+ async search<T = any>(schemaName: string, request: SearchRequest): Promise<SearchResult<T>> {
279
+ try {
280
+ // Validate schema exists
281
+ if (!this.registry.hasSchema(schemaName)) {
282
+ throw new Error(`Schema '${schemaName}' not found in registry`);
283
+ }
284
+
285
+ // Get schema plugins
286
+ const plugins = this.registry.getSchemaPlugins(schemaName);
287
+
288
+ // Apply beforeSearch hooks
289
+ let processedOptions = request.options;
290
+ for (const plugin of plugins) {
291
+ if (plugin.hooks.beforeSearch) {
292
+ processedOptions = plugin.hooks.beforeSearch(schemaName, processedOptions);
293
+ }
294
+ }
295
+
296
+ // Execute search based on method (TypeScript properly narrows types here)
297
+ let result: SearchResult<T>;
298
+ switch (request.method) {
299
+ case "vector":
300
+ result = await this.executeVectorSearch(schemaName, processedOptions);
301
+ break;
302
+ case "bm25":
303
+ result = await this.executeBM25Search(schemaName, processedOptions);
304
+ break;
305
+ case "hybrid":
306
+ result = await this.executeHybridSearch(schemaName, processedOptions);
307
+ break;
308
+ default:
309
+ // Exhaustiveness check - TypeScript ensures all methods are handled
310
+ throw new Error(`Unsupported search method`);
311
+ }
312
+
313
+ // Apply afterSearch hooks
314
+ for (const plugin of plugins) {
315
+ if (plugin.hooks.afterSearch) {
316
+ result = plugin.hooks.afterSearch(schemaName, result);
317
+ }
318
+ }
319
+
320
+ return result;
321
+ } catch (error) {
322
+ Logger.log(`Error searching ${schemaName} with ${request.method}:`, error);
323
+ throw WeaviateError.from(
324
+ error,
325
+ WeaviateErrorCode.SEARCH_ERROR,
326
+ `Failed to search ${schemaName} with method ${request.method}`,
327
+ );
328
+ }
329
+ }
330
+
331
+ /**
332
+ * Check if filter object is a plain object (our format) that needs conversion
333
+ *
334
+ * @param obj - Filter object to check
335
+ * @returns true if plain object, false if already a FilterValue
336
+ */
337
+ private isPlainFilterObject(obj: any): boolean {
338
+ return (
339
+ obj &&
340
+ typeof obj === "object" &&
341
+ Object.hasOwn(obj, "path") &&
342
+ Object.hasOwn(obj, "operator") &&
343
+ Object.hasOwn(obj, "valueString")
344
+ );
345
+ }
346
+
347
+ /**
348
+ * Build Weaviate FilterValue from plain object using collection.filter API
349
+ *
350
+ * Converts our simple filter format to Weaviate v3 FilterValue objects.
351
+ * This enables proper filtering in Weaviate instead of post-filtering in application.
352
+ *
353
+ * @param collection - Weaviate collection with filter builder
354
+ * @param filterObj - Plain filter object { path, operator, valueString }
355
+ * @returns FilterValue object for Weaviate v3 client, or undefined on error
356
+ */
357
+ private buildFilter(collection: any, filterObj: any): any {
358
+ // If not a plain object, assume it's already a FilterValue
359
+ if (!this.isPlainFilterObject(filterObj)) {
360
+ return filterObj;
361
+ }
362
+
363
+ // Validate collection has filter API
364
+ if (!collection || !collection.filter || !collection.filter.byProperty) {
365
+ Logger.log("Warning: Collection does not have filter.byProperty API, skipping filter");
366
+ return undefined;
367
+ }
368
+
369
+ const { path, operator, valueString } = filterObj;
370
+
371
+ // Validate path
372
+ if (!path || !Array.isArray(path) || path.length === 0) {
373
+ Logger.log("Warning: Filter has invalid or empty path, skipping filter");
374
+ return undefined;
375
+ }
376
+
377
+ const property = path[0]; // Use first element of path array
378
+
379
+ // Validate valueString
380
+ if (valueString === undefined || valueString === null) {
381
+ Logger.log(`Warning: Filter has no valueString for property ${property}, skipping filter`);
382
+ return undefined;
383
+ }
384
+
385
+ // Build filter using collection.filter API
386
+ try {
387
+ switch (operator) {
388
+ case "ContainsAny":
389
+ Logger.log(
390
+ `Building ContainsAny filter for ${property} with ${Array.isArray(valueString) ? valueString.length : 1} values`,
391
+ );
392
+ return collection.filter.byProperty(property).containsAny(valueString);
393
+
394
+ case "ContainsAll":
395
+ return collection.filter.byProperty(property).containsAll(valueString);
396
+
397
+ case "ContainsNone":
398
+ return collection.filter.byProperty(property).containsNone(valueString);
399
+
400
+ case "Equal":
401
+ return collection.filter.byProperty(property).equal(valueString);
402
+
403
+ case "NotEqual":
404
+ return collection.filter.byProperty(property).notEqual(valueString);
405
+
406
+ case "GreaterThan":
407
+ return collection.filter.byProperty(property).greaterThan(valueString);
408
+
409
+ case "GreaterThanEqual":
410
+ return collection.filter.byProperty(property).greaterOrEqual(valueString);
411
+
412
+ case "LessThan":
413
+ return collection.filter.byProperty(property).lessThan(valueString);
414
+
415
+ case "LessThanEqual":
416
+ return collection.filter.byProperty(property).lessOrEqual(valueString);
417
+
418
+ case "Like":
419
+ return collection.filter.byProperty(property).like(valueString);
420
+
421
+ case "IsNull":
422
+ return collection.filter.byProperty(property).isNull(valueString === true);
423
+
424
+ // Compound filters not supported in Phase 1
425
+ case "And":
426
+ case "Or":
427
+ case "Not":
428
+ Logger.log(`Warning: Compound filter ${operator} not yet supported, skipping filter`);
429
+ return undefined;
430
+
431
+ default:
432
+ Logger.log(`Warning: Unsupported filter operator: ${operator}, skipping filter`);
433
+ return undefined;
434
+ }
435
+ } catch (error) {
436
+ Logger.log(`Error building filter for ${property} with operator ${operator}:`, error);
437
+ Logger.log("Falling back to no filter");
438
+ return undefined;
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Execute vector search
444
+ */
445
+ private async executeVectorSearch<T>(
446
+ schemaName: string,
447
+ options: VectorSearchOptions,
448
+ ): Promise<SearchResult<T>> {
449
+ const client = await this.getClient();
450
+ let collection = client.collections.get(schemaName);
451
+
452
+ // Add tenant context if provided
453
+ if (options.tenant) {
454
+ collection = collection.withTenant(options.tenant.tenant);
455
+ }
456
+
457
+ // Build filter using collection.filter API if plain object provided
458
+ const filters = options.where ? this.buildFilter(collection, options.where) : undefined;
459
+
460
+ const queryOptions: any = {
461
+ limit: options.limit || this.defaultLimit,
462
+ offset: options.offset || 0,
463
+ filters,
464
+ returnProperties: options.fields,
465
+ includeVector: options.includeVector,
466
+ returnMetadata: options.includeMetadata
467
+ ? ["certainty", "distance", "explainScore"]
468
+ : undefined,
469
+ };
470
+
471
+ let result;
472
+
473
+ // Execute the appropriate search based on what's provided
474
+ if (options.nearText) {
475
+ const query = Array.isArray(options.nearText.concepts)
476
+ ? options.nearText.concepts.join(" ")
477
+ : options.nearText.concepts || "";
478
+ result = await collection.query.nearText(query, queryOptions);
479
+ } else if (options.nearVector) {
480
+ result = await collection.query.nearVector(options.nearVector.vector, queryOptions);
481
+ } else if (options.nearObject) {
482
+ result = await collection.query.nearObject(options.nearObject.id, queryOptions);
483
+ } else {
484
+ // Fallback to fetchObjects if no vector search specified
485
+ result = await collection.query.fetchObjects(queryOptions);
486
+ }
487
+
488
+ return {
489
+ objects: (result.objects || []).map((obj) => ({
490
+ id: obj.uuid,
491
+ properties: obj.properties as T,
492
+ vector: this.extractVector(obj.vectors),
493
+ certainty: obj.metadata?.certainty,
494
+ distance: obj.metadata?.distance,
495
+ score: obj.metadata?.score,
496
+ metadata: obj.metadata,
497
+ })),
498
+ total: result.objects?.length || 0,
499
+ };
500
+ }
501
+
502
+ /**
503
+ * Execute BM25 search
504
+ */
505
+ private async executeBM25Search<T>(
506
+ schemaName: string,
507
+ options: BM25SearchOptions,
508
+ ): Promise<SearchResult<T>> {
509
+ const client = await this.getClient();
510
+ let collection = client.collections.get(schemaName);
511
+
512
+ // Add tenant context if provided
513
+ if (options.tenant) {
514
+ collection = collection.withTenant(options.tenant.tenant);
515
+ }
516
+
517
+ // Build filter using collection.filter API if plain object provided
518
+ const filters = options.where ? this.buildFilter(collection, options.where) : undefined;
519
+
520
+ const queryOptions: any = {
521
+ limit: options.limit || this.defaultLimit,
522
+ offset: options.offset || 0,
523
+ filters,
524
+ returnProperties: options.fields,
525
+ includeVector: options.includeVector,
526
+ returnMetadata: options.includeMetadata ? ["score", "explainScore"] : undefined,
527
+ };
528
+
529
+ // Add BM25-specific options
530
+ if (options.bm25?.properties) {
531
+ queryOptions.queryProperties = options.bm25.properties;
532
+ }
533
+
534
+ const query = options.bm25?.query || "";
535
+ const result = await collection.query.bm25(query, queryOptions);
536
+
537
+ return {
538
+ objects: (result.objects || []).map((obj) => ({
539
+ id: obj.uuid,
540
+ properties: obj.properties as T,
541
+ vector: this.extractVector(obj.vectors),
542
+ certainty: obj.metadata?.certainty,
543
+ distance: obj.metadata?.distance,
544
+ score: obj.metadata?.score,
545
+ metadata: obj.metadata,
546
+ })),
547
+ total: result.objects?.length || 0,
548
+ };
549
+ }
550
+
551
+ /**
552
+ * Execute hybrid search
553
+ */
554
+ private async executeHybridSearch<T>(
555
+ schemaName: string,
556
+ options: HybridSearchOptions,
557
+ ): Promise<SearchResult<T>> {
558
+ const client = await this.getClient();
559
+ let collection = client.collections.get(schemaName);
560
+
561
+ // Add tenant context if provided
562
+ if (options.tenant) {
563
+ collection = collection.withTenant(options.tenant.tenant);
564
+ }
565
+
566
+ // Build filter using collection.filter API if plain object provided
567
+ const filters = options.where ? this.buildFilter(collection, options.where) : undefined;
568
+
569
+ const queryOptions: any = {
570
+ limit: options.limit || this.defaultLimit,
571
+ offset: options.offset || 0,
572
+ filters,
573
+ returnProperties: options.fields,
574
+ includeVector: options.includeVector,
575
+ returnMetadata: options.includeMetadata ? ["score", "explainScore"] : undefined,
576
+ };
577
+
578
+ // Add hybrid-specific options
579
+ if (options.hybrid?.alpha !== undefined) {
580
+ queryOptions.alpha = options.hybrid.alpha;
581
+ }
582
+ if (options.hybrid?.properties) {
583
+ queryOptions.queryProperties = options.hybrid.properties;
584
+ }
585
+ if (options.hybrid?.vector) {
586
+ queryOptions.vector = options.hybrid.vector;
587
+ }
588
+ if (options.hybrid?.fusionType) {
589
+ queryOptions.fusionType = options.hybrid.fusionType;
590
+ }
591
+
592
+ const query = options.hybrid?.query || "";
593
+ const result = await collection.query.hybrid(query, queryOptions);
594
+
595
+ return {
596
+ objects: (result.objects || []).map((obj) => ({
597
+ id: obj.uuid,
598
+ properties: obj.properties as T,
599
+ vector: this.extractVector(obj.vectors),
600
+ certainty: obj.metadata?.certainty,
601
+ distance: obj.metadata?.distance,
602
+ score: obj.metadata?.score,
603
+ metadata: obj.metadata,
604
+ })),
605
+ total: result.objects?.length || 0,
606
+ };
607
+ }
608
+
609
+ /**
610
+ * Extract the first vector from a Weaviate response object's vectors field.
611
+ * Handles both v3 record format ({ default: [...] }) and array format ([[...]])
612
+ */
613
+ private extractVector(vectors: any): number[] | undefined {
614
+ if (!vectors) return undefined;
615
+ if (Array.isArray(vectors)) return vectors[0] as number[] | undefined;
616
+ const values = Object.values(vectors);
617
+ return values.length > 0 ? (values[0] as number[]) : undefined;
618
+ }
619
+
620
+ /**
621
+ * Universal search across multiple schemas
622
+ *
623
+ * @param schemaNames - Array of schema names to search
624
+ * @param request - Search request with method and options
625
+ * @returns Record of schema names to search results
626
+ * @example
627
+ * const results = await weaviate.searchAll(['Person', 'Organization'], {
628
+ * method: 'hybrid',
629
+ * options: { hybrid: { query: 'engineer' }, limit: 10 }
630
+ * });
631
+ */
632
+ async searchAll<T = any>(
633
+ schemaNames: string[],
634
+ request: SearchRequest,
635
+ ): Promise<Record<string, SearchResult<T>>> {
636
+ const results: Record<string, SearchResult<T>> = {};
637
+
638
+ // Execute searches in parallel
639
+ const searchPromises = schemaNames.map(async (schemaName) => {
640
+ try {
641
+ const result = await this.search<T>(schemaName, request);
642
+ return { schemaName, result };
643
+ } catch (error) {
644
+ Logger.log(`Error searching ${schemaName}:`, error);
645
+ return { schemaName, result: { objects: [], total: 0 } as SearchResult<T> };
646
+ }
647
+ });
648
+
649
+ const searchResults = await Promise.all(searchPromises);
650
+
651
+ searchResults.forEach(({ schemaName, result }) => {
652
+ results[schemaName] = result;
653
+ });
654
+
655
+ return results;
656
+ }
657
+
658
+ /**
659
+ * Search with automatic method selection based on query
660
+ *
661
+ * @param schemaName - Name of the schema to search
662
+ * @param query - Search query
663
+ * @param options - Additional search options
664
+ * @returns Search results
665
+ * @example
666
+ * const results = await weaviate.smartSearch('Person', 'software engineer');
667
+ */
668
+ async smartSearch<T = any>(
669
+ schemaName: string,
670
+ query: string,
671
+ options: Omit<SearchOptions, "query"> = {},
672
+ ): Promise<SearchResult<T>> {
673
+ // Simple heuristic: if query has quotes or specific terms, use BM25
674
+ // Otherwise use hybrid for best results
675
+ const hasQuotes = query.includes('"') || query.includes("'");
676
+ const hasSpecificTerms = /^[A-Z][a-z]+ [A-Z][a-z]+$/.test(query); // Proper names
677
+
678
+ let method: "vector" | "bm25" | "hybrid";
679
+ if (hasQuotes || hasSpecificTerms) {
680
+ method = "bm25";
681
+ } else if (query.length < 10) {
682
+ method = "vector";
683
+ } else {
684
+ method = "hybrid";
685
+ }
686
+
687
+ Logger.log(`Smart search using ${method} method for query: "${query}"`);
688
+
689
+ // Build proper discriminated union based on selected method
690
+ let request: SearchRequest;
691
+ if (method === "bm25") {
692
+ request = {
693
+ method: "bm25",
694
+ options: { ...options, bm25: { query } },
695
+ };
696
+ } else if (method === "vector") {
697
+ request = {
698
+ method: "vector",
699
+ options: { ...options, nearText: { concepts: [query] } },
700
+ };
701
+ } else {
702
+ request = {
703
+ method: "hybrid",
704
+ options: { ...options, hybrid: { query } },
705
+ };
706
+ }
707
+
708
+ return this.search<T>(schemaName, request);
709
+ }
710
+
711
+ /**
712
+ * Convenience method for vector search with nearText
713
+ *
714
+ * @param schemaName - Name of the schema to search
715
+ * @param concepts - Concepts to search for (semantic similarity)
716
+ * @param options - Additional search options
717
+ * @returns Search results with matching objects
718
+ * @example
719
+ * const results = await weaviate.vectorSearch('Person', ['software engineer', 'AI expert']);
720
+ */
721
+ async vectorSearch<T = any>(
722
+ schemaName: string,
723
+ concepts: string[],
724
+ options: Omit<SearchOptions & VectorSearchOptions, "nearText"> = {},
725
+ ): Promise<SearchResult<T>> {
726
+ return this.search<T>(schemaName, {
727
+ method: "vector",
728
+ options: {
729
+ ...options,
730
+ nearText: { concepts },
731
+ },
732
+ });
733
+ }
734
+
735
+ /**
736
+ * Convenience method for BM25 keyword search
737
+ *
738
+ * @param schemaName - Name of the schema to search
739
+ * @param query - Text query for keyword matching
740
+ * @param options - Additional search options
741
+ * @returns Search results with matching objects
742
+ * @example
743
+ * const results = await weaviate.textSearch('Person', 'John Smith');
744
+ */
745
+ async textSearch<T = any>(
746
+ schemaName: string,
747
+ query: string,
748
+ options: Omit<SearchOptions & BM25SearchOptions, "bm25"> = {},
749
+ ): Promise<SearchResult<T>> {
750
+ return this.search<T>(schemaName, {
751
+ method: "bm25",
752
+ options: {
753
+ ...options,
754
+ bm25: { query },
755
+ },
756
+ });
757
+ }
758
+
759
+ /**
760
+ * Convenience method for hybrid search (combines vector + keyword)
761
+ *
762
+ * @param schemaName - Name of the schema to search
763
+ * @param query - Search query
764
+ * @param options - Additional search options (alpha controls the balance)
765
+ * @returns Search results with matching objects
766
+ * @example
767
+ * const results = await weaviate.hybridSearch('Person', 'software engineer');
768
+ */
769
+ async hybridSearch<T = any>(
770
+ schemaName: string,
771
+ query: string,
772
+ options: Omit<SearchOptions & HybridSearchOptions, "hybrid"> = {},
773
+ ): Promise<SearchResult<T>> {
774
+ return this.search<T>(schemaName, {
775
+ method: "hybrid",
776
+ options: {
777
+ ...options,
778
+ hybrid: { query },
779
+ },
780
+ });
781
+ }
782
+
783
+ /**
784
+ * Search objects with basic options (defaults to hybrid)
785
+ *
786
+ * @param className - Name of the class to search
787
+ * @param request - Search request with method and options
788
+ * @returns Search results with matching objects
789
+ * @example
790
+ * const results = await weaviate.searchObjects('Person', {
791
+ * method: 'hybrid',
792
+ * options: { hybrid: { query: 'engineer' }, limit: 10 }
793
+ * });
794
+ */
795
+ async searchObjects<T = any>(
796
+ className: string,
797
+ request: SearchRequest,
798
+ ): Promise<SearchResult<T>> {
799
+ return this.search<T>(className, request);
800
+ }
801
+
802
+ // ==================== CRUD METHODS ====================
803
+
804
+ /**
805
+ * Create a single object in Weaviate
806
+ *
807
+ * @param obj - Object to create with class and properties
808
+ * @returns ID of the created object
809
+ * @example
810
+ * const id = await weaviate.createObject({
811
+ * class: 'Person',
812
+ * properties: { fullName: 'John Doe', email: 'john@example.com' }
813
+ * });
814
+ */
815
+ async createObject(obj: any): Promise<string> {
816
+ try {
817
+ const client = await this.getClient();
818
+ const collection = client.collections.get(obj.class);
819
+ const result = await collection.data.insert({
820
+ properties: obj.properties,
821
+ });
822
+
823
+ return result;
824
+ } catch (error) {
825
+ Logger.log("Error creating object:", error);
826
+ throw WeaviateError.from(
827
+ error,
828
+ WeaviateErrorCode.OBJECT_CREATION_ERROR,
829
+ `Failed to create object in ${obj.class}`,
830
+ );
831
+ }
832
+ }
833
+
834
+ /**
835
+ * Create multiple objects in batch
836
+ */
837
+ async createObjectsBatch(objects: any[]): Promise<string[]> {
838
+ try {
839
+ const client = await this.getClient();
840
+
841
+ // Group objects by class
842
+ const objectsByClass = objects.reduce(
843
+ (acc, obj) => {
844
+ if (!acc[obj.class]) {
845
+ acc[obj.class] = [];
846
+ }
847
+ acc[obj.class].push(obj.properties);
848
+ return acc;
849
+ },
850
+ {} as Record<string, any[]>,
851
+ );
852
+
853
+ // Insert each class's objects
854
+ const ids: string[] = [];
855
+ for (const [className, props] of Object.entries(objectsByClass)) {
856
+ const collection = client.collections.get(className);
857
+ const result = await collection.data.insertMany(props as any);
858
+ if (result.uuids) {
859
+ ids.push(...Object.values(result.uuids));
860
+ }
861
+ }
862
+
863
+ return ids;
864
+ } catch (error) {
865
+ Logger.log("Error creating objects batch:", error);
866
+ throw WeaviateError.from(
867
+ error,
868
+ WeaviateErrorCode.BATCH_OPERATION_ERROR,
869
+ "Failed to create batch of objects",
870
+ );
871
+ }
872
+ }
873
+
874
+ /**
875
+ * Create an object with a custom vector
876
+ */
877
+ async createObjectWithVector(
878
+ className: string,
879
+ properties: any,
880
+ vector: number[],
881
+ id?: string,
882
+ tenant?: string,
883
+ ): Promise<string> {
884
+ try {
885
+ const client = await this.getClient();
886
+ let collection = client.collections.get(className);
887
+
888
+ // Add tenant context if provided
889
+ if (tenant) {
890
+ collection = collection.withTenant(tenant);
891
+ }
892
+
893
+ const result = await collection.data.insert({
894
+ properties,
895
+ vectors: vector,
896
+ ...(id && { id }),
897
+ });
898
+
899
+ return result;
900
+ } catch (error) {
901
+ Logger.log("Error creating object with vector:", error);
902
+ throw WeaviateError.from(
903
+ error,
904
+ WeaviateErrorCode.OBJECT_CREATION_ERROR,
905
+ `Failed to create object with vector in ${className}`,
906
+ );
907
+ }
908
+ }
909
+
910
+ /**
911
+ * Get an object by ID
912
+ */
913
+ async getObject<T = any>(
914
+ className: string,
915
+ objectId: string,
916
+ tenant?: string,
917
+ ): Promise<T | null> {
918
+ try {
919
+ const client = await this.getClient();
920
+ let collection = client.collections.get(className);
921
+
922
+ // Add tenant context if provided
923
+ if (tenant) {
924
+ collection = collection.withTenant(tenant);
925
+ }
926
+
927
+ const result = await collection.query.fetchObjectById(objectId);
928
+
929
+ return (result?.properties as T) || null;
930
+ } catch (error) {
931
+ Logger.log("Error getting object:", error);
932
+ throw WeaviateError.from(
933
+ error,
934
+ WeaviateErrorCode.OBJECT_RETRIEVAL_ERROR,
935
+ `Failed to get object ${objectId} from ${className}`,
936
+ );
937
+ }
938
+ }
939
+
940
+ /**
941
+ * Update an object
942
+ */
943
+ async updateObject(className: string, objectId: string, properties: any): Promise<void> {
944
+ try {
945
+ const client = await this.getClient();
946
+ const collection = client.collections.get(className);
947
+ await collection.data.update({
948
+ id: objectId,
949
+ properties,
950
+ });
951
+ } catch (error) {
952
+ Logger.log("Error updating object:", error);
953
+ throw WeaviateError.from(
954
+ error,
955
+ WeaviateErrorCode.OBJECT_UPDATE_ERROR,
956
+ `Failed to update object ${objectId} in ${className}`,
957
+ );
958
+ }
959
+ }
960
+
961
+ /**
962
+ * Update an object with tenant support (properties only, no vector)
963
+ */
964
+ async updateObjectWithTenant(
965
+ className: string,
966
+ objectId: string,
967
+ properties: any,
968
+ tenant?: string,
969
+ skipHealthCheck = false,
970
+ ): Promise<void> {
971
+ try {
972
+ // Skip health check for batch operations - they handle their own retries
973
+ const client = await this.getClient(skipHealthCheck);
974
+ let collection = client.collections.get(className);
975
+
976
+ // Add tenant context if provided
977
+ if (tenant) {
978
+ collection = collection.withTenant(tenant);
979
+ }
980
+
981
+ await collection.data.update({
982
+ id: objectId,
983
+ properties,
984
+ });
985
+ } catch (error) {
986
+ Logger.log("Error updating object with tenant:", error);
987
+ throw WeaviateError.from(
988
+ error,
989
+ WeaviateErrorCode.OBJECT_UPDATE_ERROR,
990
+ `Failed to update object ${objectId} in ${className}`,
991
+ );
992
+ }
993
+ }
994
+
995
+ /**
996
+ * Update an object with a custom vector
997
+ */
998
+ async updateObjectWithVector(
999
+ className: string,
1000
+ objectId: string,
1001
+ properties: any,
1002
+ vector: number[],
1003
+ tenant?: string,
1004
+ ): Promise<void> {
1005
+ try {
1006
+ const client = await this.getClient();
1007
+ let collection = client.collections.get(className);
1008
+
1009
+ // Add tenant context if provided
1010
+ if (tenant) {
1011
+ collection = collection.withTenant(tenant);
1012
+ }
1013
+
1014
+ await collection.data.update({
1015
+ id: objectId,
1016
+ properties,
1017
+ vectors: vector,
1018
+ });
1019
+ } catch (error) {
1020
+ Logger.log("Error updating object with vector:", error);
1021
+ throw WeaviateError.from(
1022
+ error,
1023
+ WeaviateErrorCode.OBJECT_UPDATE_ERROR,
1024
+ `Failed to update object ${objectId} with vector in ${className}`,
1025
+ );
1026
+ }
1027
+ }
1028
+
1029
+ /**
1030
+ * Delete an object
1031
+ */
1032
+ async deleteObject(className: string, objectId: string): Promise<void> {
1033
+ try {
1034
+ const client = await this.getClient();
1035
+ const collection = client.collections.get(className);
1036
+ await collection.data.deleteById(objectId);
1037
+ } catch (error) {
1038
+ Logger.log("Error deleting object:", error);
1039
+ throw WeaviateError.from(
1040
+ error,
1041
+ WeaviateErrorCode.OBJECT_DELETE_ERROR,
1042
+ `Failed to delete object ${objectId} from ${className}`,
1043
+ );
1044
+ }
1045
+ }
1046
+
1047
+ /**
1048
+ * Get object count for a class
1049
+ */
1050
+ async getObjectCount(className: string): Promise<number> {
1051
+ try {
1052
+ const client = await this.getClient();
1053
+ const collection = client.collections.get(className);
1054
+ const count = await collection.aggregate.overAll();
1055
+ return count.totalCount || 0;
1056
+ } catch (error) {
1057
+ Logger.log("Error getting object count:", error);
1058
+ throw WeaviateError.from(
1059
+ error,
1060
+ WeaviateErrorCode.OBJECT_RETRIEVAL_ERROR,
1061
+ `Failed to get object count for ${className}`,
1062
+ );
1063
+ }
1064
+ }
1065
+
1066
+ // ==================== MULTI-TENANCY METHODS ====================
1067
+
1068
+ /**
1069
+ * Create a new tenant for a multi-tenant collection
1070
+ *
1071
+ * @param className - Name of the multi-tenant class
1072
+ * @param options - Tenant creation options (name, activityStatus)
1073
+ * @returns Result with success status and tenant information
1074
+ * @example
1075
+ * const result = await weaviate.createTenant('UserDocuments', {
1076
+ * name: 'acme-corp',
1077
+ * activityStatus: 'HOT'
1078
+ * });
1079
+ */
1080
+ async createTenant(
1081
+ className: string,
1082
+ options: CreateTenantOptions,
1083
+ ): Promise<TenantManagementResult> {
1084
+ try {
1085
+ // Validate tenant name format
1086
+ if (!TenantContextManager.validateTenantName(options.name)) {
1087
+ const sanitized = TenantContextManager.sanitizeTenantName(options.name);
1088
+ throw new Error(
1089
+ `Invalid tenant name '${options.name}'. Tenant names must be lowercase alphanumeric with hyphens only (max 63 chars). Suggested: '${sanitized}'`,
1090
+ );
1091
+ }
1092
+
1093
+ const client = await this.getClient();
1094
+ const collection = client.collections.get(className);
1095
+ await collection.tenants.create({
1096
+ name: options.name,
1097
+ activityStatus: options.activityStatus || "HOT",
1098
+ });
1099
+
1100
+ Logger.log(`Tenant '${options.name}' created for class '${className}'`);
1101
+
1102
+ return {
1103
+ success: true,
1104
+ tenant: {
1105
+ name: options.name,
1106
+ activityStatus: options.activityStatus || "HOT",
1107
+ },
1108
+ };
1109
+ } catch (error) {
1110
+ Logger.log(`Error creating tenant '${options.name}':`, error);
1111
+ return {
1112
+ success: false,
1113
+ error: error.message || "Failed to create tenant",
1114
+ };
1115
+ }
1116
+ }
1117
+
1118
+ /**
1119
+ * List all tenants for a multi-tenant collection
1120
+ */
1121
+ async listTenants(className: string): Promise<Tenant[]> {
1122
+ try {
1123
+ const client = await this.getClient();
1124
+ const collection = client.collections.get(className);
1125
+ const result = await collection.tenants.get();
1126
+
1127
+ return Object.values(result).map((tenant: any) => ({
1128
+ name: tenant.name,
1129
+ activityStatus: tenant.activityStatus,
1130
+ createdAt: tenant.createdAt,
1131
+ updatedAt: tenant.updatedAt,
1132
+ }));
1133
+ } catch (error) {
1134
+ Logger.log(`Error listing tenants for class '${className}':`, error);
1135
+ throw WeaviateError.from(
1136
+ error,
1137
+ WeaviateErrorCode.TENANT_RETRIEVAL_ERROR,
1138
+ `Failed to list tenants for ${className}`,
1139
+ );
1140
+ }
1141
+ }
1142
+
1143
+ /**
1144
+ * Get a specific tenant
1145
+ */
1146
+ async getTenant(className: string, tenantName: string): Promise<Tenant | null> {
1147
+ try {
1148
+ const tenants = await this.listTenants(className);
1149
+ return tenants.find((tenant) => tenant.name === tenantName) || null;
1150
+ } catch (error) {
1151
+ Logger.log(`Error getting tenant '${tenantName}':`, error);
1152
+ throw WeaviateError.from(
1153
+ error,
1154
+ WeaviateErrorCode.TENANT_RETRIEVAL_ERROR,
1155
+ `Failed to get tenant '${tenantName}' from ${className}`,
1156
+ );
1157
+ }
1158
+ }
1159
+
1160
+ /**
1161
+ * Update a tenant
1162
+ */
1163
+ async updateTenant(
1164
+ className: string,
1165
+ tenantName: string,
1166
+ options: UpdateTenantOptions,
1167
+ ): Promise<TenantManagementResult> {
1168
+ try {
1169
+ // Validate tenant name format
1170
+ if (!TenantContextManager.validateTenantName(tenantName)) {
1171
+ throw new Error(
1172
+ `Invalid tenant name '${tenantName}'. Tenant names must be lowercase alphanumeric with hyphens only (max 63 chars).`,
1173
+ );
1174
+ }
1175
+
1176
+ const client = await this.getClient();
1177
+ const collection = client.collections.get(className);
1178
+ await collection.tenants.update({
1179
+ name: tenantName,
1180
+ activityStatus: options.activityStatus as "HOT" | "COLD" | "FROZEN" | undefined,
1181
+ });
1182
+
1183
+ Logger.log(`Tenant '${tenantName}' updated for class '${className}'`);
1184
+
1185
+ return {
1186
+ success: true,
1187
+ tenant: {
1188
+ name: tenantName,
1189
+ activityStatus: options.activityStatus || "HOT",
1190
+ },
1191
+ };
1192
+ } catch (error) {
1193
+ Logger.log(`Error updating tenant '${tenantName}':`, error);
1194
+ return {
1195
+ success: false,
1196
+ error: error.message || "Failed to update tenant",
1197
+ };
1198
+ }
1199
+ }
1200
+
1201
+ /**
1202
+ * Delete a tenant
1203
+ */
1204
+ async deleteTenant(className: string, tenantName: string): Promise<TenantManagementResult> {
1205
+ try {
1206
+ // Validate tenant name format
1207
+ if (!TenantContextManager.validateTenantName(tenantName)) {
1208
+ throw new Error(
1209
+ `Invalid tenant name '${tenantName}'. Tenant names must be lowercase alphanumeric with hyphens only (max 63 chars).`,
1210
+ );
1211
+ }
1212
+
1213
+ const client = await this.getClient();
1214
+ const collection = client.collections.get(className);
1215
+ await collection.tenants.remove(tenantName);
1216
+
1217
+ Logger.log(`Tenant '${tenantName}' deleted from class '${className}'`);
1218
+
1219
+ return {
1220
+ success: true,
1221
+ };
1222
+ } catch (error) {
1223
+ Logger.log(`Error deleting tenant '${tenantName}':`, error);
1224
+ return {
1225
+ success: false,
1226
+ error: error.message || "Failed to delete tenant",
1227
+ };
1228
+ }
1229
+ }
1230
+
1231
+ /**
1232
+ * Get tenant statistics for a collection
1233
+ */
1234
+ async getTenantStats(className: string): Promise<TenantStats> {
1235
+ try {
1236
+ const tenants = await this.listTenants(className);
1237
+
1238
+ return {
1239
+ totalTenants: tenants.length,
1240
+ activeTenants: tenants.filter((t) => t.activityStatus === "HOT").length,
1241
+ inactiveTenants: tenants.filter((t) => t.activityStatus === "INACTIVE").length,
1242
+ coldTenants: tenants.filter((t) => t.activityStatus === "COLD").length,
1243
+ };
1244
+ } catch (error) {
1245
+ Logger.log(`Error getting tenant stats for class '${className}':`, error);
1246
+ throw WeaviateError.from(
1247
+ error,
1248
+ WeaviateErrorCode.TENANT_RETRIEVAL_ERROR,
1249
+ `Failed to get tenant stats for ${className}`,
1250
+ );
1251
+ }
1252
+ }
1253
+
1254
+ /**
1255
+ * Check if a collection supports multi-tenancy
1256
+ */
1257
+ async isMultiTenant(className: string): Promise<boolean> {
1258
+ try {
1259
+ const client = await this.getClient();
1260
+ const config = await client.collections.export(className);
1261
+ return config.multiTenancy?.enabled || false;
1262
+ } catch (error) {
1263
+ Logger.log(`Error checking multi-tenancy for class '${className}':`, error);
1264
+ return false;
1265
+ }
1266
+ }
1267
+
1268
+ /**
1269
+ * Search with tenant context
1270
+ *
1271
+ * @param schemaName - Name of the schema to search
1272
+ * @param request - Search request with method and options
1273
+ * @param tenant - Tenant identifier
1274
+ * @returns Search results scoped to the specified tenant
1275
+ * @example
1276
+ * const results = await weaviate.searchWithTenant('Person', {
1277
+ * method: 'hybrid',
1278
+ * options: { hybrid: { query: 'engineer' }, limit: 10 }
1279
+ * }, 'tenant123');
1280
+ */
1281
+ async searchWithTenant<T = any>(
1282
+ schemaName: string,
1283
+ request: SearchRequest,
1284
+ tenant: string,
1285
+ ): Promise<SearchResult<T>> {
1286
+ // Validate tenant name format
1287
+ if (!TenantContextManager.validateTenantName(tenant)) {
1288
+ throw new Error(
1289
+ `Invalid tenant name '${tenant}'. Tenant names must be lowercase alphanumeric with hyphens only (max 63 chars).`,
1290
+ );
1291
+ }
1292
+
1293
+ // Add tenant to the options
1294
+ const requestWithTenant: SearchRequest = {
1295
+ method: request.method,
1296
+ options: {
1297
+ ...request.options,
1298
+ tenant: { tenant },
1299
+ },
1300
+ } as SearchRequest;
1301
+
1302
+ return this.search<T>(schemaName, requestWithTenant);
1303
+ }
1304
+
1305
+ /**
1306
+ * Smart search with tenant context
1307
+ */
1308
+ async smartSearchWithTenant<T = any>(
1309
+ schemaName: string,
1310
+ query: string,
1311
+ tenant: string,
1312
+ options: Omit<SearchOptions, "query" | "tenant"> = {},
1313
+ ): Promise<SearchResult<T>> {
1314
+ return this.smartSearch<T>(schemaName, query, {
1315
+ ...options,
1316
+ tenant: { tenant },
1317
+ });
1318
+ }
1319
+
1320
+ // ==================== UTILITY METHODS ====================
1321
+
1322
+ /**
1323
+ * Create a query builder for a specific schema
1324
+ */
1325
+ queryBuilder(schemaName: string): QueryBuilder {
1326
+ return createQueryBuilder(schemaName);
1327
+ }
1328
+
1329
+ /**
1330
+ * Get query patterns for common operations
1331
+ */
1332
+ get patterns() {
1333
+ return QueryPatterns;
1334
+ }
1335
+
1336
+ /**
1337
+ * Get schema information
1338
+ */
1339
+ getSchemaInfo(schemaName: string): {
1340
+ schema: SchemaConfig | undefined;
1341
+ searchableFields: string[];
1342
+ filterableFields: string[];
1343
+ sortableFields: string[];
1344
+ plugins: Plugin[];
1345
+ } {
1346
+ return {
1347
+ schema: this.registry.getSchema(schemaName),
1348
+ searchableFields: this.registry.getSearchableFields(schemaName),
1349
+ filterableFields: this.registry.getFilterableFields(schemaName),
1350
+ sortableFields: this.registry.getSortableFields(schemaName),
1351
+ plugins: this.registry.getSchemaPlugins(schemaName),
1352
+ };
1353
+ }
1354
+
1355
+ /**
1356
+ * Get service statistics
1357
+ */
1358
+ getStats(): {
1359
+ registry: ReturnType<SchemaRegistry["getStats"]>;
1360
+ schemas: string[];
1361
+ } {
1362
+ return {
1363
+ registry: this.registry.getStats(),
1364
+ schemas: this.registry.getSchemaNames(),
1365
+ };
1366
+ }
1367
+
1368
+ /**
1369
+ * Get the schema registry
1370
+ */
1371
+ getRegistry(): SchemaRegistry {
1372
+ return this.registry;
1373
+ }
1374
+
1375
+ /**
1376
+ * Register a custom schema in the registry (without creating in Weaviate)
1377
+ *
1378
+ * @param schema - Schema configuration to register
1379
+ * @example
1380
+ * weaviate.registerSchema(ProductSchema);
1381
+ */
1382
+ registerSchema(schema: SchemaConfig): void {
1383
+ this.registry.registerSchema(schema);
1384
+ }
1385
+
1386
+ /**
1387
+ * Register multiple schemas at once
1388
+ *
1389
+ * @param schemas - Record of schema configurations to register
1390
+ */
1391
+ registerSchemas(schemas: Record<string, SchemaConfig>): void {
1392
+ this.registry.registerSchemas(schemas);
1393
+ }
1394
+
1395
+ /**
1396
+ * Register a custom plugin for schema operations
1397
+ *
1398
+ * @param plugin - Plugin to register
1399
+ * @example
1400
+ * weaviate.registerPlugin(new MyCustomPlugin());
1401
+ */
1402
+ registerPlugin(plugin: Plugin): void {
1403
+ this.registry.registerPlugin(plugin);
1404
+ }
1405
+
1406
+ /**
1407
+ * Health check
1408
+ */
1409
+ async healthCheck(): Promise<boolean> {
1410
+ try {
1411
+ const client = await this.getClient();
1412
+ await client.getMeta();
1413
+ return true;
1414
+ } catch (error) {
1415
+ Logger.log("Weaviate health check failed:", error);
1416
+ return false;
1417
+ }
1418
+ }
1419
+ }