@terrascale/sdk 0.0.2 → 0.0.4
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 +43 -0
- package/README.md +193 -56
- package/package.json +14 -5
- package/sdk-public-v1-route-manifest.json +81 -0
- package/sdk-v1-route-manifest.json +8996 -1697
- package/src/database-codec.js +21 -26
- package/src/database-types.js +11 -11
- package/src/database-view.js +6 -6
- package/src/http.js +13 -48
- package/src/ids.js +22 -0
- package/src/index.js +77 -2
- package/src/local/better-auth.js +17 -6
- package/src/local/environment.js +0 -1
- package/src/local/index.js +2 -2
- package/src/local/legacy-client.js +5 -5
- package/src/local/router.js +12 -12
- package/src/local/store.js +29 -28
- package/src/local/test-environment.js +3 -2
- package/src/postgres.js +5 -4
- package/src/react/core.js +2 -2
- package/src/ts-auth-ids.js +122 -0
- package/src/ts-auth.js +75 -77
- package/src/v1/backups.js +111 -0
- package/src/v1/catalog.js +210 -0
- package/src/v1/changes.js +225 -0
- package/src/v1/database-schema.js +45 -0
- package/src/v1/decode.js +20 -8
- package/src/v1/errors.js +23 -3
- package/src/v1/ids.js +9 -59
- package/src/v1/imports.js +72 -0
- package/src/v1/indexes.js +76 -0
- package/src/v1/json.js +4 -3
- package/src/v1/management-decode.js +24 -0
- package/src/v1/management-routes.js +67 -0
- package/src/v1/management-validation.js +25 -0
- package/src/v1/routes.js +36 -11
- package/src/v1/saved-queries.js +58 -0
- package/src/v1/shape-crypto.js +125 -0
- package/src/v1/shape-manifest.js +31 -0
- package/src/v1/shape-reader.js +212 -0
- package/src/v1/shape-subscription.js +208 -0
- package/src/v1/shapes.js +15 -10
- package/src/v1/sql.js +98 -0
- package/src/v1/system.js +80 -0
- package/src/v1/terrabase-v1.js +192 -33
- package/src/v1/transport.js +80 -34
- package/src/v1/usage.js +101 -0
- package/types/database-codec.d.ts +1 -6
- package/types/database-types.d.ts +11 -11
- package/types/http.d.ts +2 -8
- package/types/ids.d.ts +10 -0
- package/types/index.d.ts +70 -1
- package/types/local/environment.d.ts +1 -1
- package/types/local/store.d.ts +10 -0
- package/types/local/test-environment.d.ts +2 -2
- package/types/postgres.d.ts +4 -4
- package/types/ts-auth-ids.d.ts +14 -0
- package/types/ts-auth.d.ts +99 -101
- package/types/v1/backups.d.ts +128 -0
- package/types/v1/catalog.d.ts +92 -0
- package/types/v1/changes.d.ts +53 -0
- package/types/v1/database-schema.d.ts +82 -0
- package/types/v1/decode.d.ts +17 -4
- package/types/v1/errors.d.ts +16 -1
- package/types/v1/ids.d.ts +4 -16
- package/types/v1/imports.d.ts +132 -0
- package/types/v1/indexes.d.ts +75 -0
- package/types/v1/management-decode.d.ts +15 -0
- package/types/v1/management-routes.d.ts +3 -0
- package/types/v1/management-validation.d.ts +8 -0
- package/types/v1/routes.d.ts +5 -2
- package/types/v1/saved-queries.d.ts +33 -0
- package/types/v1/shape-crypto.d.ts +39 -0
- package/types/v1/shape-manifest.d.ts +28 -0
- package/types/v1/shape-reader.d.ts +45 -0
- package/types/v1/shape-subscription.d.ts +35 -0
- package/types/v1/shapes.d.ts +14 -0
- package/types/v1/sql.d.ts +47 -0
- package/types/v1/system.d.ts +85 -0
- package/types/v1/terrabase-v1.d.ts +116 -7
- package/types/v1/transport.d.ts +27 -10
- package/types/v1/usage.d.ts +171 -0
- package/src/ts-auth-discovery.js +0 -207
- package/types/ts-auth-discovery.d.ts +0 -19
package/src/v1/transport.js
CHANGED
|
@@ -15,10 +15,12 @@ import { v1Route, v1RoutePath } from "./routes.js";
|
|
|
15
15
|
export const maximumRequestBytes = 4 * 1024 * 1024;
|
|
16
16
|
// Query budgets count stored JSON before wrappers and serializer escaping.
|
|
17
17
|
const defaultMaximumResponseBytes = 64 * 1024 * 1024;
|
|
18
|
-
|
|
18
|
+
// Validate header-safe credential syntax only; the producer validates JWT claims/signatures.
|
|
19
|
+
// Retain C# keys; current project routes also authenticate project access JWTs.
|
|
20
|
+
const tokenPattern = /^(?!tbk1\.)(?:[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|tb_[A-Za-z0-9_-]{43})$/u;
|
|
19
21
|
/**
|
|
20
22
|
* Resolver input contains no credential. A successful URL is cached for this client/database.
|
|
21
|
-
* @typedef {{ readonly project: string; readonly database
|
|
23
|
+
* @typedef {{ readonly project: string | undefined; readonly database?: string | undefined; readonly signal?: AbortSignal | undefined }} V1EndpointContext
|
|
22
24
|
*/
|
|
23
25
|
/** @typedef {(context: V1EndpointContext) => string | Promise<string>} V1EndpointResolver */
|
|
24
26
|
/**
|
|
@@ -26,7 +28,7 @@ const tokenPattern = /^tb_[A-Za-z0-9_-]{43}$/u;
|
|
|
26
28
|
* URLs must use HTTPS or loopback HTTP. Mutations are never automatically replayed.
|
|
27
29
|
* @typedef {object} TerraBaseV1ClientConfig
|
|
28
30
|
* @property {string} project
|
|
29
|
-
* @property {string} token A tb_
|
|
31
|
+
* @property {string} token A ts-auth project access JWT (or a legacy C# tb_ key); held privately.
|
|
30
32
|
* @property {string | undefined} [baseUrl]
|
|
31
33
|
* @property {V1EndpointResolver | undefined} [endpointResolver]
|
|
32
34
|
* @property {FetchLike | undefined} [fetch]
|
|
@@ -35,11 +37,12 @@ const tokenPattern = /^tb_[A-Za-z0-9_-]{43}$/u;
|
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
39
|
* @typedef {object} V1CallOptions
|
|
38
|
-
* @property {string} [body]
|
|
40
|
+
* @property {string | Uint8Array} [body]
|
|
39
41
|
* @property {string} [contentType]
|
|
40
42
|
* @property {Readonly<Record<string, string>>} [headers] Contract headers only (If-Match, If-None-Match).
|
|
41
43
|
* @property {URLSearchParams | undefined} [query]
|
|
42
44
|
* @property {AbortSignal | undefined} [signal]
|
|
45
|
+
* @property {"no-store" | undefined} [cache] Authenticated shape epoch keys must bypass caches.
|
|
43
46
|
*/
|
|
44
47
|
|
|
45
48
|
/**
|
|
@@ -123,32 +126,32 @@ export class BodyTransportError extends Error {
|
|
|
123
126
|
}
|
|
124
127
|
}
|
|
125
128
|
|
|
126
|
-
/** Internal transport bound to one
|
|
129
|
+
/** Internal transport bound to one project credential. */
|
|
127
130
|
export class V1Transport {
|
|
128
|
-
/** @type {string} */
|
|
131
|
+
/** @type {string | undefined} */
|
|
129
132
|
#project;
|
|
130
133
|
/** @type {V1EndpointResolver} */
|
|
131
134
|
#resolver;
|
|
132
135
|
/** @type {Map<string, { promise: Promise<string>; timer: ReturnType<typeof setTimeout>; waiters: number }>} */
|
|
133
136
|
#bases = new Map();
|
|
134
|
-
/** @type {string} */
|
|
137
|
+
/** @type {string | undefined} */
|
|
135
138
|
#token;
|
|
136
139
|
/** @type {FetchLike} */
|
|
137
140
|
#fetch;
|
|
138
141
|
/** @type {number} */
|
|
139
142
|
#maxResponseBytes;
|
|
140
143
|
|
|
141
|
-
/** @param {TerraBaseV1ClientConfig} config */
|
|
144
|
+
/** @param {TerraBaseV1ClientConfig | (import("./system.js").TerraBaseSystemClientConfig & { project?: undefined; endpointResolver?: undefined })} config */
|
|
142
145
|
constructor(config) {
|
|
143
146
|
if (typeof config !== "object" || config === null) throw new TypeError("TerraBase v1 client config is required.");
|
|
144
|
-
this.#project = requireProject(config.project);
|
|
147
|
+
this.#project = config.project === undefined ? undefined : requireProject(config.project);
|
|
145
148
|
if ((config.baseUrl === undefined) === (config.endpointResolver === undefined))
|
|
146
149
|
throw new TypeError("Supply exactly one of baseUrl or endpointResolver.");
|
|
147
150
|
if (config.endpointResolver !== undefined && typeof config.endpointResolver !== "function")
|
|
148
151
|
throw new TypeError("endpointResolver must be a function.");
|
|
149
152
|
this.#resolver = config.endpointResolver ?? staticBaseUrlResolver(/** @type {string} */ (config.baseUrl));
|
|
150
|
-
if (typeof config.token !== "string" || !tokenPattern.test(config.token))
|
|
151
|
-
throw new TypeError("token must be a
|
|
153
|
+
if ((config.project !== undefined || config.token !== undefined) && (typeof config.token !== "string" || !tokenPattern.test(config.token)))
|
|
154
|
+
throw new TypeError("token must be a compact access JWT or a legacy C# tb_ API key.");
|
|
152
155
|
if ("autoIdempotencyKey" in config || "maxRetries" in config || "resolver" in config)
|
|
153
156
|
throw new TypeError("Unsupported client configuration member.");
|
|
154
157
|
const fetchHandler = config.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
@@ -169,8 +172,9 @@ export class V1Transport {
|
|
|
169
172
|
*/
|
|
170
173
|
async url(operation, params, signal) {
|
|
171
174
|
signal?.throwIfAborted();
|
|
172
|
-
const database = requireName("database", params.database);
|
|
173
|
-
|
|
175
|
+
const database = v1Route(operation).pathTemplate.includes("{database}") ? requireName("database", params.database) : undefined;
|
|
176
|
+
const session = database ?? "";
|
|
177
|
+
let base = this.#bases.get(session);
|
|
174
178
|
if (base === undefined) {
|
|
175
179
|
const controller = new AbortController();
|
|
176
180
|
const timer = setTimeout(() => controller.abort(new DOMException(
|
|
@@ -180,13 +184,13 @@ export class V1Transport {
|
|
|
180
184
|
const promise = new Promise((resolve, reject) => {
|
|
181
185
|
controller.signal.addEventListener("abort", () => reject(controller.signal.reason), { once: true });
|
|
182
186
|
void Promise.resolve().then(() => this.#resolver(Object.freeze({
|
|
183
|
-
project: this.#project, database, signal: controller.signal,
|
|
187
|
+
project: this.#project, ...(database === undefined ? {} : { database }), signal: controller.signal,
|
|
184
188
|
}))).then(canonicalBaseUrl).then(resolve, reject).finally(() => clearTimeout(timer));
|
|
185
189
|
});
|
|
186
190
|
base = { promise, timer, waiters: 0 };
|
|
187
|
-
this.#bases.set(
|
|
191
|
+
this.#bases.set(session, base);
|
|
188
192
|
// A failed resolution is not a session; a later operation may resolve again.
|
|
189
|
-
void promise.catch(() => { if (this.#bases.get(
|
|
193
|
+
void promise.catch(() => { if (this.#bases.get(session) === base) this.#bases.delete(session); });
|
|
190
194
|
}
|
|
191
195
|
base.waiters++;
|
|
192
196
|
if (typeof base.timer === "object") base.timer.ref();
|
|
@@ -204,7 +208,8 @@ export class V1Transport {
|
|
|
204
208
|
});
|
|
205
209
|
});
|
|
206
210
|
signal?.throwIfAborted();
|
|
207
|
-
|
|
211
|
+
if (v1Route(operation).pathTemplate.includes("{project}") && this.#project === undefined) throw new TypeError("This operation requires a project client.");
|
|
212
|
+
return `${resolved}${v1RoutePath(v1Route(operation), { ...params, ...(this.#project === undefined ? {} : { project: this.#project }) })}`;
|
|
208
213
|
} finally {
|
|
209
214
|
// Keep Node alive only while callers are waiting for this resolution.
|
|
210
215
|
if (--base.waiters === 0 && typeof base.timer === "object") base.timer.unref();
|
|
@@ -215,9 +220,11 @@ export class V1Transport {
|
|
|
215
220
|
* Reads a response body as UTF-8 text within the response byte bound. A
|
|
216
221
|
* connection failure while reading is a BodyTransportError.
|
|
217
222
|
* @param {Response} response
|
|
223
|
+
* @param {AbortSignal | undefined} [signal]
|
|
218
224
|
* @returns {Promise<string>}
|
|
219
225
|
*/
|
|
220
|
-
async readText(response) {
|
|
226
|
+
async readText(response, signal) {
|
|
227
|
+
signal?.throwIfAborted();
|
|
221
228
|
const reader = response.body?.getReader();
|
|
222
229
|
if (reader === undefined) return "";
|
|
223
230
|
/** @type {Uint8Array[]} */
|
|
@@ -225,13 +232,16 @@ export class V1Transport {
|
|
|
225
232
|
let size = 0;
|
|
226
233
|
try {
|
|
227
234
|
while (true) {
|
|
235
|
+
signal?.throwIfAborted();
|
|
228
236
|
/** @type {ReadableStreamReadResult<Uint8Array>} */
|
|
229
237
|
let part;
|
|
230
238
|
try {
|
|
231
239
|
part = await reader.read();
|
|
232
240
|
} catch (error) {
|
|
241
|
+
signal?.throwIfAborted();
|
|
233
242
|
throw new BodyTransportError(error);
|
|
234
243
|
}
|
|
244
|
+
signal?.throwIfAborted();
|
|
235
245
|
if (part.done) break;
|
|
236
246
|
size += part.value.byteLength;
|
|
237
247
|
if (size > this.#maxResponseBytes)
|
|
@@ -250,16 +260,17 @@ export class V1Transport {
|
|
|
250
260
|
bytes.set(part, offset);
|
|
251
261
|
offset += part.byteLength;
|
|
252
262
|
}
|
|
253
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
263
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
254
264
|
}
|
|
255
265
|
|
|
256
266
|
/**
|
|
257
267
|
* Parses a JSON response body exactly.
|
|
258
268
|
* @param {Response} response
|
|
269
|
+
* @param {AbortSignal | undefined} [signal]
|
|
259
270
|
* @returns {Promise<JsonValue | undefined>}
|
|
260
271
|
*/
|
|
261
|
-
async readJson(response) {
|
|
262
|
-
return V1Transport.#decodeJson(response, await this.readText(response));
|
|
272
|
+
async readJson(response, signal) {
|
|
273
|
+
return V1Transport.#decodeJson(response, await this.readText(response, signal));
|
|
263
274
|
}
|
|
264
275
|
|
|
265
276
|
/**
|
|
@@ -278,13 +289,15 @@ export class V1Transport {
|
|
|
278
289
|
/**
|
|
279
290
|
* Converts a non-success response to a TerraBaseV1Error.
|
|
280
291
|
* @param {Response} response
|
|
292
|
+
* @param {AbortSignal | undefined} [signal]
|
|
281
293
|
* @returns {Promise<TerraBaseV1Error>}
|
|
282
294
|
*/
|
|
283
|
-
async error(response) {
|
|
295
|
+
async error(response, signal) {
|
|
284
296
|
let text = "";
|
|
285
297
|
try {
|
|
286
|
-
text = await this.readText(response);
|
|
298
|
+
text = await this.readText(response, signal);
|
|
287
299
|
} catch {
|
|
300
|
+
signal?.throwIfAborted();
|
|
288
301
|
text = "";
|
|
289
302
|
}
|
|
290
303
|
return parseV1Error(response.status, response.headers, text);
|
|
@@ -298,27 +311,60 @@ export class V1Transport {
|
|
|
298
311
|
* @returns {Promise<V1CallResult>}
|
|
299
312
|
*/
|
|
300
313
|
async call(operation, params, options = {}) {
|
|
314
|
+
const response = await this.#send(operation, params, options);
|
|
315
|
+
if (response.status === 307) {
|
|
316
|
+
await response.body?.cancel();
|
|
317
|
+
return { status: response.status, headers: response.headers, value: undefined };
|
|
318
|
+
}
|
|
319
|
+
return { status: response.status, headers: response.headers, value: await this.readJson(response, options.signal) };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @param {"streamDatabaseChanges"} operation
|
|
324
|
+
* @param {Readonly<Record<string, string>>} params
|
|
325
|
+
* @param {V1CallOptions} [options]
|
|
326
|
+
* @returns {Promise<Response>}
|
|
327
|
+
*/
|
|
328
|
+
async openStream(operation, params, options = {}) {
|
|
329
|
+
const response = await this.#send(operation, params, options);
|
|
330
|
+
const mediaType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
331
|
+
if (mediaType !== "text/event-stream" || response.body === null) {
|
|
332
|
+
void response.body?.cancel().catch(() => undefined);
|
|
333
|
+
throw new TypeError("TerraBase changes require a text/event-stream response body.");
|
|
334
|
+
}
|
|
335
|
+
return response;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** @param {V1Operation} operation @param {Readonly<Record<string, string>>} params @param {V1CallOptions} options @returns {Promise<Response>} */
|
|
339
|
+
async #send(operation, params, options) {
|
|
301
340
|
const route = v1Route(operation);
|
|
302
|
-
|
|
341
|
+
const bytes = typeof options.body === "string" ? new TextEncoder().encode(options.body) : options.body;
|
|
342
|
+
if (bytes !== undefined && bytes.byteLength > maximumRequestBytes)
|
|
303
343
|
throw new TypeError(`TerraBase request bodies are limited to ${maximumRequestBytes} bytes.`);
|
|
304
344
|
let url = await this.url(operation, params, options.signal);
|
|
305
345
|
if (options.query !== undefined && options.query.size > 0) url += `?${options.query}`;
|
|
306
346
|
const headers = new Headers(options.headers);
|
|
307
|
-
headers.set("authorization", `Bearer ${this.#token}`);
|
|
308
|
-
headers.set("accept", route.responseMediaType);
|
|
347
|
+
if (route.permission !== "anonymous" && this.#token !== undefined) headers.set("authorization", `Bearer ${this.#token}`);
|
|
348
|
+
if (route.responseMediaType !== "") headers.set("accept", route.responseMediaType);
|
|
309
349
|
if (options.body !== undefined) headers.set("content-type", options.contentType ?? "application/json");
|
|
310
|
-
/** @type {RequestInit} */
|
|
350
|
+
/** @type {RequestInit & { duplex?: "half" }} */
|
|
311
351
|
const init = { method: route.method, headers, redirect: "manual" };
|
|
312
|
-
if (options.
|
|
352
|
+
if (options.cache !== undefined) init.cache = options.cache;
|
|
353
|
+
if (route.permission.endsWith(":write") && typeof process !== "undefined" && process.release?.name === "node") {
|
|
354
|
+
// Node fetch replays buffered or absent bodies on 421; use a one-shot stream, including DELETE.
|
|
355
|
+
if (operation === "uploadImportSource" && bytes !== undefined) headers.set("content-length", String(bytes.byteLength));
|
|
356
|
+
init.body = new ReadableStream({ start(controller) { if (bytes !== undefined && bytes.byteLength > 0) controller.enqueue(bytes); controller.close(); } });
|
|
357
|
+
init.duplex = "half";
|
|
358
|
+
} else if (options.body !== undefined) init.body = typeof options.body === "string" ? options.body : options.body.slice().buffer;
|
|
313
359
|
if (options.signal !== undefined) init.signal = options.signal;
|
|
314
360
|
const response = await this.#fetch(url, init);
|
|
361
|
+
if (options.signal?.aborted) {
|
|
362
|
+
void response.body?.cancel().catch(() => undefined);
|
|
363
|
+
options.signal.throwIfAborted();
|
|
364
|
+
}
|
|
315
365
|
if (response.type === "opaqueredirect")
|
|
316
366
|
throw new TypeError("Fresh shape bootstrap requires server fetch; obtain a handle and snapshot offset with collection.shape() on your server.");
|
|
317
|
-
if (!route.successStatuses.includes(response.status)) throw await this.error(response);
|
|
318
|
-
|
|
319
|
-
await response.body?.cancel();
|
|
320
|
-
return { status: response.status, headers: response.headers, value: undefined };
|
|
321
|
-
}
|
|
322
|
-
return { status: response.status, headers: response.headers, value: await this.readJson(response) };
|
|
367
|
+
if (!route.successStatuses.includes(response.status)) throw await this.error(response, options.signal);
|
|
368
|
+
return response;
|
|
323
369
|
}
|
|
324
370
|
}
|
package/src/v1/usage.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { requireId } from "../ids.js";
|
|
2
|
+
import { requireName } from "./ids.js";
|
|
3
|
+
import { dictionary, flag, list, nullable, numeric, record, text } from "./management-decode.js";
|
|
4
|
+
import { members } from "./management-validation.js";
|
|
5
|
+
/** @import { V1Transport } from "./transport.js" */
|
|
6
|
+
/** @import { V1RequestOptions } from "./terrabase-v1.js" */
|
|
7
|
+
const period = record({ from: text, to: text, granularity: text, reads: numeric, writes: numeric });
|
|
8
|
+
const series = list(record({ start: text, reads: numeric, writes: numeric }));
|
|
9
|
+
const databaseUsage = record({ databaseId: requireId, storageBytes: numeric, logicalBytes: numeric, collections: numeric,
|
|
10
|
+
documents: numeric, reads: numeric, writes: numeric, period, series });
|
|
11
|
+
const projectUsage = record({ projectId: requireId, databases: numeric, storageBytes: numeric, logicalBytes: numeric,
|
|
12
|
+
documents: numeric, reads: numeric, writes: numeric, period, series, items: list(databaseUsage) });
|
|
13
|
+
const bandwidth = record({ bytesSent: numeric, bytesReceived: numeric });
|
|
14
|
+
const directedBandwidth = list(record({ sourceRegion: text, destinationRegion: text, kind: text, bytesSent: numeric, bytesReceived: numeric }));
|
|
15
|
+
const latency = record({ p50Ms: nullable(numeric), p95Ms: nullable(numeric), p99Ms: nullable(numeric) });
|
|
16
|
+
const analytics = record({ projectId: requireId, range: text, from: text, to: text, bucketSeconds: numeric,
|
|
17
|
+
items: list(record({ databaseId: requireId, databaseName: text, region: text,
|
|
18
|
+
series: list(record({ start: text, requests: dictionary(numeric), operations: dictionary(numeric), errors: numeric,
|
|
19
|
+
latency, storageBytes: nullable(numeric), clientBandwidth: bandwidth, replicationBandwidth: bandwidth })) })) });
|
|
20
|
+
const replication = record({ projectId: requireId, range: text, from: text, to: text, bucketSeconds: numeric,
|
|
21
|
+
items: list(record({ databaseId: requireId, databaseName: text, region: text, status: text, replicatedOps: numeric,
|
|
22
|
+
lagMs: nullable(numeric), divergence: nullable(flag), convergenceMs: nullable(numeric), lastApplied: nullable(text),
|
|
23
|
+
bandwidth: directedBandwidth, series: list(record({ start: text, replicatedOps: numeric, bandwidth: directedBandwidth })) })) });
|
|
24
|
+
/** @typedef {ReturnType<typeof databaseUsage>} V1DatabaseUsage */
|
|
25
|
+
/** @typedef {ReturnType<typeof projectUsage>} V1ProjectUsage */
|
|
26
|
+
/** @typedef {ReturnType<typeof analytics>} V1Analytics */
|
|
27
|
+
/** @typedef {ReturnType<typeof replication>} V1Replication */
|
|
28
|
+
/** @typedef {{ readonly granularity?: "hour" | "day"; readonly from?: string; readonly to?: string }} V1UsageRequest */
|
|
29
|
+
/** @typedef {{ readonly range?: "1h" | "24h" | "7d" | "30d"; readonly database?: string; readonly region?: string }} V1AnalyticsRequest */
|
|
30
|
+
/** @param {V1UsageRequest} request */
|
|
31
|
+
function usageQuery(request) {
|
|
32
|
+
members(request, ["granularity", "from", "to"]);
|
|
33
|
+
const query = new URLSearchParams();
|
|
34
|
+
if (request.granularity !== undefined) {
|
|
35
|
+
if (!["hour", "day"].includes(request.granularity)) throw new TypeError("granularity must be hour or day.");
|
|
36
|
+
query.set("granularity", request.granularity);
|
|
37
|
+
}
|
|
38
|
+
for (const name of /** @type {const} */ (["from", "to"])) {
|
|
39
|
+
const value = request[name];
|
|
40
|
+
if (value === undefined) continue;
|
|
41
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,7})?(?:Z|[+-]\d{2}:\d{2})$/u.test(value) || !Number.isFinite(Date.parse(value)))
|
|
42
|
+
throw new TypeError("from and to must be RFC 3339 instants.");
|
|
43
|
+
query.set(name, value);
|
|
44
|
+
}
|
|
45
|
+
return query;
|
|
46
|
+
}
|
|
47
|
+
/** @param {V1AnalyticsRequest} request @param {boolean} project */
|
|
48
|
+
function analyticsQuery(request, project) {
|
|
49
|
+
members(request, project ? ["range", "database", "region"] : ["range", "region"]);
|
|
50
|
+
const query = new URLSearchParams();
|
|
51
|
+
if (request.range !== undefined) {
|
|
52
|
+
if (!["1h", "24h", "7d", "30d"].includes(request.range)) throw new TypeError("Invalid analytics range.");
|
|
53
|
+
query.set("range", request.range);
|
|
54
|
+
}
|
|
55
|
+
if (request.database !== undefined) query.set("database", requireId(request.database));
|
|
56
|
+
if (request.region !== undefined) {
|
|
57
|
+
if (typeof request.region !== "string" || !/^[a-z][a-z0-9-]{0,62}$/u.test(request.region)) throw new TypeError("Invalid region.");
|
|
58
|
+
query.set("region", request.region);
|
|
59
|
+
}
|
|
60
|
+
return query;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Project and database usage retain the producer's separate response envelopes. */
|
|
64
|
+
export class V1ProjectUsageClient {
|
|
65
|
+
/** @type {V1Transport} */
|
|
66
|
+
#transport;
|
|
67
|
+
/** @param {V1Transport} transport */
|
|
68
|
+
constructor(transport) { this.#transport = transport; Object.freeze(this); }
|
|
69
|
+
/** @param {V1UsageRequest} [request] @param {V1RequestOptions} [options] @returns {Promise<V1ProjectUsage>} */
|
|
70
|
+
async usage(request = {}, options = {}) {
|
|
71
|
+
return projectUsage((await this.#transport.call("getProjectUsage", {}, { query: usageQuery(request), signal: options.signal })).value);
|
|
72
|
+
}
|
|
73
|
+
/** @param {V1AnalyticsRequest} [request] @param {V1RequestOptions} [options] @returns {Promise<V1Analytics>} */
|
|
74
|
+
async analytics(request = {}, options = {}) {
|
|
75
|
+
return analytics((await this.#transport.call("getProjectAnalytics", {}, { query: analyticsQuery(request, true), signal: options.signal })).value);
|
|
76
|
+
}
|
|
77
|
+
/** @param {V1AnalyticsRequest} [request] @param {V1RequestOptions} [options] @returns {Promise<V1Replication>} */
|
|
78
|
+
async replication(request = {}, options = {}) {
|
|
79
|
+
return replication((await this.#transport.call("getProjectReplication", {}, { query: analyticsQuery(request, true), signal: options.signal })).value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class V1DatabaseUsageClient {
|
|
83
|
+
/** @type {V1Transport} */
|
|
84
|
+
#transport;
|
|
85
|
+
/** @type {{database: string}} */
|
|
86
|
+
#params;
|
|
87
|
+
/** @param {V1Transport} transport @param {string} database */
|
|
88
|
+
constructor(transport, database) { this.#transport = transport; this.#params = { database: requireName("database", database) }; Object.freeze(this); }
|
|
89
|
+
/** @param {V1UsageRequest} [request] @param {V1RequestOptions} [options] @returns {Promise<V1DatabaseUsage>} */
|
|
90
|
+
async usage(request = {}, options = {}) {
|
|
91
|
+
return databaseUsage((await this.#transport.call("getDatabaseUsage", this.#params, { query: usageQuery(request), signal: options.signal })).value);
|
|
92
|
+
}
|
|
93
|
+
/** @param {Omit<V1AnalyticsRequest, "database">} [request] @param {V1RequestOptions} [options] @returns {Promise<V1Analytics>} */
|
|
94
|
+
async analytics(request = {}, options = {}) {
|
|
95
|
+
return analytics((await this.#transport.call("getDatabaseAnalytics", this.#params, { query: analyticsQuery(request, false), signal: options.signal })).value);
|
|
96
|
+
}
|
|
97
|
+
/** @param {Omit<V1AnalyticsRequest, "database">} [request] @param {V1RequestOptions} [options] @returns {Promise<V1Replication>} */
|
|
98
|
+
async replication(request = {}, options = {}) {
|
|
99
|
+
return replication((await this.#transport.call("getDatabaseReplication", this.#params, { query: analyticsQuery(request, false), signal: options.signal })).value);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param {unknown} value
|
|
3
|
-
* @param {string} [name]
|
|
4
|
-
* @returns {string}
|
|
5
|
-
*/
|
|
6
|
-
export function requireDatabaseUuid(value: unknown, name?: string): string;
|
|
7
1
|
/**
|
|
8
2
|
* @param {unknown} value
|
|
9
3
|
* @param {string} [name]
|
|
@@ -88,6 +82,7 @@ export function encodeDatabaseCommit(scope: DatabaseScope, commit: DatabaseCommi
|
|
|
88
82
|
readonly body: string;
|
|
89
83
|
readonly effect_digest: string;
|
|
90
84
|
}>;
|
|
85
|
+
export { requireId as requireDatabaseId } from "./ids.js";
|
|
91
86
|
export type Budget = {
|
|
92
87
|
nodes: number;
|
|
93
88
|
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Entity identities are canonical uppercase ULIDs, including explicit local development.
|
|
3
3
|
*/
|
|
4
|
-
export type
|
|
4
|
+
export type EntityId = import("./ids.js").EntityId;
|
|
5
5
|
/**
|
|
6
6
|
* All 64-bit quantities stay bigint in JavaScript and decimal strings on the wire.
|
|
7
7
|
*/
|
|
8
8
|
export type DatabaseScope = {
|
|
9
|
-
readonly tenant:
|
|
10
|
-
readonly database:
|
|
9
|
+
readonly tenant: EntityId;
|
|
10
|
+
readonly database: EntityId;
|
|
11
11
|
readonly shard: bigint;
|
|
12
12
|
};
|
|
13
13
|
export type CollectionBinding = {
|
|
14
|
-
readonly collection:
|
|
14
|
+
readonly collection: EntityId;
|
|
15
15
|
readonly schema_generation: bigint;
|
|
16
16
|
readonly schema_digest: string;
|
|
17
17
|
};
|
|
@@ -44,12 +44,12 @@ export type DatabaseField = {
|
|
|
44
44
|
readonly value: DatabaseValue;
|
|
45
45
|
};
|
|
46
46
|
export type DatabaseObserved = {
|
|
47
|
-
readonly replica:
|
|
47
|
+
readonly replica: EntityId;
|
|
48
48
|
readonly incarnation: string;
|
|
49
49
|
readonly sequence: bigint;
|
|
50
50
|
};
|
|
51
51
|
export type DatabaseEvent = DatabaseObserved & {
|
|
52
|
-
readonly database:
|
|
52
|
+
readonly database: EntityId;
|
|
53
53
|
readonly shard: bigint;
|
|
54
54
|
};
|
|
55
55
|
export type DatabaseAuthority = ({
|
|
@@ -58,7 +58,7 @@ export type DatabaseAuthority = ({
|
|
|
58
58
|
readonly mode: "single_writer";
|
|
59
59
|
readonly generation: bigint;
|
|
60
60
|
readonly writer: {
|
|
61
|
-
readonly replica:
|
|
61
|
+
readonly replica: EntityId;
|
|
62
62
|
readonly incarnation: string;
|
|
63
63
|
};
|
|
64
64
|
});
|
|
@@ -77,7 +77,7 @@ export type DatabaseWriteValue = ({
|
|
|
77
77
|
readonly kind: "tombstone";
|
|
78
78
|
});
|
|
79
79
|
export type DatabaseWrite = CollectionBinding & {
|
|
80
|
-
readonly document:
|
|
80
|
+
readonly document: EntityId;
|
|
81
81
|
readonly condition: DatabaseCondition;
|
|
82
82
|
readonly observed: readonly DatabaseObserved[];
|
|
83
83
|
readonly value: DatabaseWriteValue;
|
|
@@ -121,7 +121,7 @@ export type DatabaseQuery = {
|
|
|
121
121
|
readonly cursor?: string;
|
|
122
122
|
};
|
|
123
123
|
export type DatabaseQueryRow = {
|
|
124
|
-
readonly document:
|
|
124
|
+
readonly document: EntityId;
|
|
125
125
|
readonly point: DatabasePoint;
|
|
126
126
|
};
|
|
127
127
|
export type DatabaseQueryPage = {
|
|
@@ -188,7 +188,7 @@ export type DatabaseSubscriptionRequest = ({
|
|
|
188
188
|
readonly poll_cursor: string;
|
|
189
189
|
});
|
|
190
190
|
export type DatabaseSubscriptionEffect = {
|
|
191
|
-
readonly document:
|
|
191
|
+
readonly document: EntityId;
|
|
192
192
|
readonly point: DatabasePoint | null;
|
|
193
193
|
};
|
|
194
194
|
export type DatabaseSubscriptionGroup = {
|
package/types/http.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
/** Private transport for the named hosted identity and OIDC operations. */
|
|
2
2
|
export class TsAuthHttp {
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
* @param {{ readonly authReverseProxy?: boolean }} [options]
|
|
6
|
-
*/
|
|
7
|
-
constructor(config: TsAuthRuntimeConfig, options?: {
|
|
8
|
-
readonly authReverseProxy?: boolean;
|
|
9
|
-
});
|
|
3
|
+
/** @param {TsAuthRuntimeConfig} config */
|
|
4
|
+
constructor(config: TsAuthRuntimeConfig);
|
|
10
5
|
/**
|
|
11
6
|
* @readonly
|
|
12
7
|
* @type {ResolvedTsAuthRuntimeConfig}
|
|
@@ -39,7 +34,6 @@ export type TsAuthRequest<TBody> = {
|
|
|
39
34
|
readonly formBody?: URLSearchParams | string | undefined;
|
|
40
35
|
readonly userinfoAccessToken?: string | undefined;
|
|
41
36
|
readonly resourceIntrospectionBasic?: string | undefined;
|
|
42
|
-
readonly issuer?: string | undefined;
|
|
43
37
|
readonly signal?: AbortSignal | undefined;
|
|
44
38
|
};
|
|
45
39
|
import type { ResolvedTsAuthRuntimeConfig } from "./config.js";
|
package/types/ids.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** @returns {EntityId} Monotonic within a millisecond, including clock rollback. */
|
|
2
|
+
export function generateId(): EntityId;
|
|
3
|
+
/** @param {unknown} value @returns {value is EntityId} */
|
|
4
|
+
export function isValidId(value: unknown): value is EntityId;
|
|
5
|
+
/** @param {unknown} value @param {string} [name] @returns {EntityId} */
|
|
6
|
+
export function requireId(value: unknown, name?: string): EntityId;
|
|
7
|
+
/**
|
|
8
|
+
* A plain 26-character, uppercase Crockford ULID.
|
|
9
|
+
*/
|
|
10
|
+
export type EntityId = string;
|
package/types/index.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
export { v1Filter } from "./v1/filter.js";
|
|
2
|
-
export {
|
|
2
|
+
export { V1ShapeSubscription } from "./v1/shape-subscription.js";
|
|
3
3
|
export { ExactDecimal } from "./v1/json.js";
|
|
4
4
|
export { staticBaseUrlResolver } from "./v1/transport.js";
|
|
5
|
+
export { V1Databases } from "./v1/catalog.js";
|
|
6
|
+
export { V1SavedQueries } from "./v1/saved-queries.js";
|
|
7
|
+
export { V1DatabaseSchemaClient } from "./v1/database-schema.js";
|
|
8
|
+
export { V1Indexes } from "./v1/indexes.js";
|
|
9
|
+
export { V1Imports } from "./v1/imports.js";
|
|
10
|
+
export type V1ShapeSubscribeOptions = import("./v1/shape-subscription.js").V1ShapeSubscribeOptions;
|
|
11
|
+
export type V1ShapeDocument = import("./v1/shape-subscription.js").V1ShapeDocument;
|
|
12
|
+
export type V1SealedShapePosition = import("./v1/shape-reader.js").V1SealedShapePosition;
|
|
13
|
+
export type EntityId = import("./ids.js").EntityId;
|
|
5
14
|
export type TerraBaseV1ClientConfig = import("./v1/transport.js").TerraBaseV1ClientConfig;
|
|
6
15
|
export type V1RequestOptions = import("./v1/terrabase-v1.js").V1RequestOptions;
|
|
7
16
|
export type V1ReadOptions = import("./v1/terrabase-v1.js").V1ReadOptions;
|
|
@@ -31,6 +40,9 @@ export type V1JsonInputObject = import("./v1/json.js").JsonInputObject;
|
|
|
31
40
|
export type V1ShapeRequest = import("./v1/shapes.js").V1ShapeRequest;
|
|
32
41
|
export type V1ShapeChange = import("./v1/shapes.js").V1ShapeChange;
|
|
33
42
|
export type V1ShapeOp = import("./v1/shapes.js").V1ShapeOp;
|
|
43
|
+
export type V1SavedQuery = import("./v1/saved-queries.js").V1SavedQuery;
|
|
44
|
+
export type V1SavedQueryRequest = import("./v1/saved-queries.js").V1SavedQueryRequest;
|
|
45
|
+
export type V1SavedQueryPage = import("./v1/saved-queries.js").V1SavedQueryPage;
|
|
34
46
|
export type TerraBaseClientConfig = import("./v1/transport.js").TerraBaseV1ClientConfig;
|
|
35
47
|
export type V1EndpointContext = import("./v1/transport.js").V1EndpointContext;
|
|
36
48
|
export type V1EndpointResolver = import("./v1/transport.js").V1EndpointResolver;
|
|
@@ -38,6 +50,63 @@ export type V1CollectionInfo = import("./v1/terrabase-v1.js").V1CollectionInfo;
|
|
|
38
50
|
export type V1CollectionPage = import("./v1/terrabase-v1.js").V1CollectionPage;
|
|
39
51
|
export type V1CollectionListOptions = import("./v1/terrabase-v1.js").V1CollectionListOptions;
|
|
40
52
|
export type V1ShapePage = import("./v1/shapes.js").V1ShapePage;
|
|
53
|
+
export type V1SqlRow = import("./v1/sql.js").V1SqlRow;
|
|
54
|
+
export type V1SqlResult = import("./v1/sql.js").V1SqlResult;
|
|
55
|
+
export type V1SqlIndexSuggestion = import("./v1/sql.js").V1SqlIndexSuggestion;
|
|
56
|
+
export type V1SqlCheck = import("./v1/sql.js").V1SqlCheck;
|
|
57
|
+
export type V1ChangeStreamRequest = import("./v1/changes.js").V1ChangeStreamRequest;
|
|
58
|
+
export type V1DatabaseChange = import("./v1/changes.js").V1DatabaseChange;
|
|
59
|
+
export type V1DatabaseChangeCursor = import("./v1/changes.js").V1DatabaseChangeCursor;
|
|
60
|
+
export type V1ManagedDatabase = import("./v1/catalog.js").V1ManagedDatabase;
|
|
61
|
+
export type V1DatabaseCreateRequest = import("./v1/catalog.js").V1DatabaseCreateRequest;
|
|
62
|
+
export type V1DatabaseUpdateRequest = import("./v1/catalog.js").V1DatabaseUpdateRequest;
|
|
63
|
+
export type V1DatabaseBranchRequest = import("./v1/catalog.js").V1DatabaseBranchRequest;
|
|
64
|
+
export type V1DatabaseListRequest = import("./v1/catalog.js").V1DatabaseListRequest;
|
|
65
|
+
export type V1DatabasePage = import("./v1/catalog.js").V1DatabasePage;
|
|
66
|
+
export type V1CollectionSchema = import("./v1/catalog.js").V1CollectionSchema;
|
|
67
|
+
export type V1InferredSchema = import("./v1/database-schema.js").V1InferredSchema;
|
|
68
|
+
export type V1DatabaseSchema = import("./v1/database-schema.js").V1DatabaseSchema;
|
|
69
|
+
export type V1UniqueSchema = import("./v1/database-schema.js").V1UniqueSchema;
|
|
70
|
+
export type V1UniqueSchemaRequest = import("./v1/database-schema.js").V1UniqueSchemaRequest;
|
|
71
|
+
export type V1QueryShapes = import("./v1/database-schema.js").V1QueryShapes;
|
|
72
|
+
export type V1Index = import("./v1/indexes.js").V1Index;
|
|
73
|
+
export type V1IndexList = import("./v1/indexes.js").V1IndexList;
|
|
74
|
+
export type V1AutoIndexPolicy = import("./v1/indexes.js").V1AutoIndexPolicy;
|
|
75
|
+
export type V1IndexRecommendations = import("./v1/indexes.js").V1IndexRecommendations;
|
|
76
|
+
export type V1AppliedIndexRecommendation = import("./v1/indexes.js").V1AppliedIndexRecommendation;
|
|
77
|
+
export type V1CreateIndexRequest = import("./v1/indexes.js").V1CreateIndexRequest;
|
|
78
|
+
export type V1DatabaseUsage = import("./v1/usage.js").V1DatabaseUsage;
|
|
79
|
+
export type V1ProjectUsage = import("./v1/usage.js").V1ProjectUsage;
|
|
80
|
+
export type V1Analytics = import("./v1/usage.js").V1Analytics;
|
|
81
|
+
export type V1Replication = import("./v1/usage.js").V1Replication;
|
|
82
|
+
export type V1UsageRequest = import("./v1/usage.js").V1UsageRequest;
|
|
83
|
+
export type V1AnalyticsRequest = import("./v1/usage.js").V1AnalyticsRequest;
|
|
84
|
+
export type V1Backup = import("./v1/backups.js").V1Backup;
|
|
85
|
+
export type V1BackupPage = import("./v1/backups.js").V1BackupPage;
|
|
86
|
+
export type V1BackupPolicy = import("./v1/backups.js").V1BackupPolicy;
|
|
87
|
+
export type V1RestoreWindow = import("./v1/backups.js").V1RestoreWindow;
|
|
88
|
+
export type V1PointInTimePlan = import("./v1/backups.js").V1PointInTimePlan;
|
|
89
|
+
export type V1RestoredDatabase = import("./v1/backups.js").V1RestoredDatabase;
|
|
90
|
+
export type V1BackupDestination = import("./v1/backups.js").V1BackupDestination;
|
|
91
|
+
export type V1BackupPolicyRequest = import("./v1/backups.js").V1BackupPolicyRequest;
|
|
92
|
+
export type V1PointInTimeRequest = import("./v1/backups.js").V1PointInTimeRequest;
|
|
93
|
+
export type V1PointInTimeRestoreRequest = import("./v1/backups.js").V1PointInTimeRestoreRequest;
|
|
94
|
+
export type V1BackupDestinationRequest = import("./v1/backups.js").V1BackupDestinationRequest;
|
|
95
|
+
export type V1ImportJob = import("./v1/imports.js").V1ImportJob;
|
|
96
|
+
export type V1ImportOptions = import("./v1/imports.js").V1ImportOptions;
|
|
97
|
+
export type V1CreateImportRequest = import("./v1/imports.js").V1CreateImportRequest;
|
|
98
|
+
export type TerraBaseSystemClientConfig = import("./v1/system.js").TerraBaseSystemClientConfig;
|
|
99
|
+
export type V1ProbeStatus = import("./v1/system.js").V1ProbeStatus;
|
|
100
|
+
export type V1ReplicationHealth = import("./v1/system.js").V1ReplicationHealth;
|
|
101
|
+
export type V1PlatformDatabases = import("./v1/system.js").V1PlatformDatabases;
|
|
102
|
+
export type V1ShapeManifest = import("./v1/shape-manifest.js").V1ShapeManifest;
|
|
103
|
+
export type V1ShapeManifestRequest = import("./v1/shape-manifest.js").V1ShapeManifestRequest;
|
|
104
|
+
export type V1ShapeKeyRequest = import("./v1/shape-reader.js").V1ShapeKeyRequest;
|
|
105
|
+
export type V1ShapeKey = import("./v1/shape-reader.js").V1ShapeKey;
|
|
41
106
|
export { createTerraBaseV1Client as createTerraBaseClient, TerraBaseV1Client as TerraBaseClient, createTerraBaseV1Client, TerraBaseV1Client, V1Database, V1Collection, V1Collections, V1Transaction } from "./v1/terrabase-v1.js";
|
|
42
107
|
export { terraScaleReleaseBlockers, TerraScaleCapabilityUnavailableError } from "./management-contracts.js";
|
|
43
108
|
export { TerraBaseV1Error, V1PreconditionFailedError, V1InvalidKeyError, V1ForbiddenScopeError, V1NotFoundError, V1ErrorCode, isTerraBaseV1Error } from "./v1/errors.js";
|
|
109
|
+
export { generateId, isValidId, requireId } from "./ids.js";
|
|
110
|
+
export { V1ProjectUsageClient, V1DatabaseUsageClient } from "./v1/usage.js";
|
|
111
|
+
export { V1Backups, V1BackupDestinationClient } from "./v1/backups.js";
|
|
112
|
+
export { createTerraBaseSystemClient, V1Health, V1Platform } from "./v1/system.js";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @returns {void}
|
|
4
4
|
*/
|
|
5
5
|
export function assertLocalSqliteEnvironment(environment?: Readonly<Record<string, string | undefined>>): void;
|
|
6
|
-
export const localSqlitePresenceIndicators: readonly ["CI", "CONTINUOUS_INTEGRATION", "GITHUB_ACTIONS", "GITLAB_CI", "FORGEJO_ACTIONS", "GITEA_ACTIONS", "TF_BUILD", "BUILDKITE", "CIRCLECI", "JENKINS_URL", "TEAMCITY_VERSION", "VERCEL", "NETLIFY", "CF_PAGES", "RENDER", "
|
|
6
|
+
export const localSqlitePresenceIndicators: readonly ["CI", "CONTINUOUS_INTEGRATION", "GITHUB_ACTIONS", "GITLAB_CI", "FORGEJO_ACTIONS", "GITEA_ACTIONS", "TF_BUILD", "BUILDKITE", "CIRCLECI", "JENKINS_URL", "TEAMCITY_VERSION", "VERCEL", "NETLIFY", "CF_PAGES", "RENDER", "K_SERVICE", "CLOUD_RUN_JOB", "KUBERNETES_SERVICE_HOST", "AWS_LAMBDA_FUNCTION_NAME", "AWS_EXECUTION_ENV", "ECS_CONTAINER_METADATA_URI", "ECS_CONTAINER_METADATA_URI_V4", "WEBSITE_INSTANCE_ID", "WEBSITE_SITE_NAME", "FUNCTIONS_WORKER_RUNTIME", "DYNO", "HEROKU_APP_NAME", "RAILWAY_ENVIRONMENT", "RAILWAY_SERVICE_ID", "NOMAD_ALLOC_ID", "TERRASCALE_DEPLOYMENT", "TERRASCALE_QUALIFICATION"];
|
|
7
7
|
/**
|
|
8
8
|
* Explicit opt-in for a hosted development environment.
|
|
9
9
|
*
|
package/types/local/store.d.ts
CHANGED
|
@@ -34,6 +34,16 @@ export class TerraScaleSqliteStore {
|
|
|
34
34
|
* @returns {T[]}
|
|
35
35
|
*/
|
|
36
36
|
list<T>(namespace: string, scope: string): T[];
|
|
37
|
+
/**
|
|
38
|
+
* @template T
|
|
39
|
+
* @param {string} namespace
|
|
40
|
+
* @param {string} scope
|
|
41
|
+
* @returns {readonly { readonly id: string; readonly value: T }[]}
|
|
42
|
+
*/
|
|
43
|
+
listEntries<T>(namespace: string, scope: string): readonly {
|
|
44
|
+
readonly id: string;
|
|
45
|
+
readonly value: T;
|
|
46
|
+
}[];
|
|
37
47
|
/**
|
|
38
48
|
* @template T
|
|
39
49
|
* @param {string} namespace
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
export function localFixture(options?: Omit<TerraScaleSqliteRuntimeOptions, "sqlite">): Promise<{
|
|
7
7
|
runtime: import("./index.js").TerraScaleSqliteRuntime;
|
|
8
8
|
client: import("./legacy-client.js").TerraBaseClient;
|
|
9
|
-
collection:
|
|
9
|
+
collection: string;
|
|
10
10
|
binding: {
|
|
11
|
-
collection:
|
|
11
|
+
collection: string;
|
|
12
12
|
schema_generation: bigint;
|
|
13
13
|
schema_digest: string;
|
|
14
14
|
};
|
package/types/postgres.d.ts
CHANGED
|
@@ -25,8 +25,8 @@ export function postgresQuery(statement: string, parameters?: readonly unknown[]
|
|
|
25
25
|
* readonly port: number;
|
|
26
26
|
* readonly tlsServerName: string;
|
|
27
27
|
* readonly caCertificatePem: string;
|
|
28
|
-
* readonly database:
|
|
29
|
-
* readonly keyId:
|
|
28
|
+
* readonly database: import("./ids.js").EntityId;
|
|
29
|
+
* readonly keyId: import("./ids.js").EntityId;
|
|
30
30
|
* readonly password: string;
|
|
31
31
|
* readonly connectTimeoutMs?: number;
|
|
32
32
|
* }} PostgresConfig
|
|
@@ -107,8 +107,8 @@ export type PostgresConfig = {
|
|
|
107
107
|
readonly port: number;
|
|
108
108
|
readonly tlsServerName: string;
|
|
109
109
|
readonly caCertificatePem: string;
|
|
110
|
-
readonly database:
|
|
111
|
-
readonly keyId:
|
|
110
|
+
readonly database: import("./ids.js").EntityId;
|
|
111
|
+
readonly keyId: import("./ids.js").EntityId;
|
|
112
112
|
readonly password: string;
|
|
113
113
|
readonly connectTimeoutMs?: number;
|
|
114
114
|
};
|