@query-farm/vgi 0.43.0 → 0.44.0
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/README.md +5 -2
- package/dist/attach-ticket.d.ts +18 -7
- package/dist/client-entry.js +215 -91
- package/dist/client-entry.js.map +10 -9
- package/dist/codec/asd.d.ts +3 -1
- package/dist/codec/conform.d.ts +51 -0
- package/dist/errors.d.ts +5 -1
- package/dist/index.core.d.ts +1 -1
- package/dist/index.js +218 -39
- package/dist/index.js.map +17 -16
- package/dist/protocol/handlers/shared.d.ts +2 -1
- package/dist/protocol/serializers/shared.d.ts +2 -1
- package/dist/rpc-server.d.ts +2 -2
- package/dist/serve-entry.js +259 -89
- package/dist/serve-entry.js.map +13 -12
- package/dist/worker-cf-entry.js +201 -30
- package/dist/worker-cf-entry.js.map +17 -16
- package/package.json +3 -3
- package/src/attach-ticket.ts +41 -13
- package/src/catalog/composite.ts +2 -1
- package/src/catalog/interface.ts +5 -4
- package/src/catalog/read-only.ts +8 -6
- package/src/client/client.ts +13 -5
- package/src/codec/asd.ts +5 -2
- package/src/codec/conform.ts +193 -0
- package/src/errors.ts +27 -7
- package/src/functions/registry.ts +3 -2
- package/src/http/fetch.ts +1 -1
- package/src/index.core.ts +3 -1
- package/src/protocol/handlers/shared.ts +8 -2
- package/src/protocol/serializers/bind.ts +3 -1
- package/src/protocol/serializers/shared.ts +5 -2
- package/src/rpc-server.ts +7 -7
package/dist/codec/asd.d.ts
CHANGED
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
import { type VgiSchema } from "../arrow/index.js";
|
|
16
16
|
/**
|
|
17
17
|
* Encode a typed object as a single-row Arrow IPC stream using `schema`.
|
|
18
|
-
* Matches Python's `ArrowSerializableDataclass.serialize_to_bytes()
|
|
18
|
+
* Matches Python's `ArrowSerializableDataclass.serialize_to_bytes()`, including
|
|
19
|
+
* its container rules: a non-nullable list/map left out or null is written as
|
|
20
|
+
* empty, and list items / map values are never null (see `conformRecord`).
|
|
19
21
|
*/
|
|
20
22
|
export declare function encodeASD(schema: VgiSchema, obj: Record<string, any>): Uint8Array;
|
|
21
23
|
/** Compare two strings by Unicode code point (= UTF-8 byte order). */
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire conformance for protocol records.
|
|
3
|
+
*
|
|
4
|
+
* vgi-python is the reference for the wire shape, and two of its rules are not
|
|
5
|
+
* expressed by a record's Arrow schema nullability flags alone:
|
|
6
|
+
*
|
|
7
|
+
* 1. A **non-nullable list or map column is never null.** Python's dataclass
|
|
8
|
+
* defaults a `list[...]` / `dict[...]` field to an empty container, so an
|
|
9
|
+
* "absent" list goes out as `[]`. A JS caller that leaves the field out (or
|
|
10
|
+
* passes `null`) would otherwise put a null in a column the schema calls
|
|
11
|
+
* non-null — `CatalogInfo.releases`, `CatalogInfo.attach_option_specs`,
|
|
12
|
+
* ... — which a strict client rejects as a protocol error.
|
|
13
|
+
*
|
|
14
|
+
* 2. **List items and map values are never null** unless the Python annotation
|
|
15
|
+
* says so (`list[str | None]`). pyarrow marks every list item field nullable,
|
|
16
|
+
* so the generated schemas carry `item: nullable=true` everywhere and cannot
|
|
17
|
+
* tell the two apart. In the whole protocol exactly one field has optional
|
|
18
|
+
* items — `argument_names` on `BindRequest` / `AggregateBindRequest` (a
|
|
19
|
+
* positional argument has no name). Every other null item is a bug on the
|
|
20
|
+
* sending side (e.g. `BindResponse.lookup_names` built from an unset secret
|
|
21
|
+
* name, where Python sends `""`).
|
|
22
|
+
*
|
|
23
|
+
* `conformRecord` applies both rules to a record about to be encoded: a null or
|
|
24
|
+
* absent non-nullable list/map becomes empty, and a null list item / map value
|
|
25
|
+
* becomes its type's zero value (`""`, `0`, `false`, empty bytes, empty list),
|
|
26
|
+
* which is also what the C++ client reads such an item as. It never mutates its
|
|
27
|
+
* input (catalog items may be frozen and shared) and returns the input itself
|
|
28
|
+
* when nothing needed changing. Nullable columns, and scalars, pass through
|
|
29
|
+
* untouched: a null in a non-nullable scalar column has no safe default and is
|
|
30
|
+
* left for the caller to fix (see `wireViolations`).
|
|
31
|
+
*/
|
|
32
|
+
import { type VgiSchema, type VgiDataType } from "../arrow/index.js";
|
|
33
|
+
/**
|
|
34
|
+
* Top-level / struct-child field names whose list items may legitimately be
|
|
35
|
+
* null (the Python annotation is `list[X | None]`). Derived from vgi-python by
|
|
36
|
+
* walking every protocol dataclass's type hints; keep in sync if the protocol
|
|
37
|
+
* adds another optional-item list.
|
|
38
|
+
*/
|
|
39
|
+
export declare const OPTIONAL_ITEM_FIELDS: ReadonlySet<string>;
|
|
40
|
+
/** The value a non-null slot of `type` takes when the sender left it null. */
|
|
41
|
+
export declare function zeroValue(type: VgiDataType): unknown;
|
|
42
|
+
/**
|
|
43
|
+
* `obj` conformed to `schema`'s wire rules (see the module comment). Returns
|
|
44
|
+
* `obj` itself when nothing changed.
|
|
45
|
+
*/
|
|
46
|
+
export declare function conformRecord<T extends Record<string, any>>(schema: VgiSchema, obj: T): T;
|
|
47
|
+
/**
|
|
48
|
+
* Column-dict form of `conformRecord` for `batchFromColumns` callers: each
|
|
49
|
+
* value is a one-element array holding the row's value.
|
|
50
|
+
*/
|
|
51
|
+
export declare function conformColumns(schema: VgiSchema, columns: Record<string, unknown[]>): Record<string, unknown[]>;
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import type { ErrorCode } from "@query-farm/vgi-rpc";
|
|
1
2
|
export declare class VgiError extends Error {
|
|
2
|
-
|
|
3
|
+
/** Canonical code hoisted as `vgi_rpc.error_code`; unset means `UNKNOWN`. */
|
|
4
|
+
readonly errorCode?: ErrorCode;
|
|
5
|
+
constructor(message: string, code?: ErrorCode);
|
|
3
6
|
}
|
|
7
|
+
/** A worker bug (the function returned the wrong number of rows): UNKNOWN. */
|
|
4
8
|
export declare class RowCountMismatchError extends VgiError {
|
|
5
9
|
constructor(expected: number, actual: number);
|
|
6
10
|
}
|
package/dist/index.core.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export type { LandingInfo } from "./http/landing.js";
|
|
|
28
28
|
export { createLandingRoutes } from "./http/landing.js";
|
|
29
29
|
export { BindResultSchema, ScanFunctionResultSchema } from "./generated/vgi-protocol-schemas.js";
|
|
30
30
|
export { type AttachOptionSpec, serializeAttachOptionSpec, serializeAttachOptionSpecs, deserializeAttachOptionSpec, deserializeAttachOptionSpecs, RESERVED_ATTACH_OPTION, ReservedAttachOptionError, } from "./catalog/attach-option.js";
|
|
31
|
-
export { ATTACH_TICKET_OPTION, ATTACH_TICKET_PREFIX, ATTACH_TICKETS_PROTOCOL_NAME, ATTACH_TICKETS_PROTOCOL_VERSION, ATTACH_TICKET_SCHEMA, SEAL_ATTACH_REQUEST_SCHEMA, AttachTicketExpiredError, AttachTicketInvalidError, AttachTicketRequestError, SealAttachDeniedError, type AttachTicketClaims, type RestoredAttach, attachTicketAad, mintAttachTicket, openAttachTicket, redeemAttachTicket, } from "./attach-ticket.js";
|
|
31
|
+
export { ATTACH_TICKET_OPTION, ATTACH_TICKET_PREFIX, ATTACH_TICKETS_PROTOCOL_NAME, ATTACH_TICKETS_PROTOCOL_VERSION, ATTACH_TICKET_SCHEMA, SEAL_ATTACH_REQUEST_SCHEMA, AttachTicketExpiredError, AttachTicketInvalidError, AttachTicketRequestError, SealAttachDeniedError, type AttachTicket, type AttachTicketClaims, type RestoredAttach, encodeAttachTicket, attachTicketAad, mintAttachTicket, openAttachTicket, redeemAttachTicket, } from "./attach-ticket.js";
|
|
32
32
|
export { type ColumnStatistics, serializeColumnStatistics } from "./util/statistics.js";
|
|
33
33
|
export { toUint8Array } from "./util/bytes.js";
|
|
34
34
|
export { iterRows, batchFromRows, batchFromColumns, emptyBatch, filterBatch, projectSchema, projectBatch, batchToScalarDict, batchToSecretDict, safeNumber, } from "./util/arrow/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
2
25
|
var __returnValue = (v) => v;
|
|
3
26
|
function __exportSetter(name, newValue) {
|
|
4
27
|
this[name] = __returnValue.bind(null, newValue);
|
|
@@ -2021,6 +2044,11 @@ var init_arrow = __esm(() => {
|
|
|
2021
2044
|
});
|
|
2022
2045
|
|
|
2023
2046
|
// src/functions/storage-cf-do.ts
|
|
2047
|
+
var exports_storage_cf_do = {};
|
|
2048
|
+
__export(exports_storage_cf_do, {
|
|
2049
|
+
FunctionStorageCfDo: () => FunctionStorageCfDo
|
|
2050
|
+
});
|
|
2051
|
+
|
|
2024
2052
|
class FunctionStorageCfDo {
|
|
2025
2053
|
_baseUrl;
|
|
2026
2054
|
_token;
|
|
@@ -2466,7 +2494,7 @@ function resolveStorageFromEnv() {
|
|
|
2466
2494
|
return new FunctionStorageSqlite;
|
|
2467
2495
|
}
|
|
2468
2496
|
if (backend === "cloudflare-do") {
|
|
2469
|
-
init_storage_cf_do();
|
|
2497
|
+
const { FunctionStorageCfDo } = (init_storage_cf_do(), __toCommonJS(exports_storage_cf_do));
|
|
2470
2498
|
return FunctionStorageCfDo.fromEnv();
|
|
2471
2499
|
}
|
|
2472
2500
|
throw new Error(`Unknown VGI_WORKER_SHARED_STORAGE backend: '${backend}'. Supported: 'memory', 'sqlite', 'cloudflare-do'.`);
|
|
@@ -2637,9 +2665,12 @@ var DEFAULT_MAX_WORKERS = 99999;
|
|
|
2637
2665
|
|
|
2638
2666
|
// src/errors.ts
|
|
2639
2667
|
class VgiError extends Error {
|
|
2640
|
-
|
|
2668
|
+
errorCode;
|
|
2669
|
+
constructor(message, code) {
|
|
2641
2670
|
super(message);
|
|
2642
2671
|
this.name = "VgiError";
|
|
2672
|
+
if (code !== undefined)
|
|
2673
|
+
this.errorCode = code;
|
|
2643
2674
|
}
|
|
2644
2675
|
}
|
|
2645
2676
|
|
|
@@ -2652,42 +2683,42 @@ class RowCountMismatchError extends VgiError {
|
|
|
2652
2683
|
|
|
2653
2684
|
class FunctionNotFoundError extends VgiError {
|
|
2654
2685
|
constructor(name, available) {
|
|
2655
|
-
super(`Unknown function '${name}'
|
|
2686
|
+
super(`Unknown function '${name}'`, "NOT_FOUND");
|
|
2656
2687
|
this.name = "FunctionNotFoundError";
|
|
2657
2688
|
}
|
|
2658
2689
|
}
|
|
2659
2690
|
|
|
2660
2691
|
class CatalogReadOnlyError extends VgiError {
|
|
2661
2692
|
constructor(operation) {
|
|
2662
|
-
super(`catalog is read-only: ${operation} is not supported
|
|
2693
|
+
super(`catalog is read-only: ${operation} is not supported`, "FAILED_PRECONDITION");
|
|
2663
2694
|
this.name = "CatalogReadOnlyError";
|
|
2664
2695
|
}
|
|
2665
2696
|
}
|
|
2666
2697
|
|
|
2667
2698
|
class CatalogNotFoundError extends VgiError {
|
|
2668
2699
|
constructor(entity, name) {
|
|
2669
|
-
super(`${entity} '${name}' not found
|
|
2700
|
+
super(`${entity} '${name}' not found`, "NOT_FOUND");
|
|
2670
2701
|
this.name = "CatalogNotFoundError";
|
|
2671
2702
|
}
|
|
2672
2703
|
}
|
|
2673
2704
|
|
|
2674
2705
|
class CatalogAlreadyExistsError extends VgiError {
|
|
2675
2706
|
constructor(entity, name) {
|
|
2676
|
-
super(`${entity} '${name}' already exists
|
|
2707
|
+
super(`${entity} '${name}' already exists`, "ALREADY_EXISTS");
|
|
2677
2708
|
this.name = "CatalogAlreadyExistsError";
|
|
2678
2709
|
}
|
|
2679
2710
|
}
|
|
2680
2711
|
|
|
2681
2712
|
class ArgumentValidationError extends VgiError {
|
|
2682
2713
|
constructor(message) {
|
|
2683
|
-
super(message);
|
|
2714
|
+
super(message, "INVALID_ARGUMENT");
|
|
2684
2715
|
this.name = "ArgumentValidationError";
|
|
2685
2716
|
}
|
|
2686
2717
|
}
|
|
2687
2718
|
|
|
2688
2719
|
class NoCatalogError extends VgiError {
|
|
2689
2720
|
constructor() {
|
|
2690
|
-
super("No catalog is configured for this worker");
|
|
2721
|
+
super("No catalog is configured for this worker", "UNIMPLEMENTED");
|
|
2691
2722
|
this.name = "NoCatalogError";
|
|
2692
2723
|
}
|
|
2693
2724
|
}
|
|
@@ -5381,6 +5412,137 @@ init_arrow();
|
|
|
5381
5412
|
|
|
5382
5413
|
// src/protocol/serializers/shared.ts
|
|
5383
5414
|
init_arrow();
|
|
5415
|
+
|
|
5416
|
+
// src/codec/conform.ts
|
|
5417
|
+
init_arrow();
|
|
5418
|
+
var OPTIONAL_ITEM_FIELDS = new Set(["argument_names"]);
|
|
5419
|
+
function children(type) {
|
|
5420
|
+
return type.children ?? [];
|
|
5421
|
+
}
|
|
5422
|
+
function mapValueType(type) {
|
|
5423
|
+
const entries = children(type)[0].type;
|
|
5424
|
+
return children(entries)[1].type;
|
|
5425
|
+
}
|
|
5426
|
+
function mapPairs(raw) {
|
|
5427
|
+
if (Array.isArray(raw))
|
|
5428
|
+
return raw.map((e) => Array.isArray(e) ? [e[0], e[1]] : [e?.key, e?.value]);
|
|
5429
|
+
if (raw instanceof Map)
|
|
5430
|
+
return Array.from(raw.entries());
|
|
5431
|
+
if (typeof raw[Symbol.iterator] === "function")
|
|
5432
|
+
return Array.from(raw);
|
|
5433
|
+
return Object.entries(raw);
|
|
5434
|
+
}
|
|
5435
|
+
function zeroValue(type) {
|
|
5436
|
+
if (isUtf8(type) || isDictionary(type))
|
|
5437
|
+
return "";
|
|
5438
|
+
if (isBinary(type))
|
|
5439
|
+
return new Uint8Array(0);
|
|
5440
|
+
if (isBool(type))
|
|
5441
|
+
return false;
|
|
5442
|
+
if (isInt(type))
|
|
5443
|
+
return type.bitWidth === 64 ? 0n : 0;
|
|
5444
|
+
if (isFloat(type))
|
|
5445
|
+
return 0;
|
|
5446
|
+
if (isList(type) || isMap(type))
|
|
5447
|
+
return [];
|
|
5448
|
+
if (isStruct(type)) {
|
|
5449
|
+
const out = {};
|
|
5450
|
+
for (const c of children(type))
|
|
5451
|
+
out[c.name] = c.nullable ? null : conformValue(c.type, undefined, false, c.name);
|
|
5452
|
+
return out;
|
|
5453
|
+
}
|
|
5454
|
+
return null;
|
|
5455
|
+
}
|
|
5456
|
+
var HAS_CONTAINER = new WeakMap;
|
|
5457
|
+
function hasContainer(type) {
|
|
5458
|
+
const cached = HAS_CONTAINER.get(type);
|
|
5459
|
+
if (cached !== undefined)
|
|
5460
|
+
return cached;
|
|
5461
|
+
let has = isList(type) || isMap(type);
|
|
5462
|
+
if (!has && isStruct(type))
|
|
5463
|
+
has = children(type).some((c) => hasContainer(c.type));
|
|
5464
|
+
HAS_CONTAINER.set(type, has);
|
|
5465
|
+
return has;
|
|
5466
|
+
}
|
|
5467
|
+
function conformValue(type, value, nullable, name) {
|
|
5468
|
+
if (value == null) {
|
|
5469
|
+
if (nullable)
|
|
5470
|
+
return value ?? null;
|
|
5471
|
+
if (isList(type) || isMap(type))
|
|
5472
|
+
return [];
|
|
5473
|
+
return value;
|
|
5474
|
+
}
|
|
5475
|
+
if (!hasContainer(type))
|
|
5476
|
+
return value;
|
|
5477
|
+
if (isList(type)) {
|
|
5478
|
+
const itemType = children(type)[0].type;
|
|
5479
|
+
const itemsNullable = OPTIONAL_ITEM_FIELDS.has(name);
|
|
5480
|
+
const items = Array.isArray(value) ? value : Array.from(value);
|
|
5481
|
+
let changed = !Array.isArray(value);
|
|
5482
|
+
const out = items.map((item) => {
|
|
5483
|
+
const next = item == null && !itemsNullable ? zeroValue(itemType) : conformValue(itemType, item, true, name);
|
|
5484
|
+
if (next !== item)
|
|
5485
|
+
changed = true;
|
|
5486
|
+
return next;
|
|
5487
|
+
});
|
|
5488
|
+
return changed ? out : value;
|
|
5489
|
+
}
|
|
5490
|
+
if (isMap(type)) {
|
|
5491
|
+
const valueType = mapValueType(type);
|
|
5492
|
+
const pairs = mapPairs(value);
|
|
5493
|
+
let changed = false;
|
|
5494
|
+
const out = pairs.map(([k, v]) => {
|
|
5495
|
+
const next = v == null ? zeroValue(valueType) : conformValue(valueType, v, true, name);
|
|
5496
|
+
if (next !== v)
|
|
5497
|
+
changed = true;
|
|
5498
|
+
return [k, next];
|
|
5499
|
+
});
|
|
5500
|
+
return changed ? out : value;
|
|
5501
|
+
}
|
|
5502
|
+
if (isStruct(type)) {
|
|
5503
|
+
let out = null;
|
|
5504
|
+
for (const c of children(type)) {
|
|
5505
|
+
const v = value[c.name];
|
|
5506
|
+
const next = conformValue(c.type, v, c.nullable, c.name);
|
|
5507
|
+
if (next !== v) {
|
|
5508
|
+
(out ??= { ...value })[c.name] = next;
|
|
5509
|
+
}
|
|
5510
|
+
}
|
|
5511
|
+
return out ?? value;
|
|
5512
|
+
}
|
|
5513
|
+
return value;
|
|
5514
|
+
}
|
|
5515
|
+
function conformRecord(schema, obj) {
|
|
5516
|
+
let out = null;
|
|
5517
|
+
for (const f of schema.fields) {
|
|
5518
|
+
const v = obj[f.name];
|
|
5519
|
+
const next = conformValue(f.type, v, f.nullable, f.name);
|
|
5520
|
+
if (next !== v) {
|
|
5521
|
+
(out ??= { ...obj })[f.name] = next;
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
5524
|
+
return out ?? obj;
|
|
5525
|
+
}
|
|
5526
|
+
function conformColumns(schema, columns) {
|
|
5527
|
+
let out = null;
|
|
5528
|
+
for (const f of schema.fields) {
|
|
5529
|
+
const col = columns[f.name];
|
|
5530
|
+
const rows = col ?? [undefined];
|
|
5531
|
+
let changed = col === undefined;
|
|
5532
|
+
const next = rows.map((v) => {
|
|
5533
|
+
const c = conformValue(f.type, v, f.nullable, f.name);
|
|
5534
|
+
if (c !== v)
|
|
5535
|
+
changed = true;
|
|
5536
|
+
return c;
|
|
5537
|
+
});
|
|
5538
|
+
if (changed) {
|
|
5539
|
+
(out ??= { ...columns })[f.name] = next;
|
|
5540
|
+
}
|
|
5541
|
+
}
|
|
5542
|
+
return out ?? columns;
|
|
5543
|
+
}
|
|
5544
|
+
|
|
5545
|
+
// src/protocol/serializers/shared.ts
|
|
5384
5546
|
function toUint8Array2(val) {
|
|
5385
5547
|
if (typeof val === "string")
|
|
5386
5548
|
return new TextEncoder().encode(val);
|
|
@@ -5392,8 +5554,9 @@ function toUint8Array2(val) {
|
|
|
5392
5554
|
}
|
|
5393
5555
|
function buildSingleRowBatch(schema, values) {
|
|
5394
5556
|
const cols = {};
|
|
5557
|
+
const row = conformRecord(schema, values);
|
|
5395
5558
|
for (const f of schema.fields) {
|
|
5396
|
-
let val =
|
|
5559
|
+
let val = row[f.name];
|
|
5397
5560
|
if (isInt(f.type) && f.type.bitWidth === 64 && typeof val === "number") {
|
|
5398
5561
|
val = BigInt(val);
|
|
5399
5562
|
}
|
|
@@ -5433,7 +5596,7 @@ function serializeBindRequest(req) {
|
|
|
5433
5596
|
return buildSingleRowBatch(BIND_REQUEST_SCHEMA, {
|
|
5434
5597
|
function_name: req.function_name,
|
|
5435
5598
|
arguments: serializeArguments(req.arguments),
|
|
5436
|
-
function_type: req.function_type,
|
|
5599
|
+
function_type: req.function_type == null ? req.function_type : String(req.function_type).toUpperCase(),
|
|
5437
5600
|
input_schema: req.input_schema ? serializeSchema(req.input_schema) : null,
|
|
5438
5601
|
settings: req.settings ? serializeBatch(req.settings) : null,
|
|
5439
5602
|
secrets: req.secrets ? serializeBatch(req.secrets) : null,
|
|
@@ -7035,7 +7198,7 @@ function schemaPathDisplay(path) {
|
|
|
7035
7198
|
// src/codec/asd.ts
|
|
7036
7199
|
init_arrow();
|
|
7037
7200
|
function encodeASD(schema, obj) {
|
|
7038
|
-
return serializeBatch(batchFromRows([sortMapsForSchema(schema, obj)], schema));
|
|
7201
|
+
return serializeBatch(batchFromRows([sortMapsForSchema(schema, conformRecord(schema, obj))], schema));
|
|
7039
7202
|
}
|
|
7040
7203
|
function compareCodePoints(a, b) {
|
|
7041
7204
|
const n = Math.min(a.length, b.length);
|
|
@@ -7052,7 +7215,7 @@ function compareCodePoints(a, b) {
|
|
|
7052
7215
|
}
|
|
7053
7216
|
return a.length - b.length;
|
|
7054
7217
|
}
|
|
7055
|
-
function
|
|
7218
|
+
function mapPairs2(raw) {
|
|
7056
7219
|
if (Array.isArray(raw))
|
|
7057
7220
|
return raw.map((e) => Array.isArray(e) ? [e[0], e[1]] : [e?.key, e?.value]);
|
|
7058
7221
|
if (raw instanceof Map)
|
|
@@ -7087,7 +7250,7 @@ function sortMapsForType(type, value) {
|
|
|
7087
7250
|
if (isMap(type)) {
|
|
7088
7251
|
const entries = type.children[0].type;
|
|
7089
7252
|
const valueType = entries.children[1].type;
|
|
7090
|
-
return
|
|
7253
|
+
return mapPairs2(value).map(([k, v]) => [k, sortMapsForType(valueType, v)]).sort((x, y) => compareKeys(x[0], y[0]));
|
|
7091
7254
|
}
|
|
7092
7255
|
if (isList(type)) {
|
|
7093
7256
|
const child = type.children[0].type;
|
|
@@ -8252,12 +8415,12 @@ var encodeAttachCatalogInfo = (v) => encodeASD(AttachCatalogInfoSchema, {
|
|
|
8252
8415
|
secret_ref: v.secret_ref ?? ""
|
|
8253
8416
|
});
|
|
8254
8417
|
function encodeScanFunctionResult(functionName, argumentsBytes, requiredExtensions = [], schemaPath = null) {
|
|
8255
|
-
return serializeBatch(batchFromColumns({
|
|
8418
|
+
return serializeBatch(batchFromColumns(conformColumns(ScanFunctionResultSchema, {
|
|
8256
8419
|
function_name: [functionName],
|
|
8257
8420
|
arguments: [argumentsBytes],
|
|
8258
8421
|
required_extensions: [requiredExtensions],
|
|
8259
8422
|
schema_path: [schemaPath]
|
|
8260
|
-
}, ScanFunctionResultSchema));
|
|
8423
|
+
}), ScanFunctionResultSchema));
|
|
8261
8424
|
}
|
|
8262
8425
|
function decodeScanFunctionResult(inner) {
|
|
8263
8426
|
const argsBytes = inner.arguments;
|
|
@@ -8301,7 +8464,7 @@ function singleBranchResult(legacy) {
|
|
|
8301
8464
|
};
|
|
8302
8465
|
}
|
|
8303
8466
|
function encodeScanBranch(cols) {
|
|
8304
|
-
return serializeBatch(batchFromColumns({
|
|
8467
|
+
return serializeBatch(batchFromColumns(conformColumns(ScanBranchSchema, {
|
|
8305
8468
|
function_name: [cols.function_name],
|
|
8306
8469
|
arguments: [cols.arguments],
|
|
8307
8470
|
branch_filter: [cols.branch_filter ?? null],
|
|
@@ -8313,7 +8476,7 @@ function encodeScanBranch(cols) {
|
|
|
8313
8476
|
format_locations: [cols.format_locations ?? null],
|
|
8314
8477
|
format_options: [cols.format_options ?? null],
|
|
8315
8478
|
schema_path: [cols.schema_path ?? null]
|
|
8316
|
-
}, ScanBranchSchema));
|
|
8479
|
+
}), ScanBranchSchema));
|
|
8317
8480
|
}
|
|
8318
8481
|
function encodeFormatOptions(options) {
|
|
8319
8482
|
const fields = [];
|
|
@@ -8884,7 +9047,7 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
8884
9047
|
}
|
|
8885
9048
|
attach(name, options, dataVersionSpec, implementationVersion) {
|
|
8886
9049
|
if (!this.catalogs().includes(name)) {
|
|
8887
|
-
throw new
|
|
9050
|
+
throw new VgiError(`No worker handles catalog '${name}'`, "NOT_FOUND");
|
|
8888
9051
|
}
|
|
8889
9052
|
validateRequiredAttachOptions(name, this.attachOptionSpecs(name), options ?? {});
|
|
8890
9053
|
const attachOpaqueData = new Uint8Array(16);
|
|
@@ -9284,11 +9447,11 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
9284
9447
|
validateAtParams(atUnit, atValue);
|
|
9285
9448
|
const schema = this._descriptor.schemas.find((s) => schemaPathsEqual(schemaDescriptorPath(s), schemaPath));
|
|
9286
9449
|
if (!schema || !schema.tables) {
|
|
9287
|
-
throw new
|
|
9450
|
+
throw new VgiError(`Table '${name}' not found in schema ${schemaPathDisplay(schemaPath)}`, "NOT_FOUND");
|
|
9288
9451
|
}
|
|
9289
9452
|
const table = schema.tables.find((t) => t.name === name);
|
|
9290
9453
|
if (!table) {
|
|
9291
|
-
throw new
|
|
9454
|
+
throw new VgiError(`Table '${name}' not found in schema ${schemaPathDisplay(schemaPath)}`, "NOT_FOUND");
|
|
9292
9455
|
}
|
|
9293
9456
|
if (atUnit && !table.supportsTimeTravel) {
|
|
9294
9457
|
throw new Error(`Table ${schemaPathDisplay(schemaPath)}.${name} does not support time travel queries`);
|
|
@@ -9373,12 +9536,12 @@ function resolveIndexGroups(schema, groups) {
|
|
|
9373
9536
|
function serializeForeignKeys(fks, schemaPath) {
|
|
9374
9537
|
if (!fks || fks.length === 0)
|
|
9375
9538
|
return [];
|
|
9376
|
-
return fks.map((fk) => serializeBatch(batchFromColumns({
|
|
9539
|
+
return fks.map((fk) => serializeBatch(batchFromColumns(conformColumns(ForeignKeyInfoSchema, {
|
|
9377
9540
|
fk_columns: [fk.columns],
|
|
9378
9541
|
pk_columns: [fk.referencedColumns],
|
|
9379
9542
|
referenced_table: [fk.referencedTable],
|
|
9380
9543
|
referenced_schema_path: [fk.referencedSchemaPath ?? schemaPath ?? ["main"]]
|
|
9381
|
-
}, ForeignKeyInfoSchema)));
|
|
9544
|
+
}), ForeignKeyInfoSchema)));
|
|
9382
9545
|
}
|
|
9383
9546
|
function defaultToSql(value) {
|
|
9384
9547
|
if (value === null || value === undefined)
|
|
@@ -9518,7 +9681,7 @@ function serializeArgsBatch(args, argSpecSchema) {
|
|
|
9518
9681
|
}
|
|
9519
9682
|
function validateAtParams(atUnit, atValue) {
|
|
9520
9683
|
if (Boolean(atUnit) !== Boolean(atValue)) {
|
|
9521
|
-
throw new
|
|
9684
|
+
throw new VgiError("at_unit and at_value must both be provided or both be absent", "INVALID_ARGUMENT");
|
|
9522
9685
|
}
|
|
9523
9686
|
}
|
|
9524
9687
|
function inferScalarType2(val) {
|
|
@@ -10403,7 +10566,7 @@ class CompositeCatalogInterface extends CatalogInterface {
|
|
|
10403
10566
|
return result;
|
|
10404
10567
|
}
|
|
10405
10568
|
}
|
|
10406
|
-
throw new
|
|
10569
|
+
throw new VgiError(`No worker handles catalog '${name}'`, "NOT_FOUND");
|
|
10407
10570
|
}
|
|
10408
10571
|
async detach(attachOpaqueData) {
|
|
10409
10572
|
await this._route(attachOpaqueData).detach(attachOpaqueData);
|
|
@@ -10727,7 +10890,7 @@ class FunctionRegistry {
|
|
|
10727
10890
|
} else if (candidates && candidates.length > 0) {
|
|
10728
10891
|
const schemas = this.schemasFor(name);
|
|
10729
10892
|
if (schemas.length > 0) {
|
|
10730
|
-
throw new
|
|
10893
|
+
throw new VgiError(`Function '${name}' is not registered in schema ${schemaPathDisplay(schemaPath)}. ` + `It is available in: [${schemas.map(schemaPathDisplay).join(", ")}]`, "NOT_FOUND");
|
|
10731
10894
|
}
|
|
10732
10895
|
}
|
|
10733
10896
|
}
|
|
@@ -12315,7 +12478,8 @@ function normalizeRequestSchemaPaths(params) {
|
|
|
12315
12478
|
}
|
|
12316
12479
|
function wrapResult(values, innerSchema) {
|
|
12317
12480
|
const a = innerSchema;
|
|
12318
|
-
const
|
|
12481
|
+
const row = conformRecord(a, values);
|
|
12482
|
+
const batch = batchFromColumns(Object.fromEntries(a.fields.map((f) => [f.name, [row[f.name] ?? null]])), a);
|
|
12319
12483
|
return { result: serializeBatch(batch) };
|
|
12320
12484
|
}
|
|
12321
12485
|
function overloadContext(req, catalogInterface) {
|
|
@@ -13331,7 +13495,7 @@ import {
|
|
|
13331
13495
|
var ATTACH_TICKET_PREFIX = "vgia1.";
|
|
13332
13496
|
var ATTACH_TICKET_OPTION = RESERVED_ATTACH_OPTION;
|
|
13333
13497
|
var ATTACH_TICKETS_PROTOCOL_NAME = "vgi.attach_tickets.v1";
|
|
13334
|
-
var ATTACH_TICKETS_PROTOCOL_VERSION = "
|
|
13498
|
+
var ATTACH_TICKETS_PROTOCOL_VERSION = "2.0.0";
|
|
13335
13499
|
var TICKET_ENVELOPE_VERSION = 1;
|
|
13336
13500
|
var MAX_OPTIONS_BYTES = 16 * 1024;
|
|
13337
13501
|
var MAX_TICKET_CHARS = 32 * 1024;
|
|
@@ -13606,8 +13770,19 @@ var SEAL_ATTACH_REQUEST_SCHEMA = schema2([
|
|
|
13606
13770
|
]);
|
|
13607
13771
|
var ATTACH_TICKET_SCHEMA = schema2([
|
|
13608
13772
|
field2("ticket", utf82(), false),
|
|
13609
|
-
field2("expires_at",
|
|
13773
|
+
field2("expires_at", timestamp2(TimeUnit2.MICROSECOND, "UTC"), true)
|
|
13610
13774
|
]);
|
|
13775
|
+
function expiresAtMicros(value) {
|
|
13776
|
+
if (value === null)
|
|
13777
|
+
return null;
|
|
13778
|
+
const ms = value.getTime();
|
|
13779
|
+
if (!Number.isFinite(ms))
|
|
13780
|
+
throw new TypeError("AttachTicket.expires_at must be a valid Date or null");
|
|
13781
|
+
return BigInt(ms) * 1000n;
|
|
13782
|
+
}
|
|
13783
|
+
function encodeAttachTicket(ticket) {
|
|
13784
|
+
return serializeBatch(batchFromColumns({ ticket: [ticket.ticket], expires_at: [expiresAtMicros(ticket.expires_at)] }, ATTACH_TICKET_SCHEMA));
|
|
13785
|
+
}
|
|
13611
13786
|
function resolveTicketMaxTtl(grantKeys, env) {
|
|
13612
13787
|
if (grantKeys)
|
|
13613
13788
|
return Math.trunc(grantKeys.maxTtlSeconds);
|
|
@@ -13694,7 +13869,7 @@ async function sealAttach2(config, request, auth) {
|
|
|
13694
13869
|
} catch (e) {
|
|
13695
13870
|
throw new AttachTicketRequestError("seal_attach request is invalid", [["request", e.message]]);
|
|
13696
13871
|
}
|
|
13697
|
-
return { ticket: token, expires_at: expiresAt === 0 ?
|
|
13872
|
+
return { ticket: token, expires_at: expiresAt === 0 ? null : new Date(expiresAt * 1000) };
|
|
13698
13873
|
}
|
|
13699
13874
|
function buildAttachTicketsProtocol(config) {
|
|
13700
13875
|
const p = new Protocol2(ATTACH_TICKETS_PROTOCOL_NAME, { protocolVersion: ATTACH_TICKETS_PROTOCOL_VERSION });
|
|
@@ -13705,8 +13880,7 @@ function buildAttachTicketsProtocol(config) {
|
|
|
13705
13880
|
handler: async (params, ctx) => {
|
|
13706
13881
|
const request = unwrapRequest(params.request);
|
|
13707
13882
|
const sealed = await sealAttach2(config, request, ctx?.auth);
|
|
13708
|
-
|
|
13709
|
-
return { result: serializeBatch(batch) };
|
|
13883
|
+
return { result: encodeAttachTicket(sealed) };
|
|
13710
13884
|
}
|
|
13711
13885
|
});
|
|
13712
13886
|
return p;
|
|
@@ -14386,6 +14560,10 @@ function toAsyncIterator(input) {
|
|
|
14386
14560
|
}
|
|
14387
14561
|
|
|
14388
14562
|
// src/client/client.ts
|
|
14563
|
+
function onConflictName(onConflict) {
|
|
14564
|
+
return String(onConflict).toUpperCase();
|
|
14565
|
+
}
|
|
14566
|
+
|
|
14389
14567
|
class VgiClient {
|
|
14390
14568
|
rpc;
|
|
14391
14569
|
defaultAttachOpaqueData;
|
|
@@ -14841,7 +15019,7 @@ class VgiClient {
|
|
|
14841
15019
|
}
|
|
14842
15020
|
await this.rpc.call("catalog_create", {
|
|
14843
15021
|
name,
|
|
14844
|
-
on_conflict: onConflict,
|
|
15022
|
+
on_conflict: onConflictName(onConflict),
|
|
14845
15023
|
options: wireOptions
|
|
14846
15024
|
});
|
|
14847
15025
|
}
|
|
@@ -14909,7 +15087,7 @@ class VgiClient {
|
|
|
14909
15087
|
await this.rpc.call("catalog_schema_create", {
|
|
14910
15088
|
attach_opaque_data: attachOpaqueData,
|
|
14911
15089
|
path: normalizeSchemaPath(path),
|
|
14912
|
-
on_conflict: opts?.onConflict ?? "error",
|
|
15090
|
+
on_conflict: onConflictName(opts?.onConflict ?? "error"),
|
|
14913
15091
|
comment: opts?.comment ?? null,
|
|
14914
15092
|
tags: tagsMap,
|
|
14915
15093
|
transaction_opaque_data: opts?.transactionOpaqueData ?? null
|
|
@@ -14988,7 +15166,7 @@ class VgiClient {
|
|
|
14988
15166
|
schema_path: normalizeSchemaPath(schemaPath),
|
|
14989
15167
|
name,
|
|
14990
15168
|
columns,
|
|
14991
|
-
on_conflict: onConflict,
|
|
15169
|
+
on_conflict: onConflictName(onConflict),
|
|
14992
15170
|
not_null_constraints: notNullConstraints ?? null,
|
|
14993
15171
|
unique_constraints: uniqueConstraints ?? null,
|
|
14994
15172
|
check_constraints: checkConstraints ?? null,
|
|
@@ -15142,7 +15320,7 @@ class VgiClient {
|
|
|
15142
15320
|
schema_path: normalizeSchemaPath(schemaPath),
|
|
15143
15321
|
name,
|
|
15144
15322
|
definition,
|
|
15145
|
-
on_conflict: onConflict,
|
|
15323
|
+
on_conflict: onConflictName(onConflict),
|
|
15146
15324
|
transaction_opaque_data: transactionOpaqueData ?? null
|
|
15147
15325
|
});
|
|
15148
15326
|
}
|
|
@@ -15209,7 +15387,7 @@ class VgiClient {
|
|
|
15209
15387
|
macro_type: [macroType],
|
|
15210
15388
|
parameters: [parameters],
|
|
15211
15389
|
definition: [definition],
|
|
15212
|
-
on_conflict: [onConflict],
|
|
15390
|
+
on_conflict: [onConflictName(onConflict)],
|
|
15213
15391
|
parameter_default_values: [parameterDefaultValues ?? null],
|
|
15214
15392
|
arguments_schema: [argumentsSchema ?? null],
|
|
15215
15393
|
transaction_opaque_data: [transactionOpaqueData ?? null]
|
|
@@ -15286,7 +15464,7 @@ function validatedHostedProtocols(hosting, primary) {
|
|
|
15286
15464
|
}
|
|
15287
15465
|
const name = p.name;
|
|
15288
15466
|
if (name.startsWith(RESERVED_PREFIX)) {
|
|
15289
|
-
throw new Error(`${owner} entry ${index} is named '${name}', which claims the reserved '${RESERVED_PREFIX}' prefix. ` + "Framework protocols are not supplied through this hook: reflection is hosted automatically, and " + "vgi_rpc.Identity.
|
|
15467
|
+
throw new Error(`${owner} entry ${index} is named '${name}', which claims the reserved '${RESERVED_PREFIX}' prefix. ` + "Framework protocols are not supplied through this hook: reflection is hosted automatically, and " + "vgi_rpc.Identity.v2 is enabled by supplying resolveToken and/or mintGrant.");
|
|
15290
15468
|
}
|
|
15291
15469
|
if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name)) {
|
|
15292
15470
|
throw new Error(`${owner} entry ${index}: protocol name '${name}' is not an identifier, optionally dot-qualified ` + "(e.g. 'acme.Reports.v1').");
|
|
@@ -15336,7 +15514,7 @@ function resolveIntrospectPrincipals(explicit, env) {
|
|
|
15336
15514
|
principals = raw.split(",").map((p) => p.trim()).filter((p) => p !== "");
|
|
15337
15515
|
}
|
|
15338
15516
|
if (principals.length === 0) {
|
|
15339
|
-
throw new Error("This worker supplies resolveToken, which hosts the vgi_rpc.Identity.
|
|
15517
|
+
throw new Error("This worker supplies resolveToken, which hosts the vgi_rpc.Identity.v2 protocol, but no " + `introspector allowlist was configured. Set ${INTROSPECT_PRINCIPALS_ENV} (comma-separated) or pass ` + `introspectPrincipals.
|
|
15340
15518
|
|
|
15341
15519
|
` + "There is no permissive default on purpose: introspection is a separate capability from " + "authentication, and allowing every authenticated caller lets any user resolve any other user's " + "credential to its owner. Remove resolveToken to leave the protocol unhosted entirely.");
|
|
15342
15520
|
}
|
|
@@ -15719,6 +15897,7 @@ export {
|
|
|
15719
15897
|
durationNanos,
|
|
15720
15898
|
durationSeconds,
|
|
15721
15899
|
emptyBatch,
|
|
15900
|
+
encodeAttachTicket,
|
|
15722
15901
|
encodeCatalogInfo,
|
|
15723
15902
|
encodeCopyFromFormatInfo,
|
|
15724
15903
|
encodeFormatOptions,
|
|
@@ -15832,4 +16011,4 @@ export {
|
|
|
15832
16011
|
utf82 as utf8
|
|
15833
16012
|
};
|
|
15834
16013
|
|
|
15835
|
-
//# debugId=
|
|
16014
|
+
//# debugId=2C6F34EB0944BDD764756E2164756E21
|