@functional-systems/lambdadb 0.4.2 → 0.5.0-rc.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 (223) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/FUNCTIONS.md +7 -2
  3. package/README.md +60 -2
  4. package/RUNTIMES.md +7 -0
  5. package/USAGE.md +20 -0
  6. package/dist/commonjs/client.d.ts +25 -10
  7. package/dist/commonjs/client.d.ts.map +1 -1
  8. package/dist/commonjs/client.js +233 -59
  9. package/dist/commonjs/client.js.map +1 -1
  10. package/dist/commonjs/compat/qdrant/client.d.ts +6 -10
  11. package/dist/commonjs/compat/qdrant/client.d.ts.map +1 -1
  12. package/dist/commonjs/compat/qdrant/client.js +33 -15
  13. package/dist/commonjs/compat/qdrant/client.js.map +1 -1
  14. package/dist/commonjs/compat/qdrant/filters.js +5 -1
  15. package/dist/commonjs/compat/qdrant/filters.js.map +1 -1
  16. package/dist/commonjs/funcs/collectionsCreate.js +1 -1
  17. package/dist/commonjs/funcs/collectionsDelete.js +1 -1
  18. package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.js +4 -0
  19. package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.js.map +1 -1
  20. package/dist/commonjs/funcs/collectionsDocsListDocs.js +3 -0
  21. package/dist/commonjs/funcs/collectionsDocsListDocs.js.map +1 -1
  22. package/dist/commonjs/funcs/collectionsDocsListDocsExtended.d.ts +15 -0
  23. package/dist/commonjs/funcs/collectionsDocsListDocsExtended.d.ts.map +1 -0
  24. package/dist/commonjs/funcs/collectionsDocsListDocsExtended.js +131 -0
  25. package/dist/commonjs/funcs/collectionsDocsListDocsExtended.js.map +1 -0
  26. package/dist/commonjs/index.d.ts +4 -1
  27. package/dist/commonjs/index.d.ts.map +1 -1
  28. package/dist/commonjs/index.js +15 -1
  29. package/dist/commonjs/index.js.map +1 -1
  30. package/dist/commonjs/lib/config.d.ts +2 -2
  31. package/dist/commonjs/lib/config.js +2 -2
  32. package/dist/commonjs/lib/config.js.map +1 -1
  33. package/dist/commonjs/lib/queryInput.d.ts +3 -11
  34. package/dist/commonjs/lib/queryInput.d.ts.map +1 -1
  35. package/dist/commonjs/lib/queryInput.js.map +1 -1
  36. package/dist/commonjs/models/collectionresponse.d.ts +12 -21
  37. package/dist/commonjs/models/collectionresponse.d.ts.map +1 -1
  38. package/dist/commonjs/models/collectionresponse.js +5 -6
  39. package/dist/commonjs/models/collectionresponse.js.map +1 -1
  40. package/dist/commonjs/models/index.d.ts +1 -0
  41. package/dist/commonjs/models/index.d.ts.map +1 -1
  42. package/dist/commonjs/models/index.js +1 -0
  43. package/dist/commonjs/models/index.js.map +1 -1
  44. package/dist/commonjs/models/operations/bulkupsertdocs.d.ts +6 -0
  45. package/dist/commonjs/models/operations/bulkupsertdocs.d.ts.map +1 -1
  46. package/dist/commonjs/models/operations/bulkupsertdocs.js +2 -0
  47. package/dist/commonjs/models/operations/bulkupsertdocs.js.map +1 -1
  48. package/dist/commonjs/models/operations/createcollection.d.ts +20 -13
  49. package/dist/commonjs/models/operations/createcollection.d.ts.map +1 -1
  50. package/dist/commonjs/models/operations/createcollection.js +15 -7
  51. package/dist/commonjs/models/operations/createcollection.js.map +1 -1
  52. package/dist/commonjs/models/operations/deletedocs.d.ts +3 -0
  53. package/dist/commonjs/models/operations/deletedocs.d.ts.map +1 -1
  54. package/dist/commonjs/models/operations/deletedocs.js +1 -0
  55. package/dist/commonjs/models/operations/deletedocs.js.map +1 -1
  56. package/dist/commonjs/models/operations/fetchdocs.d.ts +3 -0
  57. package/dist/commonjs/models/operations/fetchdocs.d.ts.map +1 -1
  58. package/dist/commonjs/models/operations/fetchdocs.js +9 -0
  59. package/dist/commonjs/models/operations/fetchdocs.js.map +1 -1
  60. package/dist/commonjs/models/operations/getbulkupsertdocs.d.ts +5 -0
  61. package/dist/commonjs/models/operations/getbulkupsertdocs.d.ts.map +1 -1
  62. package/dist/commonjs/models/operations/getbulkupsertdocs.js +5 -3
  63. package/dist/commonjs/models/operations/getbulkupsertdocs.js.map +1 -1
  64. package/dist/commonjs/models/operations/listdocs.d.ts +69 -0
  65. package/dist/commonjs/models/operations/listdocs.d.ts.map +1 -1
  66. package/dist/commonjs/models/operations/listdocs.js +41 -1
  67. package/dist/commonjs/models/operations/listdocs.js.map +1 -1
  68. package/dist/commonjs/models/operations/querycollection.d.ts +3 -0
  69. package/dist/commonjs/models/operations/querycollection.d.ts.map +1 -1
  70. package/dist/commonjs/models/operations/querycollection.js +9 -0
  71. package/dist/commonjs/models/operations/querycollection.js.map +1 -1
  72. package/dist/commonjs/models/operations/updatecollection.d.ts +10 -4
  73. package/dist/commonjs/models/operations/updatecollection.d.ts.map +1 -1
  74. package/dist/commonjs/models/operations/updatecollection.js +8 -1
  75. package/dist/commonjs/models/operations/updatecollection.js.map +1 -1
  76. package/dist/commonjs/models/operations/updatedocs.d.ts +3 -0
  77. package/dist/commonjs/models/operations/updatedocs.d.ts.map +1 -1
  78. package/dist/commonjs/models/operations/updatedocs.js +1 -0
  79. package/dist/commonjs/models/operations/updatedocs.js.map +1 -1
  80. package/dist/commonjs/models/operations/upsertdocs.d.ts +3 -0
  81. package/dist/commonjs/models/operations/upsertdocs.d.ts.map +1 -1
  82. package/dist/commonjs/models/operations/upsertdocs.js +1 -0
  83. package/dist/commonjs/models/operations/upsertdocs.js.map +1 -1
  84. package/dist/commonjs/models/versioning.d.ts +100 -0
  85. package/dist/commonjs/models/versioning.d.ts.map +1 -0
  86. package/dist/commonjs/models/versioning.js +93 -0
  87. package/dist/commonjs/models/versioning.js.map +1 -0
  88. package/dist/commonjs/types/public.d.ts +86 -8
  89. package/dist/commonjs/types/public.d.ts.map +1 -1
  90. package/dist/commonjs/types/public.js +30 -7
  91. package/dist/commonjs/types/public.js.map +1 -1
  92. package/dist/commonjs/versioning.d.ts +63 -0
  93. package/dist/commonjs/versioning.d.ts.map +1 -0
  94. package/dist/commonjs/versioning.js +390 -0
  95. package/dist/commonjs/versioning.js.map +1 -0
  96. package/dist/esm/client.d.ts +25 -10
  97. package/dist/esm/client.d.ts.map +1 -1
  98. package/dist/esm/client.js +234 -61
  99. package/dist/esm/client.js.map +1 -1
  100. package/dist/esm/compat/qdrant/client.d.ts +6 -10
  101. package/dist/esm/compat/qdrant/client.d.ts.map +1 -1
  102. package/dist/esm/compat/qdrant/client.js +33 -15
  103. package/dist/esm/compat/qdrant/client.js.map +1 -1
  104. package/dist/esm/compat/qdrant/filters.js +5 -1
  105. package/dist/esm/compat/qdrant/filters.js.map +1 -1
  106. package/dist/esm/funcs/collectionsCreate.js +1 -1
  107. package/dist/esm/funcs/collectionsDelete.js +1 -1
  108. package/dist/esm/funcs/collectionsDocsGetBulkUpsert.js +5 -1
  109. package/dist/esm/funcs/collectionsDocsGetBulkUpsert.js.map +1 -1
  110. package/dist/esm/funcs/collectionsDocsListDocs.js +3 -0
  111. package/dist/esm/funcs/collectionsDocsListDocs.js.map +1 -1
  112. package/dist/esm/funcs/collectionsDocsListDocsExtended.d.ts +15 -0
  113. package/dist/esm/funcs/collectionsDocsListDocsExtended.d.ts.map +1 -0
  114. package/dist/esm/funcs/collectionsDocsListDocsExtended.js +95 -0
  115. package/dist/esm/funcs/collectionsDocsListDocsExtended.js.map +1 -0
  116. package/dist/esm/index.d.ts +4 -1
  117. package/dist/esm/index.d.ts.map +1 -1
  118. package/dist/esm/index.js +3 -1
  119. package/dist/esm/index.js.map +1 -1
  120. package/dist/esm/lib/config.d.ts +2 -2
  121. package/dist/esm/lib/config.js +2 -2
  122. package/dist/esm/lib/config.js.map +1 -1
  123. package/dist/esm/lib/queryInput.d.ts +3 -11
  124. package/dist/esm/lib/queryInput.d.ts.map +1 -1
  125. package/dist/esm/lib/queryInput.js.map +1 -1
  126. package/dist/esm/models/collectionresponse.d.ts +12 -21
  127. package/dist/esm/models/collectionresponse.d.ts.map +1 -1
  128. package/dist/esm/models/collectionresponse.js +5 -6
  129. package/dist/esm/models/collectionresponse.js.map +1 -1
  130. package/dist/esm/models/index.d.ts +1 -0
  131. package/dist/esm/models/index.d.ts.map +1 -1
  132. package/dist/esm/models/index.js +1 -0
  133. package/dist/esm/models/index.js.map +1 -1
  134. package/dist/esm/models/operations/bulkupsertdocs.d.ts +6 -0
  135. package/dist/esm/models/operations/bulkupsertdocs.d.ts.map +1 -1
  136. package/dist/esm/models/operations/bulkupsertdocs.js +2 -0
  137. package/dist/esm/models/operations/bulkupsertdocs.js.map +1 -1
  138. package/dist/esm/models/operations/createcollection.d.ts +20 -13
  139. package/dist/esm/models/operations/createcollection.d.ts.map +1 -1
  140. package/dist/esm/models/operations/createcollection.js +15 -7
  141. package/dist/esm/models/operations/createcollection.js.map +1 -1
  142. package/dist/esm/models/operations/deletedocs.d.ts +3 -0
  143. package/dist/esm/models/operations/deletedocs.d.ts.map +1 -1
  144. package/dist/esm/models/operations/deletedocs.js +1 -0
  145. package/dist/esm/models/operations/deletedocs.js.map +1 -1
  146. package/dist/esm/models/operations/fetchdocs.d.ts +3 -0
  147. package/dist/esm/models/operations/fetchdocs.d.ts.map +1 -1
  148. package/dist/esm/models/operations/fetchdocs.js +9 -0
  149. package/dist/esm/models/operations/fetchdocs.js.map +1 -1
  150. package/dist/esm/models/operations/getbulkupsertdocs.d.ts +5 -0
  151. package/dist/esm/models/operations/getbulkupsertdocs.d.ts.map +1 -1
  152. package/dist/esm/models/operations/getbulkupsertdocs.js +6 -4
  153. package/dist/esm/models/operations/getbulkupsertdocs.js.map +1 -1
  154. package/dist/esm/models/operations/listdocs.d.ts +69 -0
  155. package/dist/esm/models/operations/listdocs.d.ts.map +1 -1
  156. package/dist/esm/models/operations/listdocs.js +38 -0
  157. package/dist/esm/models/operations/listdocs.js.map +1 -1
  158. package/dist/esm/models/operations/querycollection.d.ts +3 -0
  159. package/dist/esm/models/operations/querycollection.d.ts.map +1 -1
  160. package/dist/esm/models/operations/querycollection.js +9 -0
  161. package/dist/esm/models/operations/querycollection.js.map +1 -1
  162. package/dist/esm/models/operations/updatecollection.d.ts +10 -4
  163. package/dist/esm/models/operations/updatecollection.d.ts.map +1 -1
  164. package/dist/esm/models/operations/updatecollection.js +8 -1
  165. package/dist/esm/models/operations/updatecollection.js.map +1 -1
  166. package/dist/esm/models/operations/updatedocs.d.ts +3 -0
  167. package/dist/esm/models/operations/updatedocs.d.ts.map +1 -1
  168. package/dist/esm/models/operations/updatedocs.js +1 -0
  169. package/dist/esm/models/operations/updatedocs.js.map +1 -1
  170. package/dist/esm/models/operations/upsertdocs.d.ts +3 -0
  171. package/dist/esm/models/operations/upsertdocs.d.ts.map +1 -1
  172. package/dist/esm/models/operations/upsertdocs.js +1 -0
  173. package/dist/esm/models/operations/upsertdocs.js.map +1 -1
  174. package/dist/esm/models/versioning.d.ts +100 -0
  175. package/dist/esm/models/versioning.d.ts.map +1 -0
  176. package/dist/esm/models/versioning.js +57 -0
  177. package/dist/esm/models/versioning.js.map +1 -0
  178. package/dist/esm/types/public.d.ts +86 -8
  179. package/dist/esm/types/public.d.ts.map +1 -1
  180. package/dist/esm/types/public.js +26 -7
  181. package/dist/esm/types/public.js.map +1 -1
  182. package/dist/esm/versioning.d.ts +63 -0
  183. package/dist/esm/versioning.d.ts.map +1 -0
  184. package/dist/esm/versioning.js +344 -0
  185. package/dist/esm/versioning.js.map +1 -0
  186. package/jsr.json +3 -1
  187. package/package.json +14 -2
  188. package/src/client.ts +367 -72
  189. package/src/compat/qdrant/client.ts +46 -20
  190. package/src/compat/qdrant/filters.ts +5 -3
  191. package/src/funcs/collectionsCreate.ts +1 -1
  192. package/src/funcs/collectionsDelete.ts +1 -1
  193. package/src/funcs/collectionsDocsGetBulkUpsert.ts +6 -1
  194. package/src/funcs/collectionsDocsListDocs.ts +3 -0
  195. package/src/funcs/collectionsDocsListDocsExtended.ts +201 -0
  196. package/src/index.ts +17 -0
  197. package/src/lib/config.ts +2 -2
  198. package/src/lib/queryInput.ts +3 -10
  199. package/src/models/collectionresponse.ts +17 -26
  200. package/src/models/index.ts +1 -0
  201. package/src/models/operations/bulkupsertdocs.ts +8 -0
  202. package/src/models/operations/createcollection.ts +39 -18
  203. package/src/models/operations/deletedocs.ts +4 -0
  204. package/src/models/operations/fetchdocs.ts +12 -0
  205. package/src/models/operations/getbulkupsertdocs.ts +11 -4
  206. package/src/models/operations/listdocs.ts +120 -0
  207. package/src/models/operations/querycollection.ts +12 -0
  208. package/src/models/operations/updatecollection.ts +21 -3
  209. package/src/models/operations/updatedocs.ts +4 -0
  210. package/src/models/operations/upsertdocs.ts +4 -0
  211. package/src/models/versioning.ts +118 -0
  212. package/src/types/public.ts +136 -16
  213. package/src/versioning.ts +490 -0
  214. package/examples/collectionScoped.example.ts +0 -38
  215. package/examples/collectionsList.example.ts +0 -25
  216. package/examples/package-lock.json +0 -612
  217. package/examples/package.json +0 -18
  218. package/test/integration/qdrant-compat-external.test.mjs +0 -351
  219. package/test/integration/qdrant-compat-live.test.mjs +0 -122
  220. package/test/null-response.test.mjs +0 -73
  221. package/test/public-api.test.mjs +0 -489
  222. package/test/qdrant-compat.test.mjs +0 -467
  223. package/tsconfig.json +0 -39
