@terrascale/sdk 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +66 -11
- package/package.json +1 -1
- package/sdk-v1-route-manifest.json +39 -36
- package/src/index.js +9 -0
- package/src/local/router.js +12 -3
- package/src/v1/changes.js +2 -2
- package/src/v1/decode.js +4 -3
- package/src/v1/export.js +3 -3
- package/src/v1/filter.js +103 -2
- package/src/v1/ids.js +7 -2
- package/src/v1/indexes.js +6 -4
- package/src/v1/shape-reader.js +19 -5
- package/src/v1/shape-replica.js +46 -0
- package/src/v1/shape-subscription.js +57 -5
- package/src/v1/shapes.js +3 -3
- package/src/v1/sql.js +2 -2
- package/src/v1/terrabase-v1.js +103 -9
- package/src/v1/transport.js +27 -5
- package/types/index.d.ts +9 -0
- package/types/v1/decode.d.ts +7 -2
- package/types/v1/filter.d.ts +50 -0
- package/types/v1/ids.d.ts +3 -1
- package/types/v1/indexes.d.ts +5 -0
- package/types/v1/shape-replica.d.ts +8 -0
- package/types/v1/shape-subscription.d.ts +15 -0
- package/types/v1/terrabase-v1.d.ts +69 -1
- package/types/v1/transport.d.ts +17 -0
package/src/v1/transport.js
CHANGED
|
@@ -44,6 +44,7 @@ const tokenPattern = /^(?!tbk1\.)(?:[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-
|
|
|
44
44
|
* @property {URLSearchParams | undefined} [query]
|
|
45
45
|
* @property {AbortSignal | undefined} [signal]
|
|
46
46
|
* @property {"no-store" | undefined} [cache] Authenticated shape epoch keys must bypass caches.
|
|
47
|
+
* @property {"follow" | undefined} [redirect] Only the shape bootstrap, after a browser hides its 307 behind an opaque redirect.
|
|
47
48
|
*/
|
|
48
49
|
|
|
49
50
|
/**
|
|
@@ -51,6 +52,7 @@ const tokenPattern = /^(?!tbk1\.)(?:[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-
|
|
|
51
52
|
* @property {number} status
|
|
52
53
|
* @property {Headers} headers
|
|
53
54
|
* @property {JsonValue | undefined} value
|
|
55
|
+
* @property {string | undefined} [redirectedTo] The final URL after a followed redirect.
|
|
54
56
|
*/
|
|
55
57
|
|
|
56
58
|
/**
|
|
@@ -134,6 +136,23 @@ export class BodyTransportError extends Error {
|
|
|
134
136
|
}
|
|
135
137
|
}
|
|
136
138
|
|
|
139
|
+
/** A request that failed in transit before any response; the native failure is the cause. */
|
|
140
|
+
export class RequestTransportError extends TypeError {
|
|
141
|
+
/** @param {unknown} cause */
|
|
142
|
+
constructor(cause) {
|
|
143
|
+
super(cause instanceof Error ? cause.message : "TerraBase request failed in transit.", { cause });
|
|
144
|
+
this.name = "RequestTransportError";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** A browser hid a 307 behind an opaque redirect; only the shape bootstrap may follow it. */
|
|
149
|
+
export class OpaqueRedirectError extends TypeError {
|
|
150
|
+
constructor() {
|
|
151
|
+
super("Fresh shape bootstrap requires server fetch; obtain a handle and snapshot offset with collection.shape() on your server.");
|
|
152
|
+
this.name = "OpaqueRedirectError";
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
137
156
|
/** Internal transport bound to one project credential. */
|
|
138
157
|
export class V1Transport {
|
|
139
158
|
/** @type {string | undefined} */
|
|
@@ -353,7 +372,8 @@ export class V1Transport {
|
|
|
353
372
|
await response.body?.cancel();
|
|
354
373
|
return { status: response.status, headers: response.headers, value: undefined };
|
|
355
374
|
}
|
|
356
|
-
return { status: response.status, headers: response.headers, value: await this.readJson(response, options.signal)
|
|
375
|
+
return { status: response.status, headers: response.headers, value: await this.readJson(response, options.signal),
|
|
376
|
+
...(response.redirected ? { redirectedTo: response.url } : {}) };
|
|
357
377
|
}
|
|
358
378
|
|
|
359
379
|
/**
|
|
@@ -387,7 +407,7 @@ export class V1Transport {
|
|
|
387
407
|
if (route.responseMediaType !== "") headers.set("accept", route.responseMediaType);
|
|
388
408
|
if (options.body !== undefined) headers.set("content-type", options.contentType ?? "application/json");
|
|
389
409
|
/** @type {RequestInit & { duplex?: "half" }} */
|
|
390
|
-
const init = { method: route.method, headers, redirect: "manual" };
|
|
410
|
+
const init = { method: route.method, headers, redirect: options.redirect ?? "manual" };
|
|
391
411
|
if (options.cache !== undefined) init.cache = options.cache;
|
|
392
412
|
if (route.permission.endsWith(":write") && typeof process !== "undefined" && process.release?.name === "node") {
|
|
393
413
|
// Node fetch replays buffered or absent bodies on 421; use a one-shot stream, including DELETE.
|
|
@@ -397,13 +417,15 @@ export class V1Transport {
|
|
|
397
417
|
} else if (options.body !== undefined) init.body = typeof options.body === "string" ? options.body : options.body.slice().buffer;
|
|
398
418
|
if (options.signal !== undefined) init.signal = options.signal;
|
|
399
419
|
options.signal?.throwIfAborted();
|
|
400
|
-
|
|
420
|
+
/** @type {Response} */
|
|
421
|
+
let response;
|
|
422
|
+
try { response = await this.#fetch(url, init); }
|
|
423
|
+
catch (error) { options.signal?.throwIfAborted(); throw new RequestTransportError(error); }
|
|
401
424
|
if (options.signal?.aborted) {
|
|
402
425
|
void response.body?.cancel().catch(() => undefined);
|
|
403
426
|
options.signal.throwIfAborted();
|
|
404
427
|
}
|
|
405
|
-
if (response.type === "opaqueredirect")
|
|
406
|
-
throw new TypeError("Fresh shape bootstrap requires server fetch; obtain a handle and snapshot offset with collection.shape() on your server.");
|
|
428
|
+
if (response.type === "opaqueredirect") throw new OpaqueRedirectError();
|
|
407
429
|
if (!route.successStatuses.includes(response.status)) throw await this.error(response, options.signal);
|
|
408
430
|
return response;
|
|
409
431
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { v1Filter } from "./v1/filter.js";
|
|
2
2
|
export { V1ShapeSubscription } from "./v1/shape-subscription.js";
|
|
3
|
+
export { indexedDbShapeReplica } from "./v1/shape-replica.js";
|
|
3
4
|
export { ExactDecimal } from "./v1/json.js";
|
|
4
5
|
export { staticBaseUrlResolver } from "./v1/transport.js";
|
|
5
6
|
export { V1Databases } from "./v1/catalog.js";
|
|
@@ -8,6 +9,7 @@ export { V1DatabaseSchemaClient } from "./v1/database-schema.js";
|
|
|
8
9
|
export { V1Indexes } from "./v1/indexes.js";
|
|
9
10
|
export { V1ChangeWebhooks } from "./v1/change-webhooks.js";
|
|
10
11
|
export { V1Imports } from "./v1/imports.js";
|
|
12
|
+
export type V1ShapeReplicaStore = import("./v1/shape-subscription.js").V1ShapeReplicaStore;
|
|
11
13
|
export type V1ShapeSubscribeOptions = import("./v1/shape-subscription.js").V1ShapeSubscribeOptions;
|
|
12
14
|
export type V1ShapeDocument = import("./v1/shape-subscription.js").V1ShapeDocument;
|
|
13
15
|
export type V1SealedShapePosition = import("./v1/shape-reader.js").V1SealedShapePosition;
|
|
@@ -23,6 +25,10 @@ export type V1PatchOp = import("./v1/terrabase-v1.js").V1PatchOp;
|
|
|
23
25
|
export type V1Patch = import("./v1/terrabase-v1.js").V1Patch;
|
|
24
26
|
export type V1SortKey = import("./v1/terrabase-v1.js").V1SortKey;
|
|
25
27
|
export type V1NearSortKey = import("./v1/terrabase-v1.js").V1NearSortKey;
|
|
28
|
+
export type V1GeoNearSortKey = import("./v1/terrabase-v1.js").V1GeoNearSortKey;
|
|
29
|
+
export type V1Aggregate = import("./v1/terrabase-v1.js").V1Aggregate;
|
|
30
|
+
export type V1Group = import("./v1/terrabase-v1.js").V1Group;
|
|
31
|
+
export type V1ScoreSortKey = import("./v1/terrabase-v1.js").V1ScoreSortKey;
|
|
26
32
|
export type V1Query = import("./v1/terrabase-v1.js").V1Query;
|
|
27
33
|
export type V1Count = import("./v1/terrabase-v1.js").V1Count;
|
|
28
34
|
export type V1QueryPage = import("./v1/terrabase-v1.js").V1QueryPage;
|
|
@@ -36,6 +42,8 @@ export type V1Durability = import("./v1/decode.js").V1Durability;
|
|
|
36
42
|
export type V1Filter = import("./v1/filter.js").V1Filter;
|
|
37
43
|
export type V1Path = import("./v1/filter.js").V1Path;
|
|
38
44
|
export type V1Scalar = import("./v1/filter.js").V1Scalar;
|
|
45
|
+
export type V1GeoCircle = import("./v1/filter.js").V1GeoCircle;
|
|
46
|
+
export type V1GeoBox = import("./v1/filter.js").V1GeoBox;
|
|
39
47
|
export type V1JsonValue = import("./v1/json.js").JsonValue;
|
|
40
48
|
export type V1JsonObject = import("./v1/json.js").JsonObject;
|
|
41
49
|
export type V1JsonInput = import("./v1/json.js").JsonInput;
|
|
@@ -82,6 +90,7 @@ export type V1UniqueSchema = import("./v1/database-schema.js").V1UniqueSchema;
|
|
|
82
90
|
export type V1UniqueSchemaRequest = import("./v1/database-schema.js").V1UniqueSchemaRequest;
|
|
83
91
|
export type V1QueryShapes = import("./v1/database-schema.js").V1QueryShapes;
|
|
84
92
|
export type V1Index = import("./v1/indexes.js").V1Index;
|
|
93
|
+
export type V1IndexKind = import("./v1/indexes.js").V1IndexKind;
|
|
85
94
|
export type V1IndexList = import("./v1/indexes.js").V1IndexList;
|
|
86
95
|
export type V1AutoIndexPolicy = import("./v1/indexes.js").V1AutoIndexPolicy;
|
|
87
96
|
export type V1IndexRecommendations = import("./v1/indexes.js").V1IndexRecommendations;
|
package/types/v1/decode.d.ts
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* @property {"value" | "conflict" | (string & {})} state
|
|
10
10
|
* @property {JsonObject} document
|
|
11
11
|
* @property {readonly JsonValue[]} [siblings] Live versions and tombstones on a causal conflict.
|
|
12
|
-
* @property {number} [distance] Distance to the query vector; present only on `near` query results.
|
|
12
|
+
* @property {number} [distance] Distance to the query vector, or meters to a geo `near` point; present only on `near` query results.
|
|
13
|
+
* @property {number} [score] Full-text relevance score on results sorted by `$score`.
|
|
13
14
|
*/
|
|
14
15
|
/**
|
|
15
16
|
* The result of a document write.
|
|
@@ -99,9 +100,13 @@ export type V1Document = {
|
|
|
99
100
|
*/
|
|
100
101
|
siblings?: readonly JsonValue[];
|
|
101
102
|
/**
|
|
102
|
-
* Distance to the query vector; present only on `near` query results.
|
|
103
|
+
* Distance to the query vector, or meters to a geo `near` point; present only on `near` query results.
|
|
103
104
|
*/
|
|
104
105
|
distance?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Full-text relevance score on results sorted by `$score`.
|
|
108
|
+
*/
|
|
109
|
+
score?: number;
|
|
105
110
|
};
|
|
106
111
|
/**
|
|
107
112
|
* The result of a document write.
|
package/types/v1/filter.d.ts
CHANGED
|
@@ -10,6 +10,14 @@ export function isJsonPointer(pointer: unknown): pointer is string;
|
|
|
10
10
|
* @returns {V1Path}
|
|
11
11
|
*/
|
|
12
12
|
export function requirePath(path: V1Path): V1Path;
|
|
13
|
+
/** @param {V1Filter | null | undefined} filter @returns {number} */
|
|
14
|
+
export function searchCount(filter: V1Filter | null | undefined): number;
|
|
15
|
+
/**
|
|
16
|
+
* @param {unknown} lat
|
|
17
|
+
* @param {unknown} lon
|
|
18
|
+
* @returns {void}
|
|
19
|
+
*/
|
|
20
|
+
export function requireGeoPoint(lat: unknown, lon: unknown): void;
|
|
13
21
|
/**
|
|
14
22
|
* Validates a filter against the query-v1 grammar (operators, arity, paths,
|
|
15
23
|
* scalar operands, depth 8 and 256 nodes), so a malformed filter fails locally
|
|
@@ -100,6 +108,13 @@ export const v1Filter: Readonly<{
|
|
|
100
108
|
* @returns {V1Filter}
|
|
101
109
|
*/
|
|
102
110
|
prefix: (path: V1Path, prefix: string) => V1Filter;
|
|
111
|
+
/**
|
|
112
|
+
* Full-text search on a document member.
|
|
113
|
+
* @param {V1Path} path
|
|
114
|
+
* @param {string} terms
|
|
115
|
+
* @returns {V1Filter}
|
|
116
|
+
*/
|
|
117
|
+
search: (path: V1Path, terms: string) => V1Filter;
|
|
103
118
|
/**
|
|
104
119
|
* The value is an array containing the scalar.
|
|
105
120
|
* @param {V1Path} path
|
|
@@ -107,6 +122,20 @@ export const v1Filter: Readonly<{
|
|
|
107
122
|
* @returns {V1Filter}
|
|
108
123
|
*/
|
|
109
124
|
contains: (path: V1Path, value: V1Scalar) => V1Filter;
|
|
125
|
+
/**
|
|
126
|
+
* The `{lat, lon}` object at `path` lies within `meters` of the center (haversine, WGS 84 mean radius).
|
|
127
|
+
* @param {string} path JSON Pointer of a `{lat, lon}` point.
|
|
128
|
+
* @param {V1GeoCircle} circle `meters` is more than 0, at most 20000000.
|
|
129
|
+
* @returns {V1Filter}
|
|
130
|
+
*/
|
|
131
|
+
withinRadius: (path: string, circle: V1GeoCircle) => V1Filter;
|
|
132
|
+
/**
|
|
133
|
+
* The `{lat, lon}` object at `path` lies in the box; `west > east` crosses the antimeridian.
|
|
134
|
+
* @param {string} path JSON Pointer of a `{lat, lon}` point.
|
|
135
|
+
* @param {V1GeoBox} box
|
|
136
|
+
* @returns {V1Filter}
|
|
137
|
+
*/
|
|
138
|
+
withinBox: (path: string, box: V1GeoBox) => V1Filter;
|
|
110
139
|
}>;
|
|
111
140
|
/**
|
|
112
141
|
* A filter or sort path: an RFC 6901 JSON Pointer or "$id".
|
|
@@ -144,5 +173,26 @@ export type V1Filter = {
|
|
|
144
173
|
readonly prefix: readonly [V1Path, string];
|
|
145
174
|
} | {
|
|
146
175
|
readonly contains: readonly [V1Path, V1Scalar];
|
|
176
|
+
} | {
|
|
177
|
+
readonly within: readonly [string, V1GeoCircle | V1GeoBox];
|
|
178
|
+
} | {
|
|
179
|
+
readonly search: readonly [V1Path, string];
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Points within `meters` (more than 0, at most 20000000) of a WGS 84 point, by haversine distance.
|
|
183
|
+
*/
|
|
184
|
+
export type V1GeoCircle = {
|
|
185
|
+
readonly lat: number;
|
|
186
|
+
readonly lon: number;
|
|
187
|
+
readonly meters: number;
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Points in a latitude/longitude box; `west > east` crosses the antimeridian.
|
|
191
|
+
*/
|
|
192
|
+
export type V1GeoBox = {
|
|
193
|
+
readonly south: number;
|
|
194
|
+
readonly west: number;
|
|
195
|
+
readonly north: number;
|
|
196
|
+
readonly east: number;
|
|
147
197
|
};
|
|
148
198
|
import { ExactDecimal } from "./json.js";
|
package/types/v1/ids.d.ts
CHANGED
|
@@ -10,8 +10,10 @@ export function requireName(kind: "database" | "collection", name: unknown): str
|
|
|
10
10
|
* @returns {import("../ids.js").EntityId}
|
|
11
11
|
*/
|
|
12
12
|
export function requireProject(project: unknown): import("../ids.js").EntityId;
|
|
13
|
-
/**
|
|
13
|
+
/** Every document id is a canonical ULID. @param {unknown} id @returns {string} */
|
|
14
14
|
export function requireDocumentId(id: unknown): string;
|
|
15
|
+
/** SQL-backed collections can return non-ULID primary keys. @param {unknown} id @returns {string} */
|
|
16
|
+
export function requireStoredId(id: unknown): string;
|
|
15
17
|
/**
|
|
16
18
|
* @param {unknown} version
|
|
17
19
|
* @returns {string}
|
package/types/v1/indexes.d.ts
CHANGED
|
@@ -27,10 +27,12 @@ export type V1IndexList = ReturnType<typeof indexes>;
|
|
|
27
27
|
export type V1AutoIndexPolicy = ReturnType<typeof policy>;
|
|
28
28
|
export type V1IndexRecommendations = ReturnType<typeof recommendations>;
|
|
29
29
|
export type V1AppliedIndexRecommendation = ReturnType<typeof applied>;
|
|
30
|
+
export type V1IndexKind = "btree" | "text";
|
|
30
31
|
export type V1CreateIndexRequest = {
|
|
31
32
|
readonly collection: string;
|
|
32
33
|
readonly fields: readonly string[];
|
|
33
34
|
readonly name?: string | null;
|
|
35
|
+
readonly kind?: V1IndexKind;
|
|
34
36
|
};
|
|
35
37
|
import type { V1RequestOptions } from "./terrabase-v1.js";
|
|
36
38
|
import type { V1Transport } from "./transport.js";
|
|
@@ -41,6 +43,7 @@ declare const index: import("./management-decode.js").Decoder<Readonly<{
|
|
|
41
43
|
collection: string;
|
|
42
44
|
fields: readonly string[];
|
|
43
45
|
state: string;
|
|
46
|
+
kind: string | undefined;
|
|
44
47
|
}>>;
|
|
45
48
|
declare const indexes: import("./management-decode.js").Decoder<Readonly<{
|
|
46
49
|
items: readonly Readonly<{
|
|
@@ -48,6 +51,7 @@ declare const indexes: import("./management-decode.js").Decoder<Readonly<{
|
|
|
48
51
|
collection: string;
|
|
49
52
|
fields: readonly string[];
|
|
50
53
|
state: string;
|
|
54
|
+
kind: string | undefined;
|
|
51
55
|
}>[];
|
|
52
56
|
}>>;
|
|
53
57
|
declare const policy: import("./management-decode.js").Decoder<Readonly<{
|
|
@@ -70,6 +74,7 @@ declare const applied: import("./management-decode.js").Decoder<Readonly<{
|
|
|
70
74
|
collection: string;
|
|
71
75
|
fields: readonly string[];
|
|
72
76
|
state: string;
|
|
77
|
+
kind: string | undefined;
|
|
73
78
|
}>;
|
|
74
79
|
}>>;
|
|
75
80
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** @import { V1ShapeReplicaStore } from "./shape-subscription.js" */
|
|
2
|
+
/**
|
|
3
|
+
* A V1ShapeReplicaStore kept in browser IndexedDB, one record per key.
|
|
4
|
+
* @param {string} key Names one subject's shape, e.g. `${userId}/notes/open`; clear it on sign-out.
|
|
5
|
+
* @returns {V1ShapeReplicaStore}
|
|
6
|
+
*/
|
|
7
|
+
export function indexedDbShapeReplica(key: string): V1ShapeReplicaStore;
|
|
8
|
+
import type { V1ShapeReplicaStore } from "./shape-subscription.js";
|
|
@@ -25,6 +25,21 @@ export type V1ShapeSubscribeOptions = {
|
|
|
25
25
|
* Runs after validated responses and freshness changes; throwing rejects `done` unless already closed or aborted.
|
|
26
26
|
*/
|
|
27
27
|
onUpdate?: ((subscription: V1ShapeSubscription) => void) | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Keeps the last resumable state for reads across restarts and while offline; writes still go to the server.
|
|
30
|
+
*/
|
|
31
|
+
replica?: V1ShapeReplicaStore | undefined;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Holds one subscription's state as exact JSON text, e.g. in IndexedDB or React Native storage. Scope one store
|
|
35
|
+
* to one signed-in subject: the replica holds that subject's authorized documents. A failing store rejects `done`.
|
|
36
|
+
*/
|
|
37
|
+
export type V1ShapeReplicaStore = {
|
|
38
|
+
load: () => string | undefined | Promise<string | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Receives undefined after must_refetch discards state.
|
|
41
|
+
*/
|
|
42
|
+
save: (text: string | undefined) => void | Promise<void>;
|
|
28
43
|
};
|
|
29
44
|
export type V1ShapeDocument = {
|
|
30
45
|
readonly version: string;
|
|
@@ -438,7 +438,67 @@ export type V1NearSortKey = {
|
|
|
438
438
|
readonly metric?: "cosine" | "l2" | undefined;
|
|
439
439
|
};
|
|
440
440
|
};
|
|
441
|
-
|
|
441
|
+
/**
|
|
442
|
+
* Geo distance sort: meters from a WGS 84 point to each document's `{lat, lon}` object at `path`, nearest first,
|
|
443
|
+
* returned as `distance`. Like the vector `near`, it is the only sort key, limit is at most 100 and there is no cursor.
|
|
444
|
+
*/
|
|
445
|
+
export type V1GeoNearSortKey = {
|
|
446
|
+
readonly near: {
|
|
447
|
+
readonly path: string;
|
|
448
|
+
readonly lat: number;
|
|
449
|
+
readonly lon: number;
|
|
450
|
+
};
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* Relevance order, only sort key with exactly one search predicate.
|
|
454
|
+
*/
|
|
455
|
+
export type V1ScoreSortKey = {
|
|
456
|
+
readonly path: "$score";
|
|
457
|
+
readonly order: "desc";
|
|
458
|
+
};
|
|
459
|
+
export type V1SortKey = V1FieldSortKey | V1NearSortKey | V1GeoNearSortKey | V1ScoreSortKey;
|
|
460
|
+
/**
|
|
461
|
+
* Groups matches instead of returning documents. Summaries consider numbers only; at most 16 summary paths in total.
|
|
462
|
+
*/
|
|
463
|
+
export type V1Aggregate = {
|
|
464
|
+
/**
|
|
465
|
+
* 0-4 paths; without it every match is one group.
|
|
466
|
+
*/
|
|
467
|
+
groupBy?: readonly V1Path[] | undefined;
|
|
468
|
+
/**
|
|
469
|
+
* Distinct JSON Pointers.
|
|
470
|
+
*/
|
|
471
|
+
sum?: readonly string[] | undefined;
|
|
472
|
+
/**
|
|
473
|
+
* Distinct JSON Pointers.
|
|
474
|
+
*/
|
|
475
|
+
avg?: readonly string[] | undefined;
|
|
476
|
+
/**
|
|
477
|
+
* Distinct JSON Pointers.
|
|
478
|
+
*/
|
|
479
|
+
min?: readonly string[] | undefined;
|
|
480
|
+
/**
|
|
481
|
+
* Distinct JSON Pointers.
|
|
482
|
+
*/
|
|
483
|
+
max?: readonly string[] | undefined;
|
|
484
|
+
};
|
|
485
|
+
/**
|
|
486
|
+
* One aggregate group. Summaries are keyed by the requested JSON Pointer; `sum` is 0 and the others null without numbers.
|
|
487
|
+
*/
|
|
488
|
+
export type V1Group = {
|
|
489
|
+
/**
|
|
490
|
+
* One value per `groupBy` path (missing members group as null).
|
|
491
|
+
*/
|
|
492
|
+
key: readonly JsonValue[];
|
|
493
|
+
/**
|
|
494
|
+
* Matching documents in the group (decimal u64).
|
|
495
|
+
*/
|
|
496
|
+
count: string;
|
|
497
|
+
sum?: Readonly<Record<string, number | null>> | undefined;
|
|
498
|
+
avg?: Readonly<Record<string, number | null>> | undefined;
|
|
499
|
+
min?: Readonly<Record<string, number | null>> | undefined;
|
|
500
|
+
max?: Readonly<Record<string, number | null>> | undefined;
|
|
501
|
+
};
|
|
442
502
|
/**
|
|
443
503
|
* A query-v1 request. Every member is optional.
|
|
444
504
|
*/
|
|
@@ -464,6 +524,10 @@ export type V1Query = {
|
|
|
464
524
|
* Count every match (first page only).
|
|
465
525
|
*/
|
|
466
526
|
count?: boolean | undefined;
|
|
527
|
+
/**
|
|
528
|
+
* Answer `groups` instead of items; `limit` bounds the groups. No sort, project, cursor or count.
|
|
529
|
+
*/
|
|
530
|
+
aggregate?: V1Aggregate | undefined;
|
|
467
531
|
};
|
|
468
532
|
export type V1Count = {
|
|
469
533
|
readonly value: string;
|
|
@@ -476,6 +540,10 @@ export type V1QueryPage = {
|
|
|
476
540
|
items: readonly V1Document[];
|
|
477
541
|
nextCursor: string | null;
|
|
478
542
|
count: V1Count | undefined;
|
|
543
|
+
/**
|
|
544
|
+
* An aggregate query's groups in key order (`items` is then empty).
|
|
545
|
+
*/
|
|
546
|
+
groups: readonly V1Group[] | undefined;
|
|
479
547
|
};
|
|
480
548
|
export type V1Precondition = {
|
|
481
549
|
readonly ifMatch: string;
|
package/types/v1/transport.d.ts
CHANGED
|
@@ -23,6 +23,15 @@ export class BodyTransportError extends Error {
|
|
|
23
23
|
/** @param {unknown} cause */
|
|
24
24
|
constructor(cause: unknown);
|
|
25
25
|
}
|
|
26
|
+
/** A request that failed in transit before any response; the native failure is the cause. */
|
|
27
|
+
export class RequestTransportError extends TypeError {
|
|
28
|
+
/** @param {unknown} cause */
|
|
29
|
+
constructor(cause: unknown);
|
|
30
|
+
}
|
|
31
|
+
/** A browser hid a 307 behind an opaque redirect; only the shape bootstrap may follow it. */
|
|
32
|
+
export class OpaqueRedirectError extends TypeError {
|
|
33
|
+
constructor();
|
|
34
|
+
}
|
|
26
35
|
/** Internal transport bound to one project credential. */
|
|
27
36
|
export class V1Transport {
|
|
28
37
|
/**
|
|
@@ -128,11 +137,19 @@ export type V1CallOptions = {
|
|
|
128
137
|
* Authenticated shape epoch keys must bypass caches.
|
|
129
138
|
*/
|
|
130
139
|
cache?: "no-store" | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* Only the shape bootstrap, after a browser hides its 307 behind an opaque redirect.
|
|
142
|
+
*/
|
|
143
|
+
redirect?: "follow" | undefined;
|
|
131
144
|
};
|
|
132
145
|
export type V1CallResult = {
|
|
133
146
|
status: number;
|
|
134
147
|
headers: Headers;
|
|
135
148
|
value: JsonValue | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* The final URL after a followed redirect.
|
|
151
|
+
*/
|
|
152
|
+
redirectedTo?: string | undefined;
|
|
136
153
|
};
|
|
137
154
|
import type { V1Operation } from "./routes.js";
|
|
138
155
|
import type { JsonValue } from "./json.js";
|