@functional-systems/lambdadb 0.3.1 → 0.3.3

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 (123) hide show
  1. package/README.md +1 -1
  2. package/dist/commonjs/client.d.ts +3 -0
  3. package/dist/commonjs/client.d.ts.map +1 -1
  4. package/dist/commonjs/client.js +49 -5
  5. package/dist/commonjs/client.js.map +1 -1
  6. package/dist/commonjs/lib/matchers.d.ts.map +1 -1
  7. package/dist/commonjs/lib/matchers.js +17 -1
  8. package/dist/commonjs/lib/matchers.js.map +1 -1
  9. package/dist/commonjs/lib/schemas.d.ts +6 -0
  10. package/dist/commonjs/lib/schemas.d.ts.map +1 -1
  11. package/dist/commonjs/lib/schemas.js +9 -0
  12. package/dist/commonjs/lib/schemas.js.map +1 -1
  13. package/dist/commonjs/models/collectionresponse.js +4 -4
  14. package/dist/commonjs/models/collectionresponse.js.map +1 -1
  15. package/dist/commonjs/models/errors/badrequesterror.d.ts.map +1 -1
  16. package/dist/commonjs/models/errors/badrequesterror.js +2 -1
  17. package/dist/commonjs/models/errors/badrequesterror.js.map +1 -1
  18. package/dist/commonjs/models/errors/internalservererror.d.ts.map +1 -1
  19. package/dist/commonjs/models/errors/internalservererror.js +2 -1
  20. package/dist/commonjs/models/errors/internalservererror.js.map +1 -1
  21. package/dist/commonjs/models/errors/resourcealreadyexistserror.d.ts.map +1 -1
  22. package/dist/commonjs/models/errors/resourcealreadyexistserror.js +2 -1
  23. package/dist/commonjs/models/errors/resourcealreadyexistserror.js.map +1 -1
  24. package/dist/commonjs/models/errors/resourcenotfounderror.d.ts.map +1 -1
  25. package/dist/commonjs/models/errors/resourcenotfounderror.js +2 -1
  26. package/dist/commonjs/models/errors/resourcenotfounderror.js.map +1 -1
  27. package/dist/commonjs/models/errors/toomanyrequestserror.d.ts.map +1 -1
  28. package/dist/commonjs/models/errors/toomanyrequestserror.js +2 -1
  29. package/dist/commonjs/models/errors/toomanyrequestserror.js.map +1 -1
  30. package/dist/commonjs/models/errors/unauthenticatederror.d.ts.map +1 -1
  31. package/dist/commonjs/models/errors/unauthenticatederror.js +2 -1
  32. package/dist/commonjs/models/errors/unauthenticatederror.js.map +1 -1
  33. package/dist/commonjs/models/indexconfigsunion.js +2 -2
  34. package/dist/commonjs/models/indexconfigsunion.js.map +1 -1
  35. package/dist/commonjs/models/operations/fetchdocs.js +1 -1
  36. package/dist/commonjs/models/operations/fetchdocs.js.map +1 -1
  37. package/dist/commonjs/models/operations/getbulkupsertdocs.js +3 -3
  38. package/dist/commonjs/models/operations/getbulkupsertdocs.js.map +1 -1
  39. package/dist/commonjs/models/operations/listcollections.js +1 -1
  40. package/dist/commonjs/models/operations/listcollections.js.map +1 -1
  41. package/dist/commonjs/models/operations/listdocs.d.ts +17 -3
  42. package/dist/commonjs/models/operations/listdocs.d.ts.map +1 -1
  43. package/dist/commonjs/models/operations/listdocs.js +10 -3
  44. package/dist/commonjs/models/operations/listdocs.js.map +1 -1
  45. package/dist/commonjs/models/operations/querycollection.js +3 -3
  46. package/dist/commonjs/models/operations/querycollection.js.map +1 -1
  47. package/dist/commonjs/models/partitionconfig.js +3 -3
  48. package/dist/commonjs/models/partitionconfig.js.map +1 -1
  49. package/dist/commonjs/types/public.d.ts +1 -1
  50. package/dist/commonjs/types/public.d.ts.map +1 -1
  51. package/dist/commonjs/types/public.js.map +1 -1
  52. package/dist/esm/client.d.ts +3 -0
  53. package/dist/esm/client.d.ts.map +1 -1
  54. package/dist/esm/client.js +49 -5
  55. package/dist/esm/client.js.map +1 -1
  56. package/dist/esm/lib/matchers.d.ts.map +1 -1
  57. package/dist/esm/lib/matchers.js +17 -1
  58. package/dist/esm/lib/matchers.js.map +1 -1
  59. package/dist/esm/lib/schemas.d.ts +6 -0
  60. package/dist/esm/lib/schemas.d.ts.map +1 -1
  61. package/dist/esm/lib/schemas.js +9 -1
  62. package/dist/esm/lib/schemas.js.map +1 -1
  63. package/dist/esm/models/collectionresponse.js +5 -5
  64. package/dist/esm/models/collectionresponse.js.map +1 -1
  65. package/dist/esm/models/errors/badrequesterror.d.ts.map +1 -1
  66. package/dist/esm/models/errors/badrequesterror.js +2 -1
  67. package/dist/esm/models/errors/badrequesterror.js.map +1 -1
  68. package/dist/esm/models/errors/internalservererror.d.ts.map +1 -1
  69. package/dist/esm/models/errors/internalservererror.js +2 -1
  70. package/dist/esm/models/errors/internalservererror.js.map +1 -1
  71. package/dist/esm/models/errors/resourcealreadyexistserror.d.ts.map +1 -1
  72. package/dist/esm/models/errors/resourcealreadyexistserror.js +2 -1
  73. package/dist/esm/models/errors/resourcealreadyexistserror.js.map +1 -1
  74. package/dist/esm/models/errors/resourcenotfounderror.d.ts.map +1 -1
  75. package/dist/esm/models/errors/resourcenotfounderror.js +2 -1
  76. package/dist/esm/models/errors/resourcenotfounderror.js.map +1 -1
  77. package/dist/esm/models/errors/toomanyrequestserror.d.ts.map +1 -1
  78. package/dist/esm/models/errors/toomanyrequestserror.js +2 -1
  79. package/dist/esm/models/errors/toomanyrequestserror.js.map +1 -1
  80. package/dist/esm/models/errors/unauthenticatederror.d.ts.map +1 -1
  81. package/dist/esm/models/errors/unauthenticatederror.js +2 -1
  82. package/dist/esm/models/errors/unauthenticatederror.js.map +1 -1
  83. package/dist/esm/models/indexconfigsunion.js +3 -3
  84. package/dist/esm/models/indexconfigsunion.js.map +1 -1
  85. package/dist/esm/models/operations/fetchdocs.js +2 -2
  86. package/dist/esm/models/operations/fetchdocs.js.map +1 -1
  87. package/dist/esm/models/operations/getbulkupsertdocs.js +4 -4
  88. package/dist/esm/models/operations/getbulkupsertdocs.js.map +1 -1
  89. package/dist/esm/models/operations/listcollections.js +2 -2
  90. package/dist/esm/models/operations/listcollections.js.map +1 -1
  91. package/dist/esm/models/operations/listdocs.d.ts +17 -3
  92. package/dist/esm/models/operations/listdocs.d.ts.map +1 -1
  93. package/dist/esm/models/operations/listdocs.js +10 -3
  94. package/dist/esm/models/operations/listdocs.js.map +1 -1
  95. package/dist/esm/models/operations/querycollection.js +4 -4
  96. package/dist/esm/models/operations/querycollection.js.map +1 -1
  97. package/dist/esm/models/partitionconfig.js +4 -4
  98. package/dist/esm/models/partitionconfig.js.map +1 -1
  99. package/dist/esm/types/public.d.ts +1 -1
  100. package/dist/esm/types/public.d.ts.map +1 -1
  101. package/dist/esm/types/public.js.map +1 -1
  102. package/package.json +2 -2
  103. package/src/client.ts +53 -5
  104. package/src/lib/matchers.ts +18 -1
  105. package/src/lib/schemas.ts +12 -0
  106. package/src/models/collectionresponse.ts +5 -5
  107. package/src/models/errors/badrequesterror.ts +2 -1
  108. package/src/models/errors/internalservererror.ts +2 -1
  109. package/src/models/errors/resourcealreadyexistserror.ts +2 -1
  110. package/src/models/errors/resourcenotfounderror.ts +2 -1
  111. package/src/models/errors/toomanyrequestserror.ts +2 -1
  112. package/src/models/errors/unauthenticatederror.ts +2 -1
  113. package/src/models/indexconfigsunion.ts +3 -3
  114. package/src/models/operations/fetchdocs.ts +2 -2
  115. package/src/models/operations/getbulkupsertdocs.ts +4 -4
  116. package/src/models/operations/listcollections.ts +2 -2
  117. package/src/models/operations/listdocs.ts +29 -4
  118. package/src/models/operations/querycollection.ts +4 -4
  119. package/src/models/partitionconfig.ts +4 -4
  120. package/src/types/public.ts +4 -1
  121. package/test/null-response.test.mjs +73 -0
  122. package/test/public-api.test.mjs +210 -0
  123. package/.devcontainer/devcontainer.json +0 -45