package/src/client.ts CHANGED
@@ -12,6 +12,12 @@
12
12
 
13
13
  import { LambdaDBCore } from "./core.js";
14
14
  import type { SDKOptions } from "./lib/config.js";
15
+ import {
16
+ HTTPClient,
17
+ isAbortError,
18
+ isConnectionError,
19
+ isTimeoutError,
20
+ } from "./lib/http.js";
15
21
  import { collectionsCreate } from "./funcs/collectionsCreate.js";
16
22
  import { collectionsDelete } from "./funcs/collectionsDelete.js";
17
23
  import { collectionsGet } from "./funcs/collectionsGet.js";
@@ -23,17 +29,30 @@ import { collectionsDocsDelete } from "./funcs/collectionsDocsDelete.js";
23
29
  import { collectionsDocsFetch } from "./funcs/collectionsDocsFetch.js";
24
30
  import { collectionsDocsGetBulkUpsert } from "./funcs/collectionsDocsGetBulkUpsert.js";
25
31
  import { collectionsDocsListDocs } from "./funcs/collectionsDocsListDocs.js";
32
+ import { collectionsDocsListDocsExtended } from "./funcs/collectionsDocsListDocsExtended.js";
26
33
  import { collectionsDocsUpdate } from "./funcs/collectionsDocsUpdate.js";
