@query-farm/vgi 0.37.0 → 0.38.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 +74 -0
- package/dist/catalog/attach-option.d.ts +11 -8
- package/dist/catalog/composite.d.ts +23 -1
- package/dist/catalog/contents-digest.d.ts +25 -0
- package/dist/catalog/interface.d.ts +107 -2
- package/dist/catalog/read-only.d.ts +45 -1
- package/dist/client/client.d.ts +19 -1
- package/dist/client-entry.js +141 -4
- package/dist/client-entry.js.map +10 -9
- package/dist/codec/asd.d.ts +8 -0
- package/dist/generated/vgi-client.d.ts +19 -0
- package/dist/generated/vgi-protocol-schemas.d.ts +3 -0
- package/dist/generated/vgi-protocol-types.d.ts +26 -0
- package/dist/http/fetch.d.ts +2 -1
- package/dist/index.core.d.ts +5 -2
- package/dist/index.js +574 -36
- package/dist/index.js.map +21 -17
- package/dist/protocol/handlers/catalog/contents.d.ts +27 -0
- package/dist/rpc-server.d.ts +97 -0
- package/dist/serve-entry.d.ts +2 -1
- package/dist/serve-entry.js +405 -25
- package/dist/serve-entry.js.map +18 -14
- package/dist/worker-cf-entry.d.ts +3 -0
- package/dist/worker-cf-entry.js +528 -31
- package/dist/worker-cf-entry.js.map +21 -17
- package/dist/worker.d.ts +9 -1
- package/package.json +3 -3
- package/src/catalog/attach-option.ts +11 -8
- package/src/catalog/composite.ts +81 -0
- package/src/catalog/contents-digest.ts +78 -0
- package/src/catalog/interface.ts +167 -5
- package/src/catalog/read-only.ts +68 -6
- package/src/client/client.ts +53 -0
- package/src/codec/asd.ts +96 -1
- package/src/generated/vgi-client.ts +22 -1
- package/src/generated/vgi-protocol-schemas.ts +30 -1
- package/src/generated/vgi-protocol-types.ts +126 -0
- package/src/http/fetch.ts +10 -2
- package/src/index.core.ts +21 -2
- package/src/protocol/dispatch.ts +1 -1
- package/src/protocol/handlers/catalog/admin.ts +35 -26
- package/src/protocol/handlers/catalog/contents.ts +162 -0
- package/src/protocol/handlers/catalog/macro.ts +2 -1
- package/src/protocol/handlers/catalog/shared.ts +12 -1
- package/src/rpc-server.ts +273 -0
- package/src/serve-entry.ts +7 -1
- package/src/worker-cf-entry.ts +8 -0
- package/src/worker.ts +24 -6
package/dist/index.js
CHANGED
|
@@ -7035,7 +7035,84 @@ function schemaPathDisplay(path) {
|
|
|
7035
7035
|
// src/codec/asd.ts
|
|
7036
7036
|
init_arrow();
|
|
7037
7037
|
function encodeASD(schema, obj) {
|
|
7038
|
-
return serializeBatch(batchFromRows([obj], schema));
|
|
7038
|
+
return serializeBatch(batchFromRows([sortMapsForSchema(schema, obj)], schema));
|
|
7039
|
+
}
|
|
7040
|
+
function compareCodePoints(a, b) {
|
|
7041
|
+
const n = Math.min(a.length, b.length);
|
|
7042
|
+
for (let i = 0;i < n; i++) {
|
|
7043
|
+
const x = a.charCodeAt(i);
|
|
7044
|
+
const y = b.charCodeAt(i);
|
|
7045
|
+
if (x === y)
|
|
7046
|
+
continue;
|
|
7047
|
+
const xs = x >= 55296 && x <= 57343;
|
|
7048
|
+
const ys = y >= 55296 && y <= 57343;
|
|
7049
|
+
if (xs !== ys)
|
|
7050
|
+
return xs ? 1 : -1;
|
|
7051
|
+
return x - y;
|
|
7052
|
+
}
|
|
7053
|
+
return a.length - b.length;
|
|
7054
|
+
}
|
|
7055
|
+
function mapPairs(raw) {
|
|
7056
|
+
if (Array.isArray(raw))
|
|
7057
|
+
return raw.map((e) => Array.isArray(e) ? [e[0], e[1]] : [e?.key, e?.value]);
|
|
7058
|
+
if (raw instanceof Map)
|
|
7059
|
+
return Array.from(raw.entries());
|
|
7060
|
+
if (typeof raw[Symbol.iterator] === "function")
|
|
7061
|
+
return Array.from(raw);
|
|
7062
|
+
return Object.entries(raw);
|
|
7063
|
+
}
|
|
7064
|
+
function compareKeys(a, b) {
|
|
7065
|
+
if (typeof a === "string" && typeof b === "string")
|
|
7066
|
+
return compareCodePoints(a, b);
|
|
7067
|
+
if ((typeof a === "number" || typeof a === "bigint") && (typeof b === "number" || typeof b === "bigint")) {
|
|
7068
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
7069
|
+
}
|
|
7070
|
+
return compareCodePoints(String(a), String(b));
|
|
7071
|
+
}
|
|
7072
|
+
var HAS_MAP = new WeakMap;
|
|
7073
|
+
function typeHasMap(type) {
|
|
7074
|
+
const cached = HAS_MAP.get(type);
|
|
7075
|
+
if (cached !== undefined)
|
|
7076
|
+
return cached;
|
|
7077
|
+
let has = isMap(type);
|
|
7078
|
+
if (!has && (isList(type) || isStruct(type))) {
|
|
7079
|
+
has = type.children.some((c) => typeHasMap(c.type));
|
|
7080
|
+
}
|
|
7081
|
+
HAS_MAP.set(type, has);
|
|
7082
|
+
return has;
|
|
7083
|
+
}
|
|
7084
|
+
function sortMapsForType(type, value) {
|
|
7085
|
+
if (value == null || !typeHasMap(type))
|
|
7086
|
+
return value;
|
|
7087
|
+
if (isMap(type)) {
|
|
7088
|
+
const entries = type.children[0].type;
|
|
7089
|
+
const valueType = entries.children[1].type;
|
|
7090
|
+
return mapPairs(value).map(([k, v]) => [k, sortMapsForType(valueType, v)]).sort((x, y) => compareKeys(x[0], y[0]));
|
|
7091
|
+
}
|
|
7092
|
+
if (isList(type)) {
|
|
7093
|
+
const child = type.children[0].type;
|
|
7094
|
+
return Array.from(value, (v) => sortMapsForType(child, v));
|
|
7095
|
+
}
|
|
7096
|
+
if (isStruct(type)) {
|
|
7097
|
+
const out = { ...value };
|
|
7098
|
+
for (const cf of type.children)
|
|
7099
|
+
out[cf.name] = sortMapsForType(cf.type, value[cf.name]);
|
|
7100
|
+
return out;
|
|
7101
|
+
}
|
|
7102
|
+
return value;
|
|
7103
|
+
}
|
|
7104
|
+
function sortMapsForSchema(schema, obj) {
|
|
7105
|
+
let out = null;
|
|
7106
|
+
for (const f of schema.fields) {
|
|
7107
|
+
if (!typeHasMap(f.type))
|
|
7108
|
+
continue;
|
|
7109
|
+
const v = obj[f.name];
|
|
7110
|
+
if (v == null)
|
|
7111
|
+
continue;
|
|
7112
|
+
out ??= { ...obj };
|
|
7113
|
+
out[f.name] = sortMapsForType(f.type, v);
|
|
7114
|
+
}
|
|
7115
|
+
return out ?? obj;
|
|
7039
7116
|
}
|
|
7040
7117
|
function decodeASD(schema, bytes) {
|
|
7041
7118
|
const batch = deserializeBatch(bytes);
|
|
@@ -7292,6 +7369,18 @@ var ForeignKeyInfoSchema = schema2([
|
|
|
7292
7369
|
field2("referenced_table", utf82(), false),
|
|
7293
7370
|
field2("referenced_schema_path", list2(field2("item", utf82(), true)), false)
|
|
7294
7371
|
]);
|
|
7372
|
+
var SchemaContentsSchema = schema2([
|
|
7373
|
+
field2("path", list2(field2("item", utf82(), true)), false),
|
|
7374
|
+
field2("schema", binary2(), false),
|
|
7375
|
+
field2("tables", list2(field2("item", binary2(), true)), false),
|
|
7376
|
+
field2("views", list2(field2("item", binary2(), true)), false),
|
|
7377
|
+
field2("scalar_functions", list2(field2("item", binary2(), true)), false),
|
|
7378
|
+
field2("aggregate_functions", list2(field2("item", binary2(), true)), false),
|
|
7379
|
+
field2("table_functions", list2(field2("item", binary2(), true)), false),
|
|
7380
|
+
field2("scalar_macros", list2(field2("item", binary2(), true)), false),
|
|
7381
|
+
field2("table_macros", list2(field2("item", binary2(), true)), false),
|
|
7382
|
+
field2("indexes", list2(field2("item", binary2(), true)), false)
|
|
7383
|
+
]);
|
|
7295
7384
|
var AggregateBindRequestSchema = schema2([
|
|
7296
7385
|
field2("function_name", utf82(), false),
|
|
7297
7386
|
field2("arguments", binary2(), false),
|
|
@@ -7614,11 +7703,18 @@ var CatalogAttachResultSchema = schema2([
|
|
|
7614
7703
|
field2("global_functions", list2(field2("item", binary2(), true)), false),
|
|
7615
7704
|
field2("global_function_prefix", utf82(), false),
|
|
7616
7705
|
field2("resolved_data_version", utf82(), true),
|
|
7617
|
-
field2("resolved_implementation_version", utf82(), true)
|
|
7706
|
+
field2("resolved_implementation_version", utf82(), true),
|
|
7707
|
+
field2("supports_catalog_contents", bool2(), false)
|
|
7618
7708
|
]);
|
|
7619
7709
|
var CatalogCatalogsResultSchema = schema2([
|
|
7620
7710
|
field2("items", list2(field2("item", binary2(), true)), false)
|
|
7621
7711
|
]);
|
|
7712
|
+
var CatalogContentsResultSchema = schema2([
|
|
7713
|
+
field2("catalog_version", int642(), false),
|
|
7714
|
+
field2("etag", utf82(), true),
|
|
7715
|
+
field2("not_modified", bool2(), false),
|
|
7716
|
+
field2("schemas", list2(field2("item", struct2([field2("path", list2(field2("item", utf82(), true)), false), field2("schema", binary2(), false), field2("tables", list2(field2("item", binary2(), true)), false), field2("views", list2(field2("item", binary2(), true)), false), field2("scalar_functions", list2(field2("item", binary2(), true)), false), field2("aggregate_functions", list2(field2("item", binary2(), true)), false), field2("table_functions", list2(field2("item", binary2(), true)), false), field2("scalar_macros", list2(field2("item", binary2(), true)), false), field2("table_macros", list2(field2("item", binary2(), true)), false), field2("indexes", list2(field2("item", binary2(), true)), false)]), true)), false)
|
|
7717
|
+
]);
|
|
7622
7718
|
var CatalogCopyFromFormatsResultSchema = schema2([
|
|
7623
7719
|
field2("items", list2(field2("item", binary2(), true)), false)
|
|
7624
7720
|
]);
|
|
@@ -7737,6 +7833,10 @@ var CatalogAttachParamsSchema = schema2([
|
|
|
7737
7833
|
field2("request", binary2(), false)
|
|
7738
7834
|
]);
|
|
7739
7835
|
var CatalogCatalogsParamsSchema = schema2([]);
|
|
7836
|
+
var CatalogContentsParamsSchema = schema2([
|
|
7837
|
+
field2("attach_opaque_data", binary2(), false),
|
|
7838
|
+
field2("if_none_match", utf82(), true)
|
|
7839
|
+
]);
|
|
7740
7840
|
var CatalogCopyFromFormatsParamsSchema = schema2([
|
|
7741
7841
|
field2("attach_opaque_data", binary2(), false),
|
|
7742
7842
|
field2("transaction_opaque_data", binary2(), true)
|
|
@@ -8067,12 +8167,59 @@ var TableFunctionStatisticsParamsSchema = schema2([
|
|
|
8067
8167
|
field2("request", binary2(), false)
|
|
8068
8168
|
]);
|
|
8069
8169
|
|
|
8170
|
+
// src/generated/vgi-protocol-types.ts
|
|
8171
|
+
function buildCatalogAttachResult(init) {
|
|
8172
|
+
return {
|
|
8173
|
+
attach_opaque_data: init.attach_opaque_data,
|
|
8174
|
+
supports_transactions: init.supports_transactions,
|
|
8175
|
+
supports_time_travel: init.supports_time_travel,
|
|
8176
|
+
catalog_version_frozen: init.catalog_version_frozen,
|
|
8177
|
+
catalog_version: init.catalog_version,
|
|
8178
|
+
attach_opaque_data_required: init.attach_opaque_data_required ?? true,
|
|
8179
|
+
default_schema: init.default_schema ?? "main",
|
|
8180
|
+
settings: init.settings ?? [],
|
|
8181
|
+
secret_types: init.secret_types ?? [],
|
|
8182
|
+
attach_catalogs: init.attach_catalogs ?? [],
|
|
8183
|
+
comment: init.comment ?? null,
|
|
8184
|
+
tags: init.tags ?? {},
|
|
8185
|
+
supports_column_statistics: init.supports_column_statistics ?? false,
|
|
8186
|
+
global_functions: init.global_functions ?? [],
|
|
8187
|
+
global_function_prefix: init.global_function_prefix ?? "",
|
|
8188
|
+
resolved_data_version: init.resolved_data_version ?? null,
|
|
8189
|
+
resolved_implementation_version: init.resolved_implementation_version ?? null,
|
|
8190
|
+
supports_catalog_contents: init.supports_catalog_contents ?? false
|
|
8191
|
+
};
|
|
8192
|
+
}
|
|
8193
|
+
function buildSchemaContents(init) {
|
|
8194
|
+
return {
|
|
8195
|
+
path: init.path,
|
|
8196
|
+
schema: init.schema,
|
|
8197
|
+
tables: init.tables ?? [],
|
|
8198
|
+
views: init.views ?? [],
|
|
8199
|
+
scalar_functions: init.scalar_functions ?? [],
|
|
8200
|
+
aggregate_functions: init.aggregate_functions ?? [],
|
|
8201
|
+
table_functions: init.table_functions ?? [],
|
|
8202
|
+
scalar_macros: init.scalar_macros ?? [],
|
|
8203
|
+
table_macros: init.table_macros ?? [],
|
|
8204
|
+
indexes: init.indexes ?? []
|
|
8205
|
+
};
|
|
8206
|
+
}
|
|
8207
|
+
function buildCatalogContentsResponse(init) {
|
|
8208
|
+
return {
|
|
8209
|
+
catalog_version: init.catalog_version,
|
|
8210
|
+
etag: init.etag ?? null,
|
|
8211
|
+
not_modified: init.not_modified ?? false,
|
|
8212
|
+
schemas: init.schemas ?? []
|
|
8213
|
+
};
|
|
8214
|
+
}
|
|
8215
|
+
var decodeCatalogContentsResponse = (b) => decodeASD(CatalogContentsResultSchema, b);
|
|
8070
8216
|
// src/generated/vgi-client.ts
|
|
8071
8217
|
var encodeCatalogInfo = (v) => encodeASD(CatalogInfoSchema, v);
|
|
8072
8218
|
var decodeCatalogInfo = (b) => decodeASD(CatalogInfoSchema, b);
|
|
8073
8219
|
var encodeFunctionInfo = (v) => encodeASD(FunctionInfoSchema, v);
|
|
8074
8220
|
var decodeFunctionInfo = (b) => decodeASD(FunctionInfoSchema, b);
|
|
8075
8221
|
var encodeIndexInfo = (v) => encodeASD(IndexInfoSchema, v);
|
|
8222
|
+
var decodeIndexInfo = (b) => decodeASD(IndexInfoSchema, b);
|
|
8076
8223
|
var encodeMacroInfo = (v) => encodeASD(MacroInfoSchema, v);
|
|
8077
8224
|
var decodeMacroInfo = (b) => decodeASD(MacroInfoSchema, b);
|
|
8078
8225
|
var encodeSchemaInfo = (v) => encodeASD(SchemaInfoSchema, v);
|
|
@@ -8215,6 +8362,9 @@ function isPromise(v) {
|
|
|
8215
8362
|
}
|
|
8216
8363
|
|
|
8217
8364
|
class CatalogInterface {
|
|
8365
|
+
catalogContentsEtag = null;
|
|
8366
|
+
catalogContentsAttachIndependent = false;
|
|
8367
|
+
catalogVersionFrozen = false;
|
|
8218
8368
|
catalogNameForAttach(_attachOpaqueData) {
|
|
8219
8369
|
const names = this.catalogs();
|
|
8220
8370
|
return names.length === 1 ? names[0] : null;
|
|
@@ -8332,6 +8482,42 @@ class CatalogInterface {
|
|
|
8332
8482
|
copyFromFormats(attachOpaqueData, transactionOpaqueData) {
|
|
8333
8483
|
return [];
|
|
8334
8484
|
}
|
|
8485
|
+
async catalogContents(attachOpaqueData, _ifNoneMatch) {
|
|
8486
|
+
const schemas = await this.schemas(attachOpaqueData, undefined);
|
|
8487
|
+
const contents = await Promise.all(schemas.map(async (schema) => {
|
|
8488
|
+
const counts = schema.estimated_object_count ?? {};
|
|
8489
|
+
const path = schema.path;
|
|
8490
|
+
const kind = async (countKey, list) => (counts[countKey] ?? 1) === 0 ? [] : [...await list()];
|
|
8491
|
+
const [tables, views, scalarFunctions, aggregateFunctions, tableFunctions, scalarMacros, tableMacros, indexes] = await Promise.all([
|
|
8492
|
+
kind("table", () => this.schemaContentsTables(attachOpaqueData, path)),
|
|
8493
|
+
kind("view", () => this.schemaContentsViews(attachOpaqueData, path)),
|
|
8494
|
+
kind("scalar_function", () => this.schemaContentsFunctions(attachOpaqueData, path, "scalar_function")),
|
|
8495
|
+
kind("aggregate_function", () => this.schemaContentsFunctions(attachOpaqueData, path, "aggregate_function")),
|
|
8496
|
+
kind("table_function", () => this.schemaContentsFunctions(attachOpaqueData, path, "table_function")),
|
|
8497
|
+
kind("macro", () => this.schemaContentsMacros(attachOpaqueData, path, "scalar_macro")),
|
|
8498
|
+
kind("macro", () => this.schemaContentsMacros(attachOpaqueData, path, "table_macro")),
|
|
8499
|
+
kind("index", () => this.schemaContentsIndexes(attachOpaqueData, path))
|
|
8500
|
+
]);
|
|
8501
|
+
return {
|
|
8502
|
+
schema,
|
|
8503
|
+
tables,
|
|
8504
|
+
views,
|
|
8505
|
+
scalar_functions: scalarFunctions,
|
|
8506
|
+
aggregate_functions: aggregateFunctions,
|
|
8507
|
+
table_functions: tableFunctions,
|
|
8508
|
+
scalar_macros: scalarMacros,
|
|
8509
|
+
table_macros: tableMacros,
|
|
8510
|
+
indexes
|
|
8511
|
+
};
|
|
8512
|
+
}));
|
|
8513
|
+
return { schemas: contents };
|
|
8514
|
+
}
|
|
8515
|
+
catalogContentsCacheable() {
|
|
8516
|
+
return this.catalogContentsAttachIndependent && this.catalogVersionFrozen;
|
|
8517
|
+
}
|
|
8518
|
+
catalogContentsOwner(_attachOpaqueData) {
|
|
8519
|
+
return this;
|
|
8520
|
+
}
|
|
8335
8521
|
transactionBegin(attachOpaqueData) {
|
|
8336
8522
|
return null;
|
|
8337
8523
|
}
|
|
@@ -8594,17 +8780,25 @@ function encodeFunctionInfoOnce(info) {
|
|
|
8594
8780
|
}
|
|
8595
8781
|
|
|
8596
8782
|
// src/catalog/read-only.ts
|
|
8783
|
+
var READ_ONLY_ITEM_ATTACH_ID = new TextEncoder().encode("readonly-catalog-");
|
|
8784
|
+
|
|
8597
8785
|
class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
8786
|
+
supportsCatalogContents = true;
|
|
8787
|
+
catalogVersionFrozen = true;
|
|
8788
|
+
perAttachItemIds = false;
|
|
8789
|
+
catalogContentsAttachIndependent = true;
|
|
8598
8790
|
_descriptor;
|
|
8599
8791
|
_registry;
|
|
8600
8792
|
_attachments = new Map;
|
|
8601
8793
|
_version = 1;
|
|
8602
8794
|
_functionListings = new Map;
|
|
8603
8795
|
_functionInfos = new Map;
|
|
8604
|
-
constructor(descriptor, registry) {
|
|
8796
|
+
constructor(descriptor, registry, options = {}) {
|
|
8605
8797
|
super();
|
|
8606
8798
|
this._descriptor = descriptor;
|
|
8607
8799
|
this._registry = registry;
|
|
8800
|
+
if (options.perAttachItemIds)
|
|
8801
|
+
this.perAttachItemIds = true;
|
|
8608
8802
|
for (const sch of descriptor.schemas ?? []) {
|
|
8609
8803
|
for (const fn of sch.functions ?? [])
|
|
8610
8804
|
registry.registerInSchema(fn, schemaDescriptorPath(sch), descriptor.name);
|
|
@@ -8652,7 +8846,7 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
8652
8846
|
const secretTypes = (this._descriptor.secretTypes ?? []).map((s) => serializeSecretType(s));
|
|
8653
8847
|
const attachCatalogs = (this._descriptor.attachCatalogs ?? []).map((c) => encodeAttachCatalogInfo(c));
|
|
8654
8848
|
const hasTimeTravel = this._descriptor.schemas.some((s) => s.tables?.some((t) => t.supportsTimeTravel) ?? false);
|
|
8655
|
-
return {
|
|
8849
|
+
return buildCatalogAttachResult({
|
|
8656
8850
|
attach_opaque_data: attachOpaqueData,
|
|
8657
8851
|
supports_transactions: false,
|
|
8658
8852
|
supports_time_travel: hasTimeTravel,
|
|
@@ -8669,8 +8863,9 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
8669
8863
|
global_functions: this._globalFunctionInfos().map(encodeFunctionInfoOnce),
|
|
8670
8864
|
global_function_prefix: this._descriptor.globalFunctionPrefix ?? "",
|
|
8671
8865
|
resolved_data_version: null,
|
|
8672
|
-
resolved_implementation_version: null
|
|
8673
|
-
|
|
8866
|
+
resolved_implementation_version: null,
|
|
8867
|
+
supports_catalog_contents: this.supportsCatalogContents
|
|
8868
|
+
});
|
|
8674
8869
|
}
|
|
8675
8870
|
detach(attachOpaqueData) {
|
|
8676
8871
|
for (const [name, id] of this._attachments) {
|
|
@@ -8683,9 +8878,15 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
8683
8878
|
version(attachOpaqueData, transactionOpaqueData) {
|
|
8684
8879
|
return this._version;
|
|
8685
8880
|
}
|
|
8881
|
+
itemAttachId(attachOpaqueData) {
|
|
8882
|
+
return this.perAttachItemIds ? attachOpaqueData : READ_ONLY_ITEM_ATTACH_ID;
|
|
8883
|
+
}
|
|
8884
|
+
catalogContentsCacheable() {
|
|
8885
|
+
return super.catalogContentsCacheable() && !this.perAttachItemIds;
|
|
8886
|
+
}
|
|
8686
8887
|
schemas(attachOpaqueData, transactionOpaqueData) {
|
|
8687
8888
|
return this._descriptor.schemas.map((s) => ({
|
|
8688
|
-
attach_opaque_data: attachOpaqueData,
|
|
8889
|
+
attach_opaque_data: this.itemAttachId(attachOpaqueData),
|
|
8689
8890
|
path: schemaDescriptorPath(s),
|
|
8690
8891
|
comment: s.comment ?? null,
|
|
8691
8892
|
tags: s.tags ?? {},
|
|
@@ -8717,7 +8918,7 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
8717
8918
|
if (!desc)
|
|
8718
8919
|
return null;
|
|
8719
8920
|
return {
|
|
8720
|
-
attach_opaque_data: attachOpaqueData,
|
|
8921
|
+
attach_opaque_data: this.itemAttachId(attachOpaqueData),
|
|
8721
8922
|
path: schemaDescriptorPath(desc),
|
|
8722
8923
|
comment: desc.comment ?? null,
|
|
8723
8924
|
tags: desc.tags ?? {},
|
|
@@ -8743,7 +8944,7 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
8743
8944
|
input_schema: null,
|
|
8744
8945
|
settings: null,
|
|
8745
8946
|
secrets: null,
|
|
8746
|
-
attach_opaque_data: attachOpaqueData,
|
|
8947
|
+
attach_opaque_data: this.itemAttachId(attachOpaqueData),
|
|
8747
8948
|
transaction_opaque_data: null,
|
|
8748
8949
|
resolved_secrets_provided: false
|
|
8749
8950
|
};
|
|
@@ -9417,6 +9618,72 @@ class CompositeCatalogInterface extends CatalogInterface {
|
|
|
9417
9618
|
async macroGet(attachOpaqueData, schemaPath, name, transactionOpaqueData) {
|
|
9418
9619
|
return await this._route(attachOpaqueData).macroGet(attachOpaqueData, schemaPath, name, transactionOpaqueData);
|
|
9419
9620
|
}
|
|
9621
|
+
async schemaCreate(...args) {
|
|
9622
|
+
await this._route(args[0]).schemaCreate(...args);
|
|
9623
|
+
}
|
|
9624
|
+
async schemaDrop(...args) {
|
|
9625
|
+
await this._route(args[0]).schemaDrop(...args);
|
|
9626
|
+
}
|
|
9627
|
+
async tableCreate(...args) {
|
|
9628
|
+
await this._route(args[0]).tableCreate(...args);
|
|
9629
|
+
}
|
|
9630
|
+
async tableDrop(...args) {
|
|
9631
|
+
await this._route(args[0]).tableDrop(...args);
|
|
9632
|
+
}
|
|
9633
|
+
async tableCommentSet(...args) {
|
|
9634
|
+
await this._route(args[0]).tableCommentSet(...args);
|
|
9635
|
+
}
|
|
9636
|
+
async tableRename(...args) {
|
|
9637
|
+
await this._route(args[0]).tableRename(...args);
|
|
9638
|
+
}
|
|
9639
|
+
async tableColumnAdd(...args) {
|
|
9640
|
+
await this._route(args[0]).tableColumnAdd(...args);
|
|
9641
|
+
}
|
|
9642
|
+
async tableColumnDrop(...args) {
|
|
9643
|
+
await this._route(args[0]).tableColumnDrop(...args);
|
|
9644
|
+
}
|
|
9645
|
+
async tableColumnRename(...args) {
|
|
9646
|
+
await this._route(args[0]).tableColumnRename(...args);
|
|
9647
|
+
}
|
|
9648
|
+
async tableColumnDefaultSet(...args) {
|
|
9649
|
+
await this._route(args[0]).tableColumnDefaultSet(...args);
|
|
9650
|
+
}
|
|
9651
|
+
async tableColumnDefaultDrop(...args) {
|
|
9652
|
+
await this._route(args[0]).tableColumnDefaultDrop(...args);
|
|
9653
|
+
}
|
|
9654
|
+
async tableColumnTypeChange(...args) {
|
|
9655
|
+
await this._route(args[0]).tableColumnTypeChange(...args);
|
|
9656
|
+
}
|
|
9657
|
+
async tableNotNullSet(...args) {
|
|
9658
|
+
await this._route(args[0]).tableNotNullSet(...args);
|
|
9659
|
+
}
|
|
9660
|
+
async tableNotNullDrop(...args) {
|
|
9661
|
+
await this._route(args[0]).tableNotNullDrop(...args);
|
|
9662
|
+
}
|
|
9663
|
+
async viewCreate(...args) {
|
|
9664
|
+
await this._route(args[0]).viewCreate(...args);
|
|
9665
|
+
}
|
|
9666
|
+
async viewDrop(...args) {
|
|
9667
|
+
await this._route(args[0]).viewDrop(...args);
|
|
9668
|
+
}
|
|
9669
|
+
async viewRename(...args) {
|
|
9670
|
+
await this._route(args[0]).viewRename(...args);
|
|
9671
|
+
}
|
|
9672
|
+
async viewCommentSet(...args) {
|
|
9673
|
+
await this._route(args[0]).viewCommentSet(...args);
|
|
9674
|
+
}
|
|
9675
|
+
async macroCreate(...args) {
|
|
9676
|
+
await this._route(args[0]).macroCreate(...args);
|
|
9677
|
+
}
|
|
9678
|
+
async macroDrop(...args) {
|
|
9679
|
+
await this._route(args[0]).macroDrop(...args);
|
|
9680
|
+
}
|
|
9681
|
+
async catalogContents(attachOpaqueData, ifNoneMatch) {
|
|
9682
|
+
return await this._route(attachOpaqueData).catalogContents(attachOpaqueData, ifNoneMatch);
|
|
9683
|
+
}
|
|
9684
|
+
catalogContentsOwner(attachOpaqueData) {
|
|
9685
|
+
return this._route(attachOpaqueData).catalogContentsOwner(attachOpaqueData);
|
|
9686
|
+
}
|
|
9420
9687
|
async copyFromFormats(attachOpaqueData, transactionOpaqueData) {
|
|
9421
9688
|
return await this._route(attachOpaqueData).copyFromFormats(attachOpaqueData, transactionOpaqueData);
|
|
9422
9689
|
}
|
|
@@ -10819,6 +11086,9 @@ function catalogUnary(protocol, signingKey, name, config) {
|
|
|
10819
11086
|
result: config.result,
|
|
10820
11087
|
doc: config.doc,
|
|
10821
11088
|
handler: async (params, ctx) => {
|
|
11089
|
+
if (params.request != null && params.attach_opaque_data === undefined && params.name === undefined) {
|
|
11090
|
+
params = unwrapRequest(params.request);
|
|
11091
|
+
}
|
|
10822
11092
|
normalizeRequestSchemaPaths(params);
|
|
10823
11093
|
await unwrapParamsOpaque(params, ctx, signingKey);
|
|
10824
11094
|
return config.handler(params, ctx);
|
|
@@ -11672,6 +11942,134 @@ function hex(buf) {
|
|
|
11672
11942
|
return Array.from(buf, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
11673
11943
|
}
|
|
11674
11944
|
|
|
11945
|
+
// src/catalog/contents-digest.ts
|
|
11946
|
+
var KINDS = [
|
|
11947
|
+
"tables",
|
|
11948
|
+
"views",
|
|
11949
|
+
"scalar_functions",
|
|
11950
|
+
"aggregate_functions",
|
|
11951
|
+
"table_functions",
|
|
11952
|
+
"scalar_macros",
|
|
11953
|
+
"table_macros",
|
|
11954
|
+
"indexes"
|
|
11955
|
+
];
|
|
11956
|
+
async function catalogContentsDigest(schemas) {
|
|
11957
|
+
const utf8 = new TextEncoder;
|
|
11958
|
+
const parts = [];
|
|
11959
|
+
let total = 0;
|
|
11960
|
+
const count = (n) => {
|
|
11961
|
+
const b = new Uint8Array(8);
|
|
11962
|
+
new DataView(b.buffer).setBigUint64(0, BigInt(n), true);
|
|
11963
|
+
parts.push(b);
|
|
11964
|
+
total += 8;
|
|
11965
|
+
};
|
|
11966
|
+
const chunk = (data) => {
|
|
11967
|
+
count(data.byteLength);
|
|
11968
|
+
parts.push(data);
|
|
11969
|
+
total += data.byteLength;
|
|
11970
|
+
};
|
|
11971
|
+
const chunks = (values) => {
|
|
11972
|
+
count(values.length);
|
|
11973
|
+
for (const v of values)
|
|
11974
|
+
chunk(v);
|
|
11975
|
+
};
|
|
11976
|
+
count(schemas.length);
|
|
11977
|
+
for (const entry of schemas) {
|
|
11978
|
+
chunks(entry.path.map((p) => utf8.encode(p)));
|
|
11979
|
+
chunk(entry.schema);
|
|
11980
|
+
for (const kind of KINDS)
|
|
11981
|
+
chunks(entry[kind]);
|
|
11982
|
+
}
|
|
11983
|
+
const buf = new Uint8Array(total);
|
|
11984
|
+
let off = 0;
|
|
11985
|
+
for (const p of parts) {
|
|
11986
|
+
buf.set(p, off);
|
|
11987
|
+
off += p.byteLength;
|
|
11988
|
+
}
|
|
11989
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", buf));
|
|
11990
|
+
let hex = "";
|
|
11991
|
+
for (const b of digest)
|
|
11992
|
+
hex += b.toString(16).padStart(2, "0");
|
|
11993
|
+
return hex;
|
|
11994
|
+
}
|
|
11995
|
+
|
|
11996
|
+
// src/protocol/handlers/catalog/contents.ts
|
|
11997
|
+
var CACHE = new WeakMap;
|
|
11998
|
+
async function buildCatalogContents(cat, owner, attach, version, ifNoneMatch) {
|
|
11999
|
+
const result = await cat.catalogContents(attach, ifNoneMatch);
|
|
12000
|
+
const etag0 = result.etag ?? null;
|
|
12001
|
+
if (result.not_modified) {
|
|
12002
|
+
if (etag0 === null || ifNoneMatch === null || etag0 !== ifNoneMatch) {
|
|
12003
|
+
throw new Error("catalog_contents returned not_modified, but only a catalog whose etag equals " + "if_none_match may (and it must return that etag)");
|
|
12004
|
+
}
|
|
12005
|
+
if (result.schemas && result.schemas.length > 0) {
|
|
12006
|
+
throw new Error("catalog_contents returned not_modified with schemas; it must return none");
|
|
12007
|
+
}
|
|
12008
|
+
return buildCatalogContentsResponse({ catalog_version: version, etag: etag0, not_modified: true });
|
|
12009
|
+
}
|
|
12010
|
+
const infos = [...result.schemas ?? []];
|
|
12011
|
+
const keys = infos.map((c) => schemaPathKey(c.schema.path));
|
|
12012
|
+
const keySet = new Set(keys);
|
|
12013
|
+
if (keySet.size !== keys.length)
|
|
12014
|
+
throw new Error("catalog_contents returned duplicate schema paths");
|
|
12015
|
+
for (const c of infos) {
|
|
12016
|
+
if (c.schema.path.length > 1 && !keySet.has(schemaPathKey(c.schema.path.slice(0, -1)))) {
|
|
12017
|
+
throw new Error(`catalog_contents returned schema path ${JSON.stringify(c.schema.path)} without its parent`);
|
|
12018
|
+
}
|
|
12019
|
+
}
|
|
12020
|
+
const schemas = infos.sort((a, b) => a.schema.path.length - b.schema.path.length).map((c) => buildSchemaContents({
|
|
12021
|
+
path: [...c.schema.path],
|
|
12022
|
+
schema: encodeSchemaInfo(c.schema),
|
|
12023
|
+
tables: c.tables.map((t) => encodeTableInfo(t)),
|
|
12024
|
+
views: c.views.map((v) => encodeViewInfo(v)),
|
|
12025
|
+
scalar_functions: c.scalar_functions.map((f) => encodeFunctionInfoOnce(f)),
|
|
12026
|
+
aggregate_functions: c.aggregate_functions.map((f) => encodeFunctionInfoOnce(f)),
|
|
12027
|
+
table_functions: c.table_functions.map((f) => encodeFunctionInfoOnce(f)),
|
|
12028
|
+
scalar_macros: c.scalar_macros.map((m) => encodeMacroInfo(m)),
|
|
12029
|
+
table_macros: c.table_macros.map((m) => encodeMacroInfo(m)),
|
|
12030
|
+
indexes: c.indexes.map((i) => encodeIndexInfo(i))
|
|
12031
|
+
}));
|
|
12032
|
+
let etag = etag0;
|
|
12033
|
+
if (etag === null && owner.catalogContentsEtag === "content-hash") {
|
|
12034
|
+
etag = await catalogContentsDigest(schemas);
|
|
12035
|
+
}
|
|
12036
|
+
if (etag !== null && ifNoneMatch !== null && etag === ifNoneMatch) {
|
|
12037
|
+
return buildCatalogContentsResponse({ catalog_version: version, etag, not_modified: true });
|
|
12038
|
+
}
|
|
12039
|
+
return buildCatalogContentsResponse({ catalog_version: version, etag, schemas });
|
|
12040
|
+
}
|
|
12041
|
+
async function serveCatalogContents(cat, attach, ifNoneMatch) {
|
|
12042
|
+
const owner = cat.catalogContentsOwner(attach);
|
|
12043
|
+
const version = Number(await cat.version(attach));
|
|
12044
|
+
if (owner.catalogContentsCacheable()) {
|
|
12045
|
+
let pending = CACHE.get(owner);
|
|
12046
|
+
let snapshot = pending ? await pending.catch(() => null) : null;
|
|
12047
|
+
if (!snapshot || snapshot.version !== version) {
|
|
12048
|
+
pending = (async () => {
|
|
12049
|
+
const built = await buildCatalogContents(cat, owner, attach, version, null);
|
|
12050
|
+
return {
|
|
12051
|
+
version,
|
|
12052
|
+
etag: built.etag ?? null,
|
|
12053
|
+
wire: wrapResult(built, CatalogContentsResultSchema)
|
|
12054
|
+
};
|
|
12055
|
+
})();
|
|
12056
|
+
CACHE.set(owner, pending);
|
|
12057
|
+
try {
|
|
12058
|
+
snapshot = await pending;
|
|
12059
|
+
} catch (err) {
|
|
12060
|
+
if (CACHE.get(owner) === pending)
|
|
12061
|
+
CACHE.delete(owner);
|
|
12062
|
+
throw err;
|
|
12063
|
+
}
|
|
12064
|
+
}
|
|
12065
|
+
if (ifNoneMatch !== null && snapshot.etag !== null && ifNoneMatch === snapshot.etag) {
|
|
12066
|
+
return wrapResult(buildCatalogContentsResponse({ catalog_version: version, etag: snapshot.etag, not_modified: true }), CatalogContentsResultSchema);
|
|
12067
|
+
}
|
|
12068
|
+
return snapshot.wire;
|
|
12069
|
+
}
|
|
12070
|
+
return wrapResult(await buildCatalogContents(cat, owner, attach, version, ifNoneMatch), CatalogContentsResultSchema);
|
|
12071
|
+
}
|
|
12072
|
+
|
|
11675
12073
|
// src/protocol/handlers/catalog/admin.ts
|
|
11676
12074
|
function registerCatalogAdminMethods(protocol, getCatalog, signingKey) {
|
|
11677
12075
|
catalogUnary(protocol, signingKey, "catalog_catalogs", {
|
|
@@ -11699,25 +12097,11 @@ function registerCatalogAdminMethods(protocol, getCatalog, signingKey) {
|
|
|
11699
12097
|
const optionsDict = decodeOptionsBatch(innerParams.options);
|
|
11700
12098
|
const result = await cat.attach(innerParams.name, optionsDict, innerParams.data_version_spec ?? null, innerParams.implementation_version ?? null);
|
|
11701
12099
|
const sealedAttach = await sealAttach(toUint8Array(result.attach_opaque_data), ctx?.auth, signingKey);
|
|
11702
|
-
return wrapResult({
|
|
12100
|
+
return wrapResult(buildCatalogAttachResult({
|
|
12101
|
+
...result,
|
|
11703
12102
|
attach_opaque_data: sealedAttach,
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
catalog_version_frozen: result.catalog_version_frozen,
|
|
11707
|
-
catalog_version: result.catalog_version,
|
|
11708
|
-
attach_opaque_data_required: result.attach_opaque_data_required ?? true,
|
|
11709
|
-
default_schema: result.default_schema ?? "main",
|
|
11710
|
-
settings: result.settings ?? [],
|
|
11711
|
-
secret_types: result.secret_types ?? [],
|
|
11712
|
-
attach_catalogs: result.attach_catalogs ?? [],
|
|
11713
|
-
comment: result.comment ?? null,
|
|
11714
|
-
tags: result.tags ?? {},
|
|
11715
|
-
supports_column_statistics: result.supports_column_statistics ?? true,
|
|
11716
|
-
global_functions: result.global_functions ?? [],
|
|
11717
|
-
global_function_prefix: result.global_function_prefix ?? "",
|
|
11718
|
-
resolved_data_version: result.resolved_data_version ?? null,
|
|
11719
|
-
resolved_implementation_version: result.resolved_implementation_version ?? null
|
|
11720
|
-
}, CatalogAttachResultSchema);
|
|
12103
|
+
supports_column_statistics: result.supports_column_statistics ?? true
|
|
12104
|
+
}), CatalogAttachResultSchema);
|
|
11721
12105
|
}
|
|
11722
12106
|
});
|
|
11723
12107
|
catalogUnary(protocol, signingKey, "catalog_detach", {
|
|
@@ -11798,6 +12182,14 @@ function registerCatalogAdminMethods(protocol, getCatalog, signingKey) {
|
|
|
11798
12182
|
}, CatalogSchemasResultSchema);
|
|
11799
12183
|
}
|
|
11800
12184
|
});
|
|
12185
|
+
catalogUnary(protocol, signingKey, "catalog_contents", {
|
|
12186
|
+
params: CatalogContentsParamsSchema,
|
|
12187
|
+
result: RESULT_BINARY_SCHEMA,
|
|
12188
|
+
handler: async (params) => {
|
|
12189
|
+
const ifNoneMatch = params.if_none_match == null ? null : String(params.if_none_match);
|
|
12190
|
+
return serveCatalogContents(getCatalog(), toUint8Array(params.attach_opaque_data), ifNoneMatch);
|
|
12191
|
+
}
|
|
12192
|
+
});
|
|
11801
12193
|
catalogUnary(protocol, signingKey, "catalog_copy_from_formats", {
|
|
11802
12194
|
params: CatalogCopyFromFormatsParamsSchema,
|
|
11803
12195
|
result: RESULT_BINARY_SCHEMA,
|
|
@@ -12092,7 +12484,7 @@ function registerCatalogMacroMethods(protocol, getCatalog, signingKey) {
|
|
|
12092
12484
|
result: emptyResultSchema,
|
|
12093
12485
|
handler: async (params) => {
|
|
12094
12486
|
const cat = getCatalog();
|
|
12095
|
-
const innerParams =
|
|
12487
|
+
const innerParams = params;
|
|
12096
12488
|
await cat.macroCreate(toUint8Array(innerParams.attach_opaque_data), innerParams.schema_path, innerParams.name, innerParams.macro_type, innerParams.parameters ? Array.isArray(innerParams.parameters) ? innerParams.parameters : [...innerParams.parameters] : [], innerParams.definition, innerParams.on_conflict, innerParams.parameter_default_values ? toUint8Array(innerParams.parameter_default_values) : null, innerParams.arguments_schema ? toUint8Array(innerParams.arguments_schema) : null, innerParams.transaction_opaque_data ? toUint8Array(innerParams.transaction_opaque_data) : undefined);
|
|
12097
12489
|
return {};
|
|
12098
12490
|
}
|
|
@@ -12158,7 +12550,7 @@ function registerCatalogMethods(protocol, catalog, _catalogName, signingKey) {
|
|
|
12158
12550
|
// src/protocol/dispatch.ts
|
|
12159
12551
|
var VGI_PROTOCOL_NAME = "vgi.v2";
|
|
12160
12552
|
function buildVgiProtocol(config) {
|
|
12161
|
-
const protocol = new Protocol(VGI_PROTOCOL_NAME, { protocolVersion: "2.
|
|
12553
|
+
const protocol = new Protocol(VGI_PROTOCOL_NAME, { protocolVersion: "2.1.0" });
|
|
12162
12554
|
registerFunctionMethods(protocol, {
|
|
12163
12555
|
registry: config.registry,
|
|
12164
12556
|
signingKey: config.signingKey,
|
|
@@ -12798,7 +13190,40 @@ class VgiClient {
|
|
|
12798
13190
|
global_functions: inner.global_functions ? (Array.isArray(inner.global_functions) ? inner.global_functions : [...inner.global_functions]).map(toUint8Array) : [],
|
|
12799
13191
|
global_function_prefix: inner.global_function_prefix ?? "",
|
|
12800
13192
|
resolved_data_version: inner.resolved_data_version ?? null,
|
|
12801
|
-
resolved_implementation_version: inner.resolved_implementation_version ?? null
|
|
13193
|
+
resolved_implementation_version: inner.resolved_implementation_version ?? null,
|
|
13194
|
+
supports_catalog_contents: inner.supports_catalog_contents ?? false
|
|
13195
|
+
};
|
|
13196
|
+
}
|
|
13197
|
+
async catalogContents(attachOpaqueData, ifNoneMatch = null) {
|
|
13198
|
+
const result = await this.rpc.call("catalog_contents", {
|
|
13199
|
+
attach_opaque_data: attachOpaqueData,
|
|
13200
|
+
if_none_match: ifNoneMatch
|
|
13201
|
+
});
|
|
13202
|
+
if (!result)
|
|
13203
|
+
throw new VgiClientError("catalog_contents returned null");
|
|
13204
|
+
const response = decodeCatalogContentsResponse(toUint8Array(result.result));
|
|
13205
|
+
const schemas = response.schemas.map((c) => {
|
|
13206
|
+
const schema = decodeSchemaInfo(c.schema);
|
|
13207
|
+
if (JSON.stringify(c.path) !== JSON.stringify(schema.path)) {
|
|
13208
|
+
throw new VgiClientError(`catalog_contents: SchemaContents.path ${JSON.stringify(c.path)} != SchemaInfo.path ${JSON.stringify(schema.path)}`);
|
|
13209
|
+
}
|
|
13210
|
+
return {
|
|
13211
|
+
schema,
|
|
13212
|
+
tables: c.tables.map(decodeTableInfo),
|
|
13213
|
+
views: c.views.map(decodeViewInfo),
|
|
13214
|
+
scalar_functions: c.scalar_functions.map(decodeFunctionInfo),
|
|
13215
|
+
aggregate_functions: c.aggregate_functions.map(decodeFunctionInfo),
|
|
13216
|
+
table_functions: c.table_functions.map(decodeFunctionInfo),
|
|
13217
|
+
scalar_macros: c.scalar_macros.map(decodeMacroInfo),
|
|
13218
|
+
table_macros: c.table_macros.map(decodeMacroInfo),
|
|
13219
|
+
indexes: c.indexes.map(decodeIndexInfo)
|
|
13220
|
+
};
|
|
13221
|
+
});
|
|
13222
|
+
return {
|
|
13223
|
+
catalog_version: Number(response.catalog_version ?? 0),
|
|
13224
|
+
etag: response.etag ?? null,
|
|
13225
|
+
not_modified: Boolean(response.not_modified),
|
|
13226
|
+
schemas
|
|
12802
13227
|
};
|
|
12803
13228
|
}
|
|
12804
13229
|
async catalogDetach(attachOpaqueData) {
|
|
@@ -13203,9 +13628,103 @@ class VgiClient {
|
|
|
13203
13628
|
// src/index.core.ts
|
|
13204
13629
|
import { str, bytes, int as int3, int32 as int323, float, float32 as float323, bool as bool3, toSchema, OutputCollector, AuthContext } from "@query-farm/vgi-rpc";
|
|
13205
13630
|
import { subprocessConnect, httpConnect, tcpConnect } from "@query-farm/vgi-rpc";
|
|
13631
|
+
|
|
13632
|
+
// src/rpc-server.ts
|
|
13633
|
+
import {
|
|
13634
|
+
IdentityImpl,
|
|
13635
|
+
VgiRpcServer
|
|
13636
|
+
} from "@query-farm/vgi-rpc";
|
|
13637
|
+
var TRANSPORTS = new Set(["pipe", "unix", "tcp", "iroh", "stream", "http"]);
|
|
13638
|
+
var IDENTITY_TRANSPORTS = new Set(["http"]);
|
|
13639
|
+
var RESERVED_PREFIX = "vgi_rpc.";
|
|
13640
|
+
var INTROSPECT_PRINCIPALS_ENV = "VGI_INTROSPECT_PRINCIPALS";
|
|
13641
|
+
function buildRpcServer(primary, hosting, options) {
|
|
13642
|
+
if (!TRANSPORTS.has(options.transport)) {
|
|
13643
|
+
throw new Error(`Unknown transport ${JSON.stringify(options.transport)}; expected one of ${[...TRANSPORTS].join(", ")}.`);
|
|
13644
|
+
}
|
|
13645
|
+
const protocols = validatedHostedProtocols(hosting, primary);
|
|
13646
|
+
const identity = IDENTITY_TRANSPORTS.has(options.transport) ? buildIdentity(hosting, options.env) : undefined;
|
|
13647
|
+
return new VgiRpcServer(primary, {
|
|
13648
|
+
serverId: options.serverId,
|
|
13649
|
+
protocols,
|
|
13650
|
+
identity
|
|
13651
|
+
});
|
|
13652
|
+
}
|
|
13653
|
+
function validatedHostedProtocols(hosting, primary) {
|
|
13654
|
+
if (hosting.hostedProtocols === undefined)
|
|
13655
|
+
return [];
|
|
13656
|
+
const owner = "hostedProtocols()";
|
|
13657
|
+
if (typeof hosting.hostedProtocols !== "function") {
|
|
13658
|
+
throw new TypeError(`${owner} must be a function returning vgi-rpc Protocols, got ${typeof hosting.hostedProtocols}.`);
|
|
13659
|
+
}
|
|
13660
|
+
const raw = hosting.hostedProtocols();
|
|
13661
|
+
if (raw == null || typeof raw[Symbol.iterator] !== "function" || typeof raw === "string") {
|
|
13662
|
+
throw new TypeError(`${owner} must return an iterable of vgi-rpc Protocols, got ${String(raw)}.`);
|
|
13663
|
+
}
|
|
13664
|
+
const seen = new Set;
|
|
13665
|
+
const out = [];
|
|
13666
|
+
let index = 0;
|
|
13667
|
+
for (const proto of raw) {
|
|
13668
|
+
const p = proto;
|
|
13669
|
+
if (p == null || typeof p.name !== "string" || typeof p.getMethod !== "function") {
|
|
13670
|
+
throw new TypeError(`${owner} entry ${index} must be a vgi-rpc Protocol, got ${String(proto)}.`);
|
|
13671
|
+
}
|
|
13672
|
+
const name = p.name;
|
|
13673
|
+
if (name.startsWith(RESERVED_PREFIX)) {
|
|
13674
|
+
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.v1 is enabled by supplying resolveToken and/or mintGrant.");
|
|
13675
|
+
}
|
|
13676
|
+
if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name)) {
|
|
13677
|
+
throw new Error(`${owner} entry ${index}: protocol name '${name}' is not an identifier, optionally dot-qualified ` + "(e.g. 'acme.Reports.v1').");
|
|
13678
|
+
}
|
|
13679
|
+
if (name === primary.name) {
|
|
13680
|
+
throw new Error(`${owner} entry ${index} is named '${name}', the worker's own protocol. Give it a distinct name.`);
|
|
13681
|
+
}
|
|
13682
|
+
if (seen.has(name)) {
|
|
13683
|
+
throw new Error(`${owner} lists protocol name '${name}' twice. The name is the routing key, so each hosted protocol ` + "needs a distinct name.");
|
|
13684
|
+
}
|
|
13685
|
+
seen.add(name);
|
|
13686
|
+
out.push(proto);
|
|
13687
|
+
index++;
|
|
13688
|
+
}
|
|
13689
|
+
return out;
|
|
13690
|
+
}
|
|
13691
|
+
function buildIdentity(hosting, env) {
|
|
13692
|
+
const { resolveToken, mintGrant } = hosting;
|
|
13693
|
+
if (!resolveToken && !mintGrant)
|
|
13694
|
+
return;
|
|
13695
|
+
return new IdentityImpl({
|
|
13696
|
+
resolveToken,
|
|
13697
|
+
mintGrant,
|
|
13698
|
+
introspectPrincipals: resolveToken ? resolveIntrospectPrincipals(hosting.introspectPrincipals, env) : undefined,
|
|
13699
|
+
maxAuthAge: hosting.maxAuthAge
|
|
13700
|
+
});
|
|
13701
|
+
}
|
|
13702
|
+
function resolveIntrospectPrincipals(explicit, env) {
|
|
13703
|
+
let principals;
|
|
13704
|
+
if (explicit !== undefined) {
|
|
13705
|
+
principals = [...explicit].map((p) => p.trim()).filter((p) => p !== "");
|
|
13706
|
+
} else {
|
|
13707
|
+
const source = env ?? globalThis.process?.env;
|
|
13708
|
+
const raw = source?.[INTROSPECT_PRINCIPALS_ENV] ?? "";
|
|
13709
|
+
principals = raw.split(",").map((p) => p.trim()).filter((p) => p !== "");
|
|
13710
|
+
}
|
|
13711
|
+
if (principals.length === 0) {
|
|
13712
|
+
throw new Error("This worker supplies resolveToken, which hosts the vgi_rpc.Identity.v1 protocol, but no " + `introspector allowlist was configured. Set ${INTROSPECT_PRINCIPALS_ENV} (comma-separated) or pass ` + `introspectPrincipals.
|
|
13713
|
+
|
|
13714
|
+
` + "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.");
|
|
13715
|
+
}
|
|
13716
|
+
return principals;
|
|
13717
|
+
}
|
|
13718
|
+
|
|
13719
|
+
// src/index.core.ts
|
|
13720
|
+
import {
|
|
13721
|
+
AuthUnavailableError,
|
|
13722
|
+
GrantRefusedError,
|
|
13723
|
+
IdentityUnavailableError,
|
|
13724
|
+
StatusError
|
|
13725
|
+
} from "@query-farm/vgi-rpc";
|
|
13206
13726
|
// src/worker.ts
|
|
13207
13727
|
import {
|
|
13208
|
-
VgiRpcServer,
|
|
13209
13728
|
observePeerIdentity,
|
|
13210
13729
|
peerIdentityPrimary,
|
|
13211
13730
|
serveUnix,
|
|
@@ -13269,11 +13788,19 @@ function parseLauncherArgs(argv) {
|
|
|
13269
13788
|
|
|
13270
13789
|
class Worker {
|
|
13271
13790
|
_registry;
|
|
13791
|
+
_hosting;
|
|
13272
13792
|
_catalogInterface;
|
|
13273
13793
|
_catalogName;
|
|
13274
13794
|
constructor(config) {
|
|
13275
13795
|
this._registry = config.registry ?? new FunctionRegistry;
|
|
13276
13796
|
this._catalogName = config.catalogName;
|
|
13797
|
+
this._hosting = {
|
|
13798
|
+
hostedProtocols: config.hostedProtocols,
|
|
13799
|
+
resolveToken: config.resolveToken,
|
|
13800
|
+
mintGrant: config.mintGrant,
|
|
13801
|
+
introspectPrincipals: config.introspectPrincipals,
|
|
13802
|
+
maxAuthAge: config.maxAuthAge
|
|
13803
|
+
};
|
|
13277
13804
|
if (config.functions) {
|
|
13278
13805
|
for (const func of config.functions) {
|
|
13279
13806
|
this._registry.register(func);
|
|
@@ -13313,7 +13840,7 @@ class Worker {
|
|
|
13313
13840
|
const envOverride = process.env.VGI_WORKER_IDLE_TIMEOUT;
|
|
13314
13841
|
const idleTimeout = envOverride !== undefined && envOverride !== "" ? Number(envOverride) : launcher.idleTimeout;
|
|
13315
13842
|
debug(() => `[worker] AF_UNIX mode: ${launcher.unixPath} idle=${idleTimeout ?? 300}s${envOverride !== undefined && envOverride !== "" ? " (env override)" : ""}`);
|
|
13316
|
-
serveUnix(protocol, {
|
|
13843
|
+
serveUnix(this.buildServer(protocol, "unix"), {
|
|
13317
13844
|
unixPath: launcher.unixPath,
|
|
13318
13845
|
idleTimeout
|
|
13319
13846
|
}).then((handle) => handle.done).then(() => {
|
|
@@ -13330,7 +13857,7 @@ ${err.stack}
|
|
|
13330
13857
|
const envOverride = process.env.VGI_WORKER_IDLE_TIMEOUT;
|
|
13331
13858
|
const idleTimeout = envOverride !== undefined && envOverride !== "" ? Number(envOverride) : launcher.idleTimeout;
|
|
13332
13859
|
debug(() => `[worker] TCP mode: ${launcher.tcpHost}:${launcher.tcpPort} idle=${idleTimeout ?? 300}s${envOverride !== undefined && envOverride !== "" ? " (env override)" : ""}`);
|
|
13333
|
-
serveTcp(protocol, {
|
|
13860
|
+
serveTcp(this.buildServer(protocol, launcher.irohRawUpstream ? "iroh" : "tcp"), {
|
|
13334
13861
|
host: launcher.tcpHost,
|
|
13335
13862
|
port: launcher.tcpPort,
|
|
13336
13863
|
idleTimeout,
|
|
@@ -13350,7 +13877,7 @@ ${err.stack}
|
|
|
13350
13877
|
});
|
|
13351
13878
|
return;
|
|
13352
13879
|
}
|
|
13353
|
-
const server =
|
|
13880
|
+
const server = this.buildServer(protocol, "pipe");
|
|
13354
13881
|
debug(() => `[worker] server created, calling run()`);
|
|
13355
13882
|
server.run().then(() => {
|
|
13356
13883
|
debug(() => `[worker] server.run() resolved cleanly`);
|
|
@@ -13367,6 +13894,9 @@ ${err.stack}
|
|
|
13367
13894
|
process.exit(1);
|
|
13368
13895
|
}
|
|
13369
13896
|
}
|
|
13897
|
+
buildServer(protocol, transport) {
|
|
13898
|
+
return buildRpcServer(protocol, this._hosting, { transport });
|
|
13899
|
+
}
|
|
13370
13900
|
buildProtocol() {
|
|
13371
13901
|
return buildVgiProtocol({
|
|
13372
13902
|
registry: this._registry,
|
|
@@ -13375,7 +13905,7 @@ ${err.stack}
|
|
|
13375
13905
|
});
|
|
13376
13906
|
}
|
|
13377
13907
|
async serveStream(readable, writable) {
|
|
13378
|
-
await serveStreamRpc(this.buildProtocol(), { readable, writable });
|
|
13908
|
+
await serveStreamRpc(this.buildServer(this.buildProtocol(), "stream"), { readable, writable });
|
|
13379
13909
|
}
|
|
13380
13910
|
}
|
|
13381
13911
|
export {
|
|
@@ -13383,6 +13913,7 @@ export {
|
|
|
13383
13913
|
ArgumentValidationError,
|
|
13384
13914
|
Arguments,
|
|
13385
13915
|
AuthContext,
|
|
13916
|
+
AuthUnavailableError,
|
|
13386
13917
|
BindResultSchema,
|
|
13387
13918
|
BoundStorage,
|
|
13388
13919
|
CACHE_ETAG_KEY,
|
|
@@ -13420,6 +13951,9 @@ export {
|
|
|
13420
13951
|
FunctionStorageSqlite,
|
|
13421
13952
|
FunctionType,
|
|
13422
13953
|
GROUP_COLUMN_NAME,
|
|
13954
|
+
GrantRefusedError,
|
|
13955
|
+
INTROSPECT_PRINCIPALS_ENV,
|
|
13956
|
+
IdentityUnavailableError,
|
|
13423
13957
|
IntervalUnit2 as IntervalUnit,
|
|
13424
13958
|
NoCatalogError,
|
|
13425
13959
|
NullHandling,
|
|
@@ -13428,9 +13962,11 @@ export {
|
|
|
13428
13962
|
OutputCollector,
|
|
13429
13963
|
PARENT_ROW_METADATA_KEY,
|
|
13430
13964
|
PushdownFilters,
|
|
13965
|
+
READ_ONLY_ITEM_ATTACH_ID,
|
|
13431
13966
|
ReadOnlyCatalogInterface,
|
|
13432
13967
|
RowCountMismatchError,
|
|
13433
13968
|
ScanFunctionResultSchema,
|
|
13969
|
+
StatusError,
|
|
13434
13970
|
TableInOutPhase,
|
|
13435
13971
|
TimeUnit2 as TimeUnit,
|
|
13436
13972
|
TypeId,
|
|
@@ -13468,7 +14004,9 @@ export {
|
|
|
13468
14004
|
batchToSecretDict,
|
|
13469
14005
|
binary2 as binary,
|
|
13470
14006
|
bool3 as bool,
|
|
14007
|
+
buildCatalogAttachResult,
|
|
13471
14008
|
buildJoinKeysLookup,
|
|
14009
|
+
buildRpcServer,
|
|
13472
14010
|
buildScanBranchesResult,
|
|
13473
14011
|
buildVgiProtocol,
|
|
13474
14012
|
bytes,
|
|
@@ -13621,4 +14159,4 @@ export {
|
|
|
13621
14159
|
utf82 as utf8
|
|
13622
14160
|
};
|
|
13623
14161
|
|
|
13624
|
-
//# debugId=
|
|
14162
|
+
//# debugId=B9E14A528C9EAE0164756E2164756E21
|