@@ -1 +1 @@
1
- {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/types/public.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0EH;;GAEG;AACH,MAAM,UAAU,2BAA2B,CACzC,CAA0B;IAE1B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAgC,EAAE,GAAG,IAAI,EAAE,CAAC;IACrD,IAAI,SAAS,IAAI,IAAI;QAAE,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAClE,IAAI,SAAS,IAAI,IAAI;QAAE,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAClE,IAAI,aAAa,IAAI,IAAI;QACvB,GAAG,CAAC,aAAa,GAAG,IAAI,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gCAAgC,CAAC,GAGhD;IACC,MAAM,GAAG,GAAqC;QAC5C,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,2BAA2B,CAAC;KAC9D,CAAC;IACF,IAAI,GAAG,CAAC,aAAa,KAAK,SAAS;QAAE,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC;IAC3E,OAAO,GAAG,CAAC;AACb,CAAC;AAOD,uEAAuE;AACvE,MAAM,UAAU,8BAA8B,CAAC,GAE9C;IACC,OAAO,EAAE,UAAU,EAAE,2BAA2B,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;AACrE,CAAC"}
1
+ {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/types/public.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6EH;;GAEG;AACH,MAAM,UAAU,2BAA2B,CACzC,CAA0B;IAE1B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAgC,EAAE,GAAG,IAAI,EAAE,CAAC;IACrD,IAAI,SAAS,IAAI,IAAI;QAAE,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAClE,IAAI,SAAS,IAAI,IAAI;QAAE,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAClE,IAAI,aAAa,IAAI,IAAI;QACvB,GAAG,CAAC,aAAa,GAAG,IAAI,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gCAAgC,CAAC,GAGhD;IACC,MAAM,GAAG,GAAqC;QAC5C,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,2BAA2B,CAAC;KAC9D,CAAC;IACF,IAAI,GAAG,CAAC,aAAa,KAAK,SAAS;QAAE,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC;IAC3E,OAAO,GAAG,CAAC;AACb,CAAC;AAOD,uEAAuE;AACvE,MAAM,UAAU,8BAA8B,CAAC,GAE9C;IACC,OAAO,EAAE,UAAU,EAAE,2BAA2B,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;AACrE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@functional-systems/lambdadb",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "author": "Functional Systems, Inc.",
5
5
  "homepage": "https://github.com/lambdadb/lambdadb-typescript-client#readme",
6
6
  "license": "Apache-2.0",
@@ -28,7 +28,7 @@
28
28
  "scripts": {
29
29
  "lint": "eslint --cache --max-warnings=0 src",
30
30
  "build": "tshy",
31
- "test": "echo \"No tests yet\"",
31
+ "test": "npm run build && node --test test/*.test.mjs",
32
32
  "prepublishOnly": "npm run build"
33
33
  },
34
34
  "devDependencies": {
package/src/client.ts CHANGED
@@ -26,6 +26,7 @@ import { collectionsDocsListDocs } from "./funcs/collectionsDocsListDocs.js";
26
26
  import { collectionsDocsUpdate } from "./funcs/collectionsDocsUpdate.js";
27
27
  import { collectionsDocsUpsert } from "./funcs/collectionsDocsUpsert.js";
28
28
  import type { RequestOptions } from "./lib/sdks.js";
29
+ import { UnexpectedClientError } from "./models/errors/httpclienterrors.js";
29
30
  import { unwrapAsync, OK, ERR } from "./types/fp.js";
30
31
  import type { Result } from "./types/fp.js";
31
32
  import type * as operations from "./models/operations/index.js";
@@ -40,6 +41,7 @@ import {
40
41
  type QueryCollectionDoc,
41
42
  type ListDocsInput,
42
43
  type ListDocsResponse,
44
+ type ListDocsDoc,
43
45
  type ListCollectionsInput,
44
46
  type ListCollectionsResponseWithDates,
45
47
  type GetCollectionResponseWithDates,
@@ -88,12 +90,40 @@ async function fetchDocsFromUrl<T>(docsUrl: string): Promise<T[]> {
88
90
  const res = await fetch(docsUrl);
89
91
  if (!res.ok) {
90
92
  const text = await res.text();
91
- throw new Error(
93
+ throw new UnexpectedClientError(
92
94
  `Failed to fetch documents from URL: ${res.status} ${res.statusText}${text ? ` - ${text}` : ""}`,
93
95
  );
94
96
  }
95
- const json = (await res.json()) as { docs?: T[] };
96
- return json.docs ?? [];
97
+ const text = await res.text();
98
+ if (text.trim() === "") {
99
+ return [];
100
+ }
101
+
102
+ let payload: unknown;
103
+ try {
104
+ payload = JSON.parse(text);
105
+ } catch (cause) {
106
+ throw new UnexpectedClientError(
107
+ "Failed to parse documents from URL as JSON",
108
+ { cause },
109
+ );
110
+ }
111
+
112
+ if (payload == null) {
113
+ return [];
114
+ }
115
+ if (typeof payload !== "object" || Array.isArray(payload)) {
116
+ throw new UnexpectedClientError("Unexpected document payload shape from URL");
117
+ }
118
+
119
+ const { docs } = payload as { docs?: unknown };
120
+ if (docs == null) {
121
+ return [];
122
+ }
123
+ if (!Array.isArray(docs)) {
124
+ throw new UnexpectedClientError("Unexpected docs payload shape from URL");
125
+ }
126
+ return docs as T[];
97
127
  }
98
128
 
99
129
  /** Default base URL for the LambdaDB API. */
@@ -401,32 +431,50 @@ class CollectionDocs {
401
431
 
402
432
  /**
403
433
  * List documents in the collection.
434
+ * When the API returns docs via docsUrl (isDocsInline false), documents are
435
+ * fetched from the presigned URL automatically so the response always has docs.
404
436
  */
405
437
  async list(
406
438
  params?: ListDocsInput,
407
439
  options?: RequestOptions,
408
440
  ) {
409
- return unwrapAsync(
441
+ const result = await unwrapAsync(
410
442
  collectionsDocsListDocs(
411
443
  this.client,
412
444
  { collectionName: this.collectionName, ...params },
413
445
  options,
414
446
  ),
415
447
  );
448
+ if (!result.isDocsInline && result.docsUrl) {
449
+ const docs = await fetchDocsFromUrl<ListDocsDoc>(result.docsUrl);
450
+ return { ...result, docs, isDocsInline: true };
451
+ }
452
+ return result;
416
453
  }
417
454
 
418
455
  /**
419
456
  * List documents in the collection (Safe: returns Result instead of throwing).
457
+ * When the API returns docs via docsUrl, documents are fetched from the presigned URL automatically.
420
458
  */
421
459
  async listSafe(
422
460
  params?: ListDocsInput,
423
461
  options?: RequestOptions,
424
462
  ): Promise<Result<ListDocsResponse, ListDocsError>> {
425
- return await collectionsDocsListDocs(
463
+ const result = await collectionsDocsListDocs(
426
464
  this.client,
427
465
  { collectionName: this.collectionName, ...params },
428
466
  options,
429
467
  );
468
+ if (!result.ok) return result;
469
+ if (!result.value.isDocsInline && result.value.docsUrl) {
470
+ try {
471
+ const docs = await fetchDocsFromUrl<ListDocsDoc>(result.value.docsUrl);
472
+ return OK({ ...result.value, docs, isDocsInline: true });
473
+ } catch (e) {
474
+ return ERR(e as ListDocsError);
475
+ }
476
+ }
477
+ return result;
430
478
  }
431
479
 
432
480
  /**
@@ -224,7 +224,24 @@ export function match<T, E>(
224
224
  switch (encoding) {
225
225
  case "json":
226
226
  body = await response.text();
227
- raw = JSON.parse(body);
227
+ if (body.trim() === "") {
228
+ raw = undefined;
229
+ break;
230
+ }
231
+ try {
232
+ raw = JSON.parse(body);
233
+ } catch (cause) {
234
+ return [ERR(
235
+ new ResponseValidationError("Response validation failed", {
236
+ cause,
237
+ rawValue: body,
238
+ rawMessage: "Response validation failed",
239
+ request,
240
+ response,
241
+ body,
242
+ }),
243
+ ), body];
244
+ }
228
245
  break;
229
246
  case "jsonl":
230
247
  raw = response.body;
@@ -4,6 +4,7 @@
4
4
 
5
5
  import {
6
6
  output,
7
+ preprocess,
7
8
  ZodEffects,
8
9
  ZodError,
9
10
  ZodObject,
@@ -50,6 +51,17 @@ export function safeParse<Inp, Out>(
50
51
  }
51
52
  }
52
53
 
54
+ /**
55
+ * Converts explicit JSON nulls to undefined before applying the provided
56
+ * schema. This lets inbound response schemas tolerate APIs that return
57
+ * `null` instead of omitting optional fields.
58
+ */
59
+ export function nullToUndefined<T extends ZodTypeAny>(
60
+ schema: T,
61
+ ): ZodEffects<T, output<T>, unknown> {
62
+ return preprocess((value) => value === null ? undefined : value, schema);
63
+ }
64
+
53
65
  export function collectExtraKeys<
54
66
  Shape extends ZodRawShape,
55
67
  Catchall extends ZodTypeAny,
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
- import { safeParse } from "../lib/schemas.js";
6
+ import { nullToUndefined, safeParse } from "../lib/schemas.js";
7
7
  import { Result as SafeParseResult } from "../types/fp.js";
8
8
  import { SDKValidationError } from "./errors/sdkvalidationerror.js";
9
9
  import {
@@ -74,12 +74,12 @@ export const CollectionResponse$inboundSchema: z.ZodType<
74
74
  projectName: z.string(),
75
75
  collectionName: z.string(),
76
76
  indexConfigs: z.record(IndexConfigsUnion$inboundSchema),
77
- partitionConfig: PartitionConfig$inboundSchema.optional(),
77
+ partitionConfig: nullToUndefined(PartitionConfig$inboundSchema.optional()),
78
78
  numPartitions: z.number().int(),
79
79
  numDocs: z.number().int(),
80
- sourceProjectName: z.string().optional(),
81
- sourceCollectionName: z.string().optional(),
82
- sourceCollectionVersionId: z.string().optional(),
80
+ sourceProjectName: nullToUndefined(z.string().optional()),
81
+ sourceCollectionName: nullToUndefined(z.string().optional()),
82
+ sourceCollectionVersionId: nullToUndefined(z.string().optional()),
83
83
  collectionStatus: Status$inboundSchema,
84
84
  createdAt: z.number().int(),
85
85
  updatedAt: z.number().int(),
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
+ import { nullToUndefined } from "../../lib/schemas.js";
6
7
  import { LambdaDBError } from "./lambdadberror.js";
7
8
 
8
9
  export type BadRequestErrorData = {
@@ -31,7 +32,7 @@ export const BadRequestError$inboundSchema: z.ZodType<
31
32
  z.ZodTypeDef,
32
33
  unknown
33
34
  > = z.object({
34
- message: z.string().optional(),
35
+ message: nullToUndefined(z.string().optional()),
35
36
  request$: z.instanceof(Request),
36
37
  response$: z.instanceof(Response),
37
38
  body$: z.string(),
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
+ import { nullToUndefined } from "../../lib/schemas.js";
6
7
  import { LambdaDBError } from "./lambdadberror.js";
7
8
 
8
9
  export type InternalServerErrorData = {
@@ -31,7 +32,7 @@ export const InternalServerError$inboundSchema: z.ZodType<
31
32
  z.ZodTypeDef,
32
33
  unknown
33
34
  > = z.object({
34
- message: z.string().optional(),
35
+ message: nullToUndefined(z.string().optional()),
35
36
  request$: z.instanceof(Request),
36
37
  response$: z.instanceof(Response),
37
38
  body$: z.string(),
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
+ import { nullToUndefined } from "../../lib/schemas.js";
6
7
  import { LambdaDBError } from "./lambdadberror.js";
7
8
 
8
9
  export type ResourceAlreadyExistsErrorData = {
@@ -31,7 +32,7 @@ export const ResourceAlreadyExistsError$inboundSchema: z.ZodType<
31
32
  z.ZodTypeDef,
32
33
  unknown
33
34
  > = z.object({
34
- message: z.string().optional(),
35
+ message: nullToUndefined(z.string().optional()),
35
36
  request$: z.instanceof(Request),
36
37
  response$: z.instanceof(Response),
37
38
  body$: z.string(),
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
+ import { nullToUndefined } from "../../lib/schemas.js";
6
7
  import { LambdaDBError } from "./lambdadberror.js";
7
8
 
8
9
  export type ResourceNotFoundErrorData = {
@@ -31,7 +32,7 @@ export const ResourceNotFoundError$inboundSchema: z.ZodType<
31
32
  z.ZodTypeDef,
32
33
  unknown
33
34
  > = z.object({
34
- message: z.string().optional(),
35
+ message: nullToUndefined(z.string().optional()),
35
36
  request$: z.instanceof(Request),
36
37
  response$: z.instanceof(Response),
37
38
  body$: z.string(),
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
+ import { nullToUndefined } from "../../lib/schemas.js";
6
7
  import { LambdaDBError } from "./lambdadberror.js";
7
8
 
8
9
  export type TooManyRequestsErrorData = {
@@ -31,7 +32,7 @@ export const TooManyRequestsError$inboundSchema: z.ZodType<
31
32
  z.ZodTypeDef,
32
33
  unknown
33
34
  > = z.object({
34
- message: z.string().optional(),
35
+ message: nullToUndefined(z.string().optional()),
35
36
  request$: z.instanceof(Request),
36
37
  response$: z.instanceof(Response),
37
38
  body$: z.string(),
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
+ import { nullToUndefined } from "../../lib/schemas.js";
6
7
  import { LambdaDBError } from "./lambdadberror.js";
7
8
 
8
9
  export type UnauthenticatedErrorData = {
@@ -31,7 +32,7 @@ export const UnauthenticatedError$inboundSchema: z.ZodType<
31
32
  z.ZodTypeDef,
32
33
  unknown
33
34
  > = z.object({
34
- message: z.string().optional(),
35
+ message: nullToUndefined(z.string().optional()),
35
36
  request$: z.instanceof(Request),
36
37
  response$: z.instanceof(Response),
37
38
  body$: z.string(),
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
- import { safeParse } from "../lib/schemas.js";
6
+ import { nullToUndefined, safeParse } from "../lib/schemas.js";
7
7
  import { ClosedEnum } from "../types/enums.js";
8
8
  import { Result as SafeParseResult } from "../types/fp.js";
9
9
  import { SDKValidationError } from "./errors/sdkvalidationerror.js";
@@ -182,7 +182,7 @@ export const IndexConfigsVector$inboundSchema: z.ZodType<
182
182
  > = z.object({
183
183
  type: z.literal("vector"),
184
184
  dimensions: z.number().int(),
185
- similarity: Similarity$inboundSchema.default("cosine"),
185
+ similarity: nullToUndefined(Similarity$inboundSchema.default("cosine")),
186
186
  });
187
187
  /** @internal */
188
188
  export type IndexConfigsVector$Outbound = {
@@ -233,7 +233,7 @@ export const IndexConfigsText$inboundSchema: z.ZodType<
233
233
  unknown
234
234
  > = z.object({
235
235
  type: z.literal("text"),
236
- analyzers: z.array(Analyzer$inboundSchema).optional(),
236
+ analyzers: nullToUndefined(z.array(Analyzer$inboundSchema).optional()),
237
237
  });
238
238
  /** @internal */
239
239
  export type IndexConfigsText$Outbound = {
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as z from "zod/v3";
6
6
  import { remap as remap$ } from "../../lib/primitives.js";
7
- import { safeParse } from "../../lib/schemas.js";
7
+ import { nullToUndefined, safeParse } from "../../lib/schemas.js";
8
8
  import { Result as SafeParseResult } from "../../types/fp.js";
9
9
  import { SDKValidationError } from "../errors/sdkvalidationerror.js";
10
10
  import * as models from "../index.js";
@@ -153,7 +153,7 @@ export const FetchDocsResponse$inboundSchema: z.ZodType<
153
153
  took: z.number().int(),
154
154
  docs: z.array(z.lazy(() => FetchDocsDoc$inboundSchema)),
155
155
  isDocsInline: z.boolean(),
156
- docsUrl: z.string().optional(),
156
+ docsUrl: nullToUndefined(z.string().optional()),
157
157
  });
158
158
 
159
159
  export function fetchDocsResponseFromJSON(
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
- import { safeParse } from "../../lib/schemas.js";
6
+ import { nullToUndefined, safeParse } from "../../lib/schemas.js";
7
7
  import { ClosedEnum } from "../../types/enums.js";
8
8
  import { Result as SafeParseResult } from "../../types/fp.js";
9
9
  import { SDKValidationError } from "../errors/sdkvalidationerror.js";
@@ -101,10 +101,10 @@ export const GetBulkUpsertDocsResponse$inboundSchema: z.ZodType<
101
101
  unknown
102
102
  > = z.object({
103
103
  url: z.string(),
104
- type: Type$inboundSchema.default("application/json"),
105
- httpMethod: HttpMethod$inboundSchema.default("PUT"),
104
+ type: nullToUndefined(Type$inboundSchema.default("application/json")),
105
+ httpMethod: nullToUndefined(HttpMethod$inboundSchema.default("PUT")),
106
106
  objectKey: z.string(),
107
- sizeLimitBytes: z.number().int().default(209715200),
107
+ sizeLimitBytes: nullToUndefined(z.number().int().default(209715200)),
108
108
  });
109
109
 
110
110
  export function getBulkUpsertDocsResponseFromJSON(
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
- import { safeParse } from "../../lib/schemas.js";
6
+ import { nullToUndefined, safeParse } from "../../lib/schemas.js";
7
7
  import { Result as SafeParseResult } from "../../types/fp.js";
8
8
  import { SDKValidationError } from "../errors/sdkvalidationerror.js";
9
9
  import * as models from "../index.js";
@@ -50,7 +50,7 @@ export const ListCollectionsResponse$inboundSchema: z.ZodType<
50
50
  unknown
51
51
  > = z.object({
52
52
  collections: z.array(models.CollectionResponse$inboundSchema),
53
- nextPageToken: z.string().optional(),
53
+ nextPageToken: nullToUndefined(z.string().optional()),
54
54
  });
55
55
 
56
56
  export function listCollectionsResponseFromJSON(
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
- import { safeParse } from "../../lib/schemas.js";
6
+ import { nullToUndefined, safeParse } from "../../lib/schemas.js";
7
7
  import { Result as SafeParseResult } from "../../types/fp.js";
8
8
  import { SDKValidationError } from "../errors/sdkvalidationerror.js";
9
9
 
@@ -22,6 +22,11 @@ export type ListDocsRequest = {
22
22
  pageToken?: string | undefined;
23
23
  };
24
24
 
25
+ export type ListDocsDoc = {
26
+ collection: string;
27
+ doc: { [k: string]: any };
28
+ };
29
+
25
30
  /**
26
31
  * Documents list.
27
32
  */
@@ -30,8 +35,16 @@ export type ListDocsResponse = {
30
35
  /**
31
36
  * A list of documents.
32
37
  */
33
- docs: Array<{ [k: string]: any }>;
38
+ docs: Array<ListDocsDoc>;
34
39
  nextPageToken?: string | undefined;
40
+ /**
41
+ * Whether the list of documents is included.
42
+ */
43
+ isDocsInline: boolean;
44
+ /**
45
+ * Download URL for the list of documents.
46
+ */
47
+ docsUrl?: string | undefined;
35
48
  };
36
49
 
37
50
  /** @internal */
@@ -58,6 +71,16 @@ export function listDocsRequestToJSON(
58
71
  return JSON.stringify(ListDocsRequest$outboundSchema.parse(listDocsRequest));
59
72
  }
60
73
 
74
+ /** @internal */
75
+ export const ListDocsDoc$inboundSchema: z.ZodType<
76
+ ListDocsDoc,
77
+ z.ZodTypeDef,
78
+ unknown
79
+ > = z.object({
80
+ collection: z.string(),
81
+ doc: z.record(z.any()),
82
+ });
83
+
61
84
  /** @internal */
62
85
  export const ListDocsResponse$inboundSchema: z.ZodType<
63
86
  ListDocsResponse,
@@ -65,8 +88,10 @@ export const ListDocsResponse$inboundSchema: z.ZodType<
65
88
  unknown
66
89
  > = z.object({
67
90
  total: z.number().int(),
68
- docs: z.array(z.record(z.any())),
69
- nextPageToken: z.string().optional(),
91
+ docs: z.array(ListDocsDoc$inboundSchema),
92
+ nextPageToken: nullToUndefined(z.string().optional()),
93
+ isDocsInline: z.boolean(),
94
+ docsUrl: nullToUndefined(z.string().optional()),
70
95
  });
71
96
 
72
97
  export function listDocsResponseFromJSON(
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as z from "zod/v3";
6
6
  import { remap as remap$ } from "../../lib/primitives.js";
7
- import { safeParse } from "../../lib/schemas.js";
7
+ import { nullToUndefined, safeParse } from "../../lib/schemas.js";
8
8
  import { Result as SafeParseResult } from "../../types/fp.js";
9
9
  import { SDKValidationError } from "../errors/sdkvalidationerror.js";
10
10
  import * as models from "../index.js";
@@ -156,7 +156,7 @@ export const QueryCollectionDoc$inboundSchema: z.ZodType<
156
156
  unknown
157
157
  > = z.object({
158
158
  collection: z.string(),
159
- score: z.number().optional(),
159
+ score: nullToUndefined(z.number().optional()),
160
160
  doc: z.record(z.any()),
161
161
  });
162
162
 
@@ -177,11 +177,11 @@ export const QueryCollectionResponse$inboundSchema: z.ZodType<
177
177
  unknown
178
178
  > = z.object({
179
179
  took: z.number().int(),
180
- maxScore: z.number().optional(),
180
+ maxScore: nullToUndefined(z.number().optional()),
181
181
  total: z.number().int(),
182
182
  docs: z.array(z.lazy(() => QueryCollectionDoc$inboundSchema)),
183
183
  isDocsInline: z.boolean(),
184
- docsUrl: z.string().optional(),
184
+ docsUrl: nullToUndefined(z.string().optional()),
185
185
  });
186
186
 
187
187
  export function queryCollectionResponseFromJSON(
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v3";
6
- import { safeParse } from "../lib/schemas.js";
6
+ import { nullToUndefined, safeParse } from "../lib/schemas.js";
7
7
  import { ClosedEnum } from "../types/enums.js";
8
8
  import { Result as SafeParseResult } from "../types/fp.js";
9
9
  import { SDKValidationError } from "./errors/sdkvalidationerror.js";
@@ -47,9 +47,9 @@ export const PartitionConfig$inboundSchema: z.ZodType<
47
47
  z.ZodTypeDef,
48
48
  unknown
49
49
  > = z.object({
50
- fieldName: z.string().optional(),
51
- dataType: DataType$inboundSchema.optional(),
52
- numPartitions: z.number().int().optional(),
50
+ fieldName: nullToUndefined(z.string().optional()),
51
+ dataType: nullToUndefined(DataType$inboundSchema.optional()),
52
+ numPartitions: nullToUndefined(z.number().int().optional()),
53
53
  });
54
54
  /** @internal */
55
55
  export type PartitionConfig$Outbound = {
@@ -34,7 +34,10 @@ export type {
34
34
  QueryCollectionResponse,
35
35
  QueryCollectionDoc,
36
36
  } from "../models/operations/querycollection.js";
37
- export type { ListDocsResponse } from "../models/operations/listdocs.js";
37
+ export type {
38
+ ListDocsResponse,
39
+ ListDocsDoc,
40
+ } from "../models/operations/listdocs.js";
38
41
  export type { MessageResponse } from "../models/index.js";
39
42
  export type {
40
43
  FetchDocsResponse,
@@ -0,0 +1,73 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { LambdaDBClient } from "../dist/esm/index.js";
5
+ import { HTTPClient } from "../dist/esm/lib/http.js";
6
+ import { ResponseValidationError } from "../dist/esm/models/errors/responsevalidationerror.js";
7
+ import { QueryCollectionResponse$inboundSchema } from "../dist/esm/models/operations/querycollection.js";
8
+
9
+ function jsonResponse(body, init = {}) {
10
+ return new Response(JSON.stringify(body), {
11
+ status: 200,
12
+ headers: { "content-type": "application/json" },
13
+ ...init,
14
+ });
15
+ }
16
+
17
+ test("response schemas accept null for optional response fields", () => {
18
+ const parsed = QueryCollectionResponse$inboundSchema.parse({
19
+ took: 1,
20
+ maxScore: null,
21
+ total: 1,
22
+ docs: [{ collection: "items", score: null, doc: { id: "a" } }],
23
+ isDocsInline: false,
24
+ docsUrl: null,
25
+ });
26
+
27
+ assert.equal(parsed.maxScore, undefined);
28
+ assert.equal(parsed.docsUrl, undefined);
29
+ assert.equal(parsed.docs[0].score, undefined);
30
+ });
31
+
32
+ test("safe methods return ResponseValidationError for invalid JSON bodies", async () => {
33
+ const httpClient = new HTTPClient({
34
+ fetcher: async () =>
35
+ new Response("{", {
36
+ status: 200,
37
+ headers: { "content-type": "application/json" },
38
+ }),
39
+ });
40
+ const client = new LambdaDBClient({ httpClient, projectApiKey: "test-key" });
41
+
42
+ const result = await client.listCollectionsSafe();
43
+
44
+ assert.equal(result.ok, false);
45
+ assert.ok(result.error instanceof ResponseValidationError);
46
+ assert.equal(result.error.rawValue, "{");
47
+ });
48
+
49
+ test("docsUrl fetches treat null document payloads as an empty docs array", async () => {
50
+ const originalFetch = globalThis.fetch;
51
+ globalThis.fetch = async () => jsonResponse(null);
52
+
53
+ try {
54
+ const httpClient = new HTTPClient({
55
+ fetcher: async () =>
56
+ jsonResponse({
57
+ total: 1,
58
+ docs: [],
59
+ isDocsInline: false,
60
+ docsUrl: "https://example.test/docs.json",
61
+ }),
62
+ });
63
+ const client = new LambdaDBClient({ httpClient, projectApiKey: "test-key" });
64
+
65
+ const result = await client.collection("items").docs.listSafe();
66
+
67
+ assert.equal(result.ok, true);
68
+ assert.deepEqual(result.value.docs, []);
69
+ assert.equal(result.value.isDocsInline, true);
70
+ } finally {
71
+ globalThis.fetch = originalFetch;
72
+ }
73
+ });