27
34
  import { collectionsDocsUpsert } from "./funcs/collectionsDocsUpsert.js";
28
35
  import type { RequestOptions } from "./lib/sdks.js";
29
- import { UnexpectedClientError } from "./models/errors/httpclienterrors.js";
36
+ import {
37
+ ConnectionError,
38
+ RequestAbortedError,
39
+ RequestTimeoutError,
40
+ UnexpectedClientError,
41
+ } from "./models/errors/httpclienterrors.js";
42
+ import {
43
+ CollectionAliases,
44
+ CollectionBranches,
45
+ CollectionTags,
46
+ } from "./versioning.js";
30
47
  import { unwrapAsync, OK, ERR } from "./types/fp.js";
31
48
  import type { Result } from "./types/fp.js";
32
49
  import type * as operations from "./models/operations/index.js";
33
50
  import type * as models from "./models/index.js";
34
51
  import {
35
52
  listCollectionsResponseWithDates,
53
+ createCollectionResponseWithDates,
36
54
  getCollectionResponseWithDates,
55
+ updateCollectionResponseWithDates,
37
56
  type CreateCollectionInput,
38
57
  type UpdateCollectionInput,
39
58
  type QueryCollectionInput,
@@ -45,17 +64,18 @@ import {
45
64
  type ListCollectionsInput,
46
65
  type ListCollectionsResponseWithDates,
47
66
  type GetCollectionResponseWithDates,
48
- UpsertDocsInput,
49
- UpdateDocsInput,
50
- DeleteDocsInput,
51
- FetchDocsInput,
52
- FetchDocsResponse,
53
- FetchDocsDoc,
54
- BulkUpsertInput,
55
- MessageResponse,
56
- CreateCollectionResponse,
57
- UpdateCollectionResponse,
58
- GetBulkUpsertDocsResponse,
67
+ type CreateCollectionResponseWithDates,
68
+ type UpdateCollectionResponseWithDates,
69
+ type GetBulkUpsertInput,
70
+ type UpsertDocsInput,
71
+ type UpdateDocsInput,
72
+ type DeleteDocsInput,
73
+ type FetchDocsInput,
74
+ type FetchDocsResponse,
75
+ type FetchDocsDoc,
76
+ type BulkUpsertInput,
77
+ type MessageResponse,
78
+ type GetBulkUpsertDocsResponse,
59
79
  } from "./types/public.js";
60
80
  import type {
61
81
  ListCollectionsError,
@@ -86,15 +106,95 @@ export type { operations, models };
86
106
  /**
87
107
  * Fetches documents from a presigned docsUrl. Response must be { docs: [...] }.
88
108
  */
89
- async function fetchDocsFromUrl<T>(docsUrl: string): Promise<T[]> {
90
- const res = await fetch(docsUrl);
109
+ function transferSignal(options?: RequestOptions): AbortSignal | undefined {
110
+ const signal = options?.signal ?? options?.fetchOptions?.signal;
111
+ if (signal != null) return signal;
112
+ if (options?.timeoutMs != null && options.timeoutMs > 0) {
113
+ return AbortSignal.timeout(options.timeoutMs);
114
+ }
115
+ return undefined;
116
+ }
117
+
118
+ function withTransferSignal(
119
+ init: RequestInit,
120
+ options?: RequestOptions,
121
+ ): RequestInit {
122
+ const signal = transferSignal(options);
123
+ return signal === undefined ? init : { ...init, signal };
124
+ }
125
+
126
+ function serializeBulkUpsertPayload(
127
+ docs: UpsertDocsInput["docs"],
128
+ ): { jsonString: string; sizeBytes: number } {
129
+ try {
130
+ const jsonString = JSON.stringify({ docs });
131
+ if (jsonString === undefined) {
132
+ throw new TypeError("JSON.stringify returned undefined");
133
+ }
134
+ return {
135
+ jsonString,
136
+ sizeBytes: new TextEncoder().encode(jsonString).length,
137
+ };
138
+ } catch (cause) {
139
+ throw new UnexpectedClientError(
140
+ "Failed to serialize bulk upsert payload",
141
+ { cause },
142
+ );
143
+ }
144
+ }
145
+
146
+ function classifyTransferError(
147
+ message: string,
148
+ cause: unknown,
149
+ ): ConnectionError | RequestAbortedError | RequestTimeoutError | UnexpectedClientError {
150
+ if (isAbortError(cause)) {
151
+ return new RequestAbortedError("Request aborted by client", { cause });
152
+ }
153
+ if (isTimeoutError(cause)) {
154
+ return new RequestTimeoutError("Request timed out", { cause });
155
+ }
156
+ if (isConnectionError(cause)) {
157
+ return new ConnectionError("Unable to make request", { cause });
158
+ }
159
+ return new UnexpectedClientError(message, { cause });
160
+ }
161
+
162
+ async function readTransferText(
163
+ response: Response,
164
+ errorMessage: string,
165
+ ): Promise<string> {
166
+ try {
167
+ return await response.text();
168
+ } catch (cause) {
169
+ throw classifyTransferError(errorMessage, cause);
170
+ }
171
+ }
172
+
173
+ async function fetchDocsFromUrl<T>(
174
+ transferClient: HTTPClient,
175
+ docsUrl: string,
176
+ options?: RequestOptions,
177
+ ): Promise<T[]> {
178
+ let res: Response;
179
+ try {
180
+ res = await transferClient.request(
181
+ new Request(
182
+ docsUrl,
183
+ withTransferSignal({ method: "GET" }, options),
184
+ ),
185
+ );
186
+ } catch (cause) {
187
+ throw classifyTransferError("Failed to fetch documents from URL", cause);
188
+ }
189
+ const text = await readTransferText(
190
+ res,
191
+ "Failed to read documents from URL",
192
+ );
91
193
  if (!res.ok) {
92
- const text = await res.text();
93
194
  throw new UnexpectedClientError(
94
195
  `Failed to fetch documents from URL: ${res.status} ${res.statusText}${text ? ` - ${text}` : ""}`,
95
196
  );
96
197
  }
97
- const text = await res.text();
98
198
  if (text.trim() === "") {
99
199
  return [];
100
200
  }
@@ -145,6 +245,11 @@ export type LambdaDBClientOptions = SDKOptions & {
145
245
  * Project name (path segment under /projects/). Default: "playground"
146
246
  */
147
247
  projectName?: string;
248
+ /**
249
+ * Separate unauthenticated transport for presigned uploads and downloads.
250
+ * API authentication and API request headers are never copied to it.
251
+ */
252
+ transferClient?: HTTPClient;
148
253
  };
149
254
 
150
255
  function normalizeClientOptions(
@@ -155,8 +260,10 @@ function normalizeClientOptions(
155
260
  projectName = DEFAULT_PROJECT_NAME,
156
261
  serverURL,
157
262
  projectHost,
263
+ transferClient: _transferClient,
158
264
  ...rest
159
265
  } = options;
266
+ void _transferClient;
160
267
 
161
268
  if (serverURL !== undefined && serverURL !== null) {
162
269
  return { ...rest, serverURL };
@@ -175,8 +282,11 @@ function normalizeClientOptions(
175
282
  * `LambdaDB` when you want to avoid passing collectionName on every call.
176
283
  */
177
284
  export class LambdaDBClient extends LambdaDBCore {
178
- constructor(options?: LambdaDBClientOptions) {
285
+ readonly #transferClient: HTTPClient;
286
+
287
+ constructor(options: LambdaDBClientOptions = {}) {
179
288
  super(normalizeClientOptions(options));
289
+ this.#transferClient = options.transferClient ?? new HTTPClient();
180
290
  }
181
291
 
182
292
  /**
@@ -184,7 +294,7 @@ export class LambdaDBClient extends LambdaDBCore {
184
294
  * use this collection name; you do not pass it again.
185
295
  */
186
296
  collection(collectionName: string): CollectionHandle {
187
- return new CollectionHandle(this, collectionName);
297
+ return new CollectionHandle(this, collectionName, this.#transferClient);
188
298
  }
189
299
 
190
300
  /**
@@ -256,8 +366,10 @@ export class LambdaDBClient extends LambdaDBCore {
256
366
  async createCollection(
257
367
  request: CreateCollectionInput,
258
368
  options?: RequestOptions,
259
- ) {
260
- return unwrapAsync(collectionsCreate(this, request, options));
369
+ ): Promise<CreateCollectionResponseWithDates> {
370
+ return createCollectionResponseWithDates(
371
+ await unwrapAsync(collectionsCreate(this, request, options)),
372
+ );
261
373
  }
262
374
 
263
375
  /**
@@ -266,8 +378,10 @@ export class LambdaDBClient extends LambdaDBCore {
266
378
  async createCollectionSafe(
267
379
  request: CreateCollectionInput,
268
380
  options?: RequestOptions,
269
- ): Promise<Result<CreateCollectionResponse, CreateCollectionError>> {
270
- return await collectionsCreate(this, request, options);
381
+ ): Promise<Result<CreateCollectionResponseWithDates, CreateCollectionError>> {
382
+ const result = await collectionsCreate(this, request, options);
383
+ if (!result.ok) return result;
384
+ return OK(createCollectionResponseWithDates(result.value));
271
385
  }
272
386
  }
273
387
 
@@ -278,8 +392,13 @@ export class CollectionHandle {
278
392
  constructor(
279
393
  private readonly client: LambdaDBCore,
280
394
  readonly collectionName: string,
395
+ private readonly transferClient: HTTPClient = new HTTPClient(),
281
396
  ) {}
282
397
 
398
+ readonly branches = new CollectionBranches(this.client, this.collectionName);
399
+ readonly tags = new CollectionTags(this.client, this.collectionName);
400
+ readonly aliases = new CollectionAliases(this.client, this.collectionName);
401
+
283
402
  /**
284
403
  * Get metadata of this collection. Timestamp fields are returned as Date.
285
404
  */
@@ -311,8 +430,8 @@ export class CollectionHandle {
311
430
  async update(
312
431
  requestBody: UpdateCollectionInput,
313
432
  options?: RequestOptions,
314
- ) {
315
- return unwrapAsync(
433
+ ): Promise<UpdateCollectionResponseWithDates> {
434
+ const response = await unwrapAsync(
316
435
  collectionsUpdate(
317
436
  this.client,
318
437
  {
@@ -322,6 +441,7 @@ export class CollectionHandle {
322
441
  options,
323
442
  ),
324
443
  );
444
+ return updateCollectionResponseWithDates(response);
325
445
  }
326
446
 
327
447
  /**
@@ -330,12 +450,14 @@ export class CollectionHandle {
330
450
  async updateSafe(
331
451
  requestBody: UpdateCollectionInput,
332
452
  options?: RequestOptions,
333
- ): Promise<Result<UpdateCollectionResponse, UpdateCollectionError>> {
334
- return await collectionsUpdate(
453
+ ): Promise<Result<UpdateCollectionResponseWithDates, UpdateCollectionError>> {
454
+ const result = await collectionsUpdate(
335
455
  this.client,
336
456
  { collectionName: this.collectionName, requestBody },
337
457
  options,
338
458
  );
459
+ if (!result.ok) return result;
460
+ return OK(updateCollectionResponseWithDates(result.value));
339
461
  }
340
462
 
341
463
  /**
@@ -385,7 +507,9 @@ export class CollectionHandle {
385
507
  );
386
508
  if (!result.isDocsInline && result.docsUrl) {
387
509
  const docs = await fetchDocsFromUrl<QueryCollectionDoc>(
510
+ this.transferClient,
388
511
  result.docsUrl,
512
+ options,
389
513
  );
390
514
  return { ...result, docs, isDocsInline: true };
391
515
  }
@@ -408,7 +532,11 @@ export class CollectionHandle {
408
532
  if (!result.ok) return result;
409
533
  if (!result.value.isDocsInline && result.value.docsUrl) {
410
534
  try {
411
- const docs = await fetchDocsFromUrl<QueryCollectionDoc>(result.value.docsUrl);
535
+ const docs = await fetchDocsFromUrl<QueryCollectionDoc>(
536
+ this.transferClient,
537
+ result.value.docsUrl,
538
+ options,
539
+ );
412
540
  return OK({ ...result.value, docs, isDocsInline: true });
413
541
  } catch (e) {
414
542
  return ERR(e as QueryCollectionError);
@@ -417,16 +545,21 @@ export class CollectionHandle {
417
545
  return result;
418
546
  }
419
547
 
420
- readonly docs: CollectionDocs = new CollectionDocs(this.client, this.collectionName);
548
+ readonly docs: CollectionDocs = new CollectionDocs(
549
+ this.client,
550
+ this.collectionName,
551
+ this.transferClient,
552
+ );
421
553
  }
422
554
 
423
555
  /**
424
556
  * Document operations scoped to a collection.
425
557
  */
426
- class CollectionDocs {
558
+ export class CollectionDocs {
427
559
  constructor(
428
560
  private readonly client: LambdaDBCore,
429
561
  private readonly collectionName: string,
562
+ private readonly transferClient: HTTPClient,
430
563
  ) {}
431
564
 
432
565
  /**
@@ -438,15 +571,46 @@ class CollectionDocs {
438
571
  params?: ListDocsInput,
439
572
  options?: RequestOptions,
440
573
  ) {
574
+ const useExtendedList = params?.filter != null
575
+ || params?.partitionFilter != null
576
+ || params?.fields != null;
441
577
  const result = await unwrapAsync(
442
- collectionsDocsListDocs(
443
- this.client,
444
- { collectionName: this.collectionName, ...params },
445
- options,
446
- ),
578
+ useExtendedList
579
+ ? collectionsDocsListDocsExtended(
580
+ this.client,
581
+ {
582
+ collectionName: this.collectionName,
583
+ requestBody: {
584
+ size: params?.size,
585
+ pageToken: params?.pageToken,
586
+ filter: params?.filter,
587
+ partitionFilter: params?.partitionFilter,
588
+ fields: params?.fields,
589
+ includeVectors: params?.includeVectors,
590
+ ref: params?.ref,
591
+ },
592
+ },
593
+ options,
594
+ )
595
+ : collectionsDocsListDocs(
596
+ this.client,
597
+ {
598
+ collectionName: this.collectionName,
599
+ size: params?.size,
600
+ pageToken: params?.pageToken,
601
+ includeVectors: params?.includeVectors,
602
+ refKind: params?.ref?.kind,
603
+ refName: params?.ref?.name,
604
+ },
605
+ options,
606
+ ),
447
607
  );
448
608
  if (!result.isDocsInline && result.docsUrl) {
449
- const docs = await fetchDocsFromUrl<ListDocsDoc>(result.docsUrl);
609
+ const docs = await fetchDocsFromUrl<ListDocsDoc>(
610
+ this.transferClient,
611
+ result.docsUrl,
612
+ options,
613
+ );
450
614
  return { ...result, docs, isDocsInline: true };
451
615
  }
452
616
  return result;
@@ -460,15 +624,46 @@ class CollectionDocs {
460
624
  params?: ListDocsInput,
461
625
  options?: RequestOptions,
462
626
  ): Promise<Result<ListDocsResponse, ListDocsError>> {
463
- const result = await collectionsDocsListDocs(
464
- this.client,
465
- { collectionName: this.collectionName, ...params },
466
- options,
467
- );
627
+ const useExtendedList = params?.filter != null
628
+ || params?.partitionFilter != null
629
+ || params?.fields != null;
630
+ const result = useExtendedList
631
+ ? await collectionsDocsListDocsExtended(
632
+ this.client,
633
+ {
634
+ collectionName: this.collectionName,
635
+ requestBody: {
636
+ size: params?.size,
637
+ pageToken: params?.pageToken,
638
+ filter: params?.filter,
639
+ partitionFilter: params?.partitionFilter,
640
+ fields: params?.fields,
641
+ includeVectors: params?.includeVectors,
642
+ ref: params?.ref,
643
+ },
644
+ },
645
+ options,
646
+ )
647
+ : await collectionsDocsListDocs(
648
+ this.client,
649
+ {
650
+ collectionName: this.collectionName,
651
+ size: params?.size,
652
+ pageToken: params?.pageToken,
653
+ includeVectors: params?.includeVectors,
654
+ refKind: params?.ref?.kind,
655
+ refName: params?.ref?.name,
656
+ },
657
+ options,
658
+ );
468
659
  if (!result.ok) return result;
469
660
  if (!result.value.isDocsInline && result.value.docsUrl) {
470
661
  try {
471
- const docs = await fetchDocsFromUrl<ListDocsDoc>(result.value.docsUrl);
662
+ const docs = await fetchDocsFromUrl<ListDocsDoc>(
663
+ this.transferClient,
664
+ result.value.docsUrl,
665
+ options,
666
+ );
472
667
  return OK({ ...result.value, docs, isDocsInline: true });
473
668
  } catch (e) {
474
669
  return ERR(e as ListDocsError);
@@ -494,7 +689,15 @@ class CollectionDocs {
494
689
  options?: RequestOptions,
495
690
  ): AsyncGenerator<ListDocsResponse> {
496
691
  let pageToken: string | undefined = params?.pageToken;
497
- const baseParams: ListDocsInput = { size: params?.size, pageToken };
692
+ const baseParams: ListDocsInput = {
693
+ size: params?.size,
694
+ pageToken,
695
+ filter: params?.filter,
696
+ partitionFilter: params?.partitionFilter,
697
+ fields: params?.fields,
698
+ includeVectors: params?.includeVectors,
699
+ ref: params?.ref,
700
+ };
498
701
  while (true) {
499
702
  const page = await this.list({ ...baseParams, pageToken }, options);
500
703
  yield page;
@@ -642,7 +845,9 @@ class CollectionDocs {
642
845
  );
643
846
  if (!result.isDocsInline && result.docsUrl) {
644
847
  const docs = await fetchDocsFromUrl<FetchDocsDoc>(
848
+ this.transferClient,
645
849
  result.docsUrl,
850
+ options,
646
851
  );
647
852
  return { ...result, docs, isDocsInline: true };
648
853
  }
@@ -665,7 +870,11 @@ class CollectionDocs {
665
870
  if (!result.ok) return result;
666
871
  if (!result.value.isDocsInline && result.value.docsUrl) {
667
872
  try {
668
- const docs = await fetchDocsFromUrl<FetchDocsDoc>(result.value.docsUrl);
873
+ const docs = await fetchDocsFromUrl<FetchDocsDoc>(
874
+ this.transferClient,
875
+ result.value.docsUrl,
876
+ options,
877
+ );
669
878
  return OK({ ...result.value, docs, isDocsInline: true });
670
879
  } catch (e) {
671
880
  return ERR(e as FetchDocsError);
@@ -677,12 +886,28 @@ class CollectionDocs {
677
886
  /**
678
887
  * Get presigned URL and metadata for bulk upload (up to 200MB). Not supported for collections with managed embedding vector fields.
679
888
  */
680
- async getBulkUpsert(options?: RequestOptions) {
889
+ async getBulkUpsert(
890
+ options?: RequestOptions,
891
+ ): Promise<GetBulkUpsertDocsResponse>;
892
+ async getBulkUpsert(
893
+ input: GetBulkUpsertInput,
894
+ options?: RequestOptions,
895
+ ): Promise<GetBulkUpsertDocsResponse>;
896
+ async getBulkUpsert(
897
+ inputOrOptions?: GetBulkUpsertInput | RequestOptions,
898
+ options?: RequestOptions,
899
+ ): Promise<GetBulkUpsertDocsResponse> {
900
+ const hasInput = options !== undefined
901
+ || (inputOrOptions != null && "branch" in inputOrOptions);
902
+ const input = hasInput ? inputOrOptions as GetBulkUpsertInput : {};
903
+ const requestOptions = hasInput
904
+ ? options
905
+ : inputOrOptions as RequestOptions | undefined;
681
906
  return unwrapAsync(
682
907
  collectionsDocsGetBulkUpsert(
683
908
  this.client,
684
- { collectionName: this.collectionName },
685
- options,
909
+ { collectionName: this.collectionName, branch: input.branch },
910
+ requestOptions,
686
911
  ),
687
912
  );
688
913
  }
@@ -692,11 +917,25 @@ class CollectionDocs {
692
917
  */
693
918
  async getBulkUpsertSafe(
694
919
  options?: RequestOptions,
920
+ ): Promise<Result<GetBulkUpsertDocsResponse, GetBulkUpsertDocsError>>;
921
+ async getBulkUpsertSafe(
922
+ input: GetBulkUpsertInput,
923
+ options?: RequestOptions,
924
+ ): Promise<Result<GetBulkUpsertDocsResponse, GetBulkUpsertDocsError>>;
925
+ async getBulkUpsertSafe(
926
+ inputOrOptions?: GetBulkUpsertInput | RequestOptions,
927
+ options?: RequestOptions,
695
928
  ): Promise<Result<GetBulkUpsertDocsResponse, GetBulkUpsertDocsError>> {
929
+ const hasInput = options !== undefined
930
+ || (inputOrOptions != null && "branch" in inputOrOptions);
931
+ const input = hasInput ? inputOrOptions as GetBulkUpsertInput : {};
932
+ const requestOptions = hasInput
933
+ ? options
934
+ : inputOrOptions as RequestOptions | undefined;
696
935
  return await collectionsDocsGetBulkUpsert(
697
936
  this.client,
698
- { collectionName: this.collectionName },
699
- options,
937
+ { collectionName: this.collectionName, branch: input.branch },
938
+ requestOptions,
700
939
  );
701
940
  }
702
941
 
@@ -742,36 +981,50 @@ class CollectionDocs {
742
981
  body: UpsertDocsInput,
743
982
  options?: RequestOptions,
744
983
  ): Promise<MessageResponse> {
745
- const { url, type, httpMethod, objectKey, sizeLimitBytes } = await this.getBulkUpsert(options);
984
+ const { url, type, httpMethod, objectKey, sizeLimitBytes, headers } =
985
+ await this.getBulkUpsert({ branch: body.branch }, options);
746
986
 
747
- const payload = { docs: body.docs };
748
- const jsonString = JSON.stringify(payload);
749
- const sizeBytes = new TextEncoder().encode(jsonString).length;
987
+ const { jsonString, sizeBytes } = serializeBulkUpsertPayload(body.docs);
750
988
  if (sizeBytes > sizeLimitBytes) {
751
989
  throw new Error(
752
990
  `Bulk upsert payload size (${sizeBytes} bytes) exceeds limit (${sizeLimitBytes} bytes)`,
753
991
  );
754
992
  }
755
993
 
756
- const putResponse = await fetch(url, {
757
- method: httpMethod,
758
- headers: { "Content-Type": type },
759
- body: jsonString,
760
- });
994
+ const uploadHeaders = new Headers(headers);
995
+ uploadHeaders.set("Content-Type", type);
996
+ let putResponse: Response;
997
+ try {
998
+ putResponse = await this.transferClient.request(
999
+ new Request(
1000
+ url,
1001
+ withTransferSignal({
1002
+ method: httpMethod,
1003
+ headers: uploadHeaders,
1004
+ body: jsonString,
1005
+ }, options),
1006
+ ),
1007
+ );
1008
+ } catch (cause) {
1009
+ throw classifyTransferError("Bulk upsert upload failed", cause);
1010
+ }
761
1011
 
762
1012
  if (!putResponse.ok) {
763
- const text = await putResponse.text();
1013
+ const text = await readTransferText(
1014
+ putResponse,
1015
+ "Failed to read bulk upsert upload response",
1016
+ );
764
1017
  throw new Error(
765
1018
  `Bulk upsert upload failed: ${putResponse.status} ${putResponse.statusText}${text ? ` - ${text}` : ""}`,
766
1019
  );
767
1020
  }
768
1021
 
769
- return this.bulkUpsert({ objectKey }, options);
1022
+ return this.bulkUpsert({ objectKey, type, branch: body.branch }, options);
770
1023
  }
771
1024
 
772
1025
  /**
773
1026
  * Bulk upsert documents in one call (Safe: returns Result instead of throwing). Not supported for collections with managed embedding vector fields.
774
- * May return Error for local failures (payload size, upload). API errors use GetBulkUpsertDocsError or BulkUpsertDocsError.
1027
+ * May return Error for local failures (serialization, payload size, upload). API errors use GetBulkUpsertDocsError or BulkUpsertDocsError.
775
1028
  */
776
1029
  async bulkUpsertDocsSafe(
777
1030
  body: UpsertDocsInput,
@@ -782,13 +1035,28 @@ class CollectionDocs {
782
1035
  GetBulkUpsertDocsError | BulkUpsertDocsError | Error
783
1036
  >
784
1037
  > {
785
- const getResult = await this.getBulkUpsertSafe(options);
1038
+ const getResult = await this.getBulkUpsertSafe(
1039
+ { branch: body.branch },
1040
+ options,
1041
+ );
786
1042
  if (!getResult.ok) return getResult;
787
- const { url, type, httpMethod, objectKey, sizeLimitBytes } = getResult.value;
1043
+ const { url, type, httpMethod, objectKey, sizeLimitBytes, headers } =
1044
+ getResult.value;
788
1045
 
789
- const payload = { docs: body.docs };
790
- const jsonString = JSON.stringify(payload);
791
- const sizeBytes = new TextEncoder().encode(jsonString).length;
1046
+ let jsonString: string;
1047
+ let sizeBytes: number;
1048
+ try {
1049
+ ({ jsonString, sizeBytes } = serializeBulkUpsertPayload(body.docs));
1050
+ } catch (cause) {
1051
+ return ERR(
1052
+ cause instanceof Error
1053
+ ? cause
1054
+ : new UnexpectedClientError(
1055
+ "Failed to serialize bulk upsert payload",
1056
+ { cause },
1057
+ ),
1058
+ );
1059
+ }
792
1060
  if (sizeBytes > sizeLimitBytes) {
793
1061
  return ERR(
794
1062
  new Error(
@@ -797,14 +1065,41 @@ class CollectionDocs {
797
1065
  );
798
1066
  }
799
1067
 
800
- const putResponse = await fetch(url, {
801
- method: httpMethod,
802
- headers: { "Content-Type": type },
803
- body: jsonString,
804
- });
1068
+ let putResponse: Response;
1069
+ try {
1070
+ const uploadHeaders = new Headers(headers);
1071
+ uploadHeaders.set("Content-Type", type);
1072
+ putResponse = await this.transferClient.request(
1073
+ new Request(
1074
+ url,
1075
+ withTransferSignal({
1076
+ method: httpMethod,
1077
+ headers: uploadHeaders,
1078
+ body: jsonString,
1079
+ }, options),
1080
+ ),
1081
+ );
1082
+ } catch (cause) {
1083
+ return ERR(classifyTransferError("Bulk upsert upload failed", cause));
1084
+ }
805
1085
 
806
1086
  if (!putResponse.ok) {
807
- const text = await putResponse.text();
1087
+ let text: string;
1088
+ try {
1089
+ text = await readTransferText(
1090
+ putResponse,
1091
+ "Failed to read bulk upsert upload response",
1092
+ );
1093
+ } catch (cause) {
1094
+ return ERR(
1095
+ cause instanceof Error
1096
+ ? cause
1097
+ : new UnexpectedClientError(
1098
+ "Failed to read bulk upsert upload response",
1099
+ { cause },
1100
+ ),
1101
+ );
1102
+ }
808
1103
  return ERR(
809
1104
  new Error(
810
1105
  `Bulk upsert upload failed: ${putResponse.status} ${putResponse.statusText}${text ? ` - ${text}` : ""}`,
@@ -812,6 +1107,6 @@ class CollectionDocs {
812
1107
  );
813
1108
  }
814
1109
 
815
- return this.bulkUpsertSafe({ objectKey }, options);
1110
+ return this.bulkUpsertSafe({ objectKey, type, branch: body.branch }, options);
816
1111
  }
817
1112
  }