@query-farm/vgi 0.37.1 → 0.39.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/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 +49 -2
- package/dist/client/types.d.ts +56 -1
- package/dist/client-entry.js +239 -11
- package/dist/client-entry.js.map +9 -8
- package/dist/codec/asd.d.ts +8 -0
- package/dist/functions/copy-to.d.ts +1 -1
- 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 +6 -3
- package/dist/index.js +672 -43
- 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 +20 -16
- package/dist/worker.d.ts +9 -1
- package/package.json +3 -3
- 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 +201 -0
- package/src/client/types.ts +58 -1
- package/src/codec/asd.ts +108 -9
- package/src/functions/copy-to.ts +1 -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 +23 -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/serve-entry.js
CHANGED
|
@@ -553,6 +553,15 @@ var TypeId = {
|
|
|
553
553
|
function isDecimal(t) {
|
|
554
554
|
return t.typeId === TypeId.Decimal;
|
|
555
555
|
}
|
|
556
|
+
function isList(t) {
|
|
557
|
+
return t.typeId === TypeId.List;
|
|
558
|
+
}
|
|
559
|
+
function isStruct(t) {
|
|
560
|
+
return t.typeId === TypeId.Struct;
|
|
561
|
+
}
|
|
562
|
+
function isMap(t) {
|
|
563
|
+
return t.typeId === TypeId.Map;
|
|
564
|
+
}
|
|
556
565
|
function typeSignature(t) {
|
|
557
566
|
if (t == null)
|
|
558
567
|
return "null";
|
|
@@ -3343,6 +3352,18 @@ var ForeignKeyInfoSchema = schema2([
|
|
|
3343
3352
|
field2("referenced_table", utf82(), false),
|
|
3344
3353
|
field2("referenced_schema_path", list2(field2("item", utf82(), true)), false)
|
|
3345
3354
|
]);
|
|
3355
|
+
var SchemaContentsSchema = schema2([
|
|
3356
|
+
field2("path", list2(field2("item", utf82(), true)), false),
|
|
3357
|
+
field2("schema", binary2(), false),
|
|
3358
|
+
field2("tables", list2(field2("item", binary2(), true)), false),
|
|
3359
|
+
field2("views", list2(field2("item", binary2(), true)), false),
|
|
3360
|
+
field2("scalar_functions", list2(field2("item", binary2(), true)), false),
|
|
3361
|
+
field2("aggregate_functions", list2(field2("item", binary2(), true)), false),
|
|
3362
|
+
field2("table_functions", list2(field2("item", binary2(), true)), false),
|
|
3363
|
+
field2("scalar_macros", list2(field2("item", binary2(), true)), false),
|
|
3364
|
+
field2("table_macros", list2(field2("item", binary2(), true)), false),
|
|
3365
|
+
field2("indexes", list2(field2("item", binary2(), true)), false)
|
|
3366
|
+
]);
|
|
3346
3367
|
var AggregateBindRequestSchema = schema2([
|
|
3347
3368
|
field2("function_name", utf82(), false),
|
|
3348
3369
|
field2("arguments", binary2(), false),
|
|
@@ -3665,11 +3686,18 @@ var CatalogAttachResultSchema = schema2([
|
|
|
3665
3686
|
field2("global_functions", list2(field2("item", binary2(), true)), false),
|
|
3666
3687
|
field2("global_function_prefix", utf82(), false),
|
|
3667
3688
|
field2("resolved_data_version", utf82(), true),
|
|
3668
|
-
field2("resolved_implementation_version", utf82(), true)
|
|
3689
|
+
field2("resolved_implementation_version", utf82(), true),
|
|
3690
|
+
field2("supports_catalog_contents", bool2(), false)
|
|
3669
3691
|
]);
|
|
3670
3692
|
var CatalogCatalogsResultSchema = schema2([
|
|
3671
3693
|
field2("items", list2(field2("item", binary2(), true)), false)
|
|
3672
3694
|
]);
|
|
3695
|
+
var CatalogContentsResultSchema = schema2([
|
|
3696
|
+
field2("catalog_version", int642(), false),
|
|
3697
|
+
field2("etag", utf82(), true),
|
|
3698
|
+
field2("not_modified", bool2(), false),
|
|
3699
|
+
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)
|
|
3700
|
+
]);
|
|
3673
3701
|
var CatalogCopyFromFormatsResultSchema = schema2([
|
|
3674
3702
|
field2("items", list2(field2("item", binary2(), true)), false)
|
|
3675
3703
|
]);
|
|
@@ -3788,6 +3816,10 @@ var CatalogAttachParamsSchema = schema2([
|
|
|
3788
3816
|
field2("request", binary2(), false)
|
|
3789
3817
|
]);
|
|
3790
3818
|
var CatalogCatalogsParamsSchema = schema2([]);
|
|
3819
|
+
var CatalogContentsParamsSchema = schema2([
|
|
3820
|
+
field2("attach_opaque_data", binary2(), false),
|
|
3821
|
+
field2("if_none_match", utf82(), true)
|
|
3822
|
+
]);
|
|
3791
3823
|
var CatalogCopyFromFormatsParamsSchema = schema2([
|
|
3792
3824
|
field2("attach_opaque_data", binary2(), false),
|
|
3793
3825
|
field2("transaction_opaque_data", binary2(), true)
|
|
@@ -4122,6 +4154,13 @@ var TableFunctionStatisticsParamsSchema = schema2([
|
|
|
4122
4154
|
function normalizeSchemaPath(path) {
|
|
4123
4155
|
return typeof path === "string" ? [path] : Array.from(path, String);
|
|
4124
4156
|
}
|
|
4157
|
+
function schemaPathKey(path) {
|
|
4158
|
+
const normalized = normalizeSchemaPath(path);
|
|
4159
|
+
if (normalized.length === 0 || normalized.some((part) => part.length === 0)) {
|
|
4160
|
+
throw new Error("schema paths must contain at least one non-empty component");
|
|
4161
|
+
}
|
|
4162
|
+
return normalized.map((part) => part.toLowerCase()).join("\x00");
|
|
4163
|
+
}
|
|
4125
4164
|
|
|
4126
4165
|
// src/protocol/handlers/shared.ts
|
|
4127
4166
|
var RESULT_BINARY_SCHEMA = schema2([
|
|
@@ -5021,6 +5060,9 @@ function catalogUnary(protocol, signingKey, name, config) {
|
|
|
5021
5060
|
result: config.result,
|
|
5022
5061
|
doc: config.doc,
|
|
5023
5062
|
handler: async (params, ctx) => {
|
|
5063
|
+
if (params.request != null && params.attach_opaque_data === undefined && params.name === undefined) {
|
|
5064
|
+
params = unwrapRequest(params.request);
|
|
5065
|
+
}
|
|
5024
5066
|
normalizeRequestSchemaPaths(params);
|
|
5025
5067
|
await unwrapParamsOpaque(params, ctx, signingKey);
|
|
5026
5068
|
return config.handler(params, ctx);
|
|
@@ -6077,7 +6119,84 @@ function hex(buf) {
|
|
|
6077
6119
|
|
|
6078
6120
|
// src/codec/asd.ts
|
|
6079
6121
|
function encodeASD(schema, obj) {
|
|
6080
|
-
return serializeBatch(batchFromRows([obj], schema));
|
|
6122
|
+
return serializeBatch(batchFromRows([sortMapsForSchema(schema, obj)], schema));
|
|
6123
|
+
}
|
|
6124
|
+
function compareCodePoints(a, b) {
|
|
6125
|
+
const n = Math.min(a.length, b.length);
|
|
6126
|
+
for (let i = 0;i < n; i++) {
|
|
6127
|
+
const x = a.charCodeAt(i);
|
|
6128
|
+
const y = b.charCodeAt(i);
|
|
6129
|
+
if (x === y)
|
|
6130
|
+
continue;
|
|
6131
|
+
const xs = x >= 55296 && x <= 57343;
|
|
6132
|
+
const ys = y >= 55296 && y <= 57343;
|
|
6133
|
+
if (xs !== ys)
|
|
6134
|
+
return xs ? 1 : -1;
|
|
6135
|
+
return x - y;
|
|
6136
|
+
}
|
|
6137
|
+
return a.length - b.length;
|
|
6138
|
+
}
|
|
6139
|
+
function mapPairs(raw) {
|
|
6140
|
+
if (Array.isArray(raw))
|
|
6141
|
+
return raw.map((e) => Array.isArray(e) ? [e[0], e[1]] : [e?.key, e?.value]);
|
|
6142
|
+
if (raw instanceof Map)
|
|
6143
|
+
return Array.from(raw.entries());
|
|
6144
|
+
if (typeof raw[Symbol.iterator] === "function")
|
|
6145
|
+
return Array.from(raw);
|
|
6146
|
+
return Object.entries(raw);
|
|
6147
|
+
}
|
|
6148
|
+
function compareKeys(a, b) {
|
|
6149
|
+
if (typeof a === "string" && typeof b === "string")
|
|
6150
|
+
return compareCodePoints(a, b);
|
|
6151
|
+
if ((typeof a === "number" || typeof a === "bigint") && (typeof b === "number" || typeof b === "bigint")) {
|
|
6152
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
6153
|
+
}
|
|
6154
|
+
return compareCodePoints(String(a), String(b));
|
|
6155
|
+
}
|
|
6156
|
+
var HAS_MAP = new WeakMap;
|
|
6157
|
+
function typeHasMap(type) {
|
|
6158
|
+
const cached = HAS_MAP.get(type);
|
|
6159
|
+
if (cached !== undefined)
|
|
6160
|
+
return cached;
|
|
6161
|
+
let has = isMap(type);
|
|
6162
|
+
if (!has && (isList(type) || isStruct(type))) {
|
|
6163
|
+
has = type.children.some((c) => typeHasMap(c.type));
|
|
6164
|
+
}
|
|
6165
|
+
HAS_MAP.set(type, has);
|
|
6166
|
+
return has;
|
|
6167
|
+
}
|
|
6168
|
+
function sortMapsForType(type, value) {
|
|
6169
|
+
if (value == null || !typeHasMap(type))
|
|
6170
|
+
return value;
|
|
6171
|
+
if (isMap(type)) {
|
|
6172
|
+
const entries = type.children[0].type;
|
|
6173
|
+
const valueType = entries.children[1].type;
|
|
6174
|
+
return mapPairs(value).map(([k, v]) => [k, sortMapsForType(valueType, v)]).sort((x, y) => compareKeys(x[0], y[0]));
|
|
6175
|
+
}
|
|
6176
|
+
if (isList(type)) {
|
|
6177
|
+
const child = type.children[0].type;
|
|
6178
|
+
return Array.from(value, (v) => sortMapsForType(child, v));
|
|
6179
|
+
}
|
|
6180
|
+
if (isStruct(type)) {
|
|
6181
|
+
const out = { ...value };
|
|
6182
|
+
for (const cf of type.children)
|
|
6183
|
+
out[cf.name] = sortMapsForType(cf.type, value[cf.name]);
|
|
6184
|
+
return out;
|
|
6185
|
+
}
|
|
6186
|
+
return value;
|
|
6187
|
+
}
|
|
6188
|
+
function sortMapsForSchema(schema, obj) {
|
|
6189
|
+
let out = null;
|
|
6190
|
+
for (const f of schema.fields) {
|
|
6191
|
+
if (!typeHasMap(f.type))
|
|
6192
|
+
continue;
|
|
6193
|
+
const v = obj[f.name];
|
|
6194
|
+
if (v == null)
|
|
6195
|
+
continue;
|
|
6196
|
+
out ??= { ...obj };
|
|
6197
|
+
out[f.name] = sortMapsForType(f.type, v);
|
|
6198
|
+
}
|
|
6199
|
+
return out ?? obj;
|
|
6081
6200
|
}
|
|
6082
6201
|
|
|
6083
6202
|
// src/generated/vgi-client.ts
|
|
@@ -6089,6 +6208,52 @@ var encodeSchemaInfo = (v) => encodeASD(SchemaInfoSchema, v);
|
|
|
6089
6208
|
var encodeTableInfo = (v) => encodeASD(TableInfoSchema, v);
|
|
6090
6209
|
var encodeViewInfo = (v) => encodeASD(ViewInfoSchema, v);
|
|
6091
6210
|
|
|
6211
|
+
// src/generated/vgi-protocol-types.ts
|
|
6212
|
+
function buildCatalogAttachResult(init) {
|
|
6213
|
+
return {
|
|
6214
|
+
attach_opaque_data: init.attach_opaque_data,
|
|
6215
|
+
supports_transactions: init.supports_transactions,
|
|
6216
|
+
supports_time_travel: init.supports_time_travel,
|
|
6217
|
+
catalog_version_frozen: init.catalog_version_frozen,
|
|
6218
|
+
catalog_version: init.catalog_version,
|
|
6219
|
+
attach_opaque_data_required: init.attach_opaque_data_required ?? true,
|
|
6220
|
+
default_schema: init.default_schema ?? "main",
|
|
6221
|
+
settings: init.settings ?? [],
|
|
6222
|
+
secret_types: init.secret_types ?? [],
|
|
6223
|
+
attach_catalogs: init.attach_catalogs ?? [],
|
|
6224
|
+
comment: init.comment ?? null,
|
|
6225
|
+
tags: init.tags ?? {},
|
|
6226
|
+
supports_column_statistics: init.supports_column_statistics ?? false,
|
|
6227
|
+
global_functions: init.global_functions ?? [],
|
|
6228
|
+
global_function_prefix: init.global_function_prefix ?? "",
|
|
6229
|
+
resolved_data_version: init.resolved_data_version ?? null,
|
|
6230
|
+
resolved_implementation_version: init.resolved_implementation_version ?? null,
|
|
6231
|
+
supports_catalog_contents: init.supports_catalog_contents ?? false
|
|
6232
|
+
};
|
|
6233
|
+
}
|
|
6234
|
+
function buildSchemaContents(init) {
|
|
6235
|
+
return {
|
|
6236
|
+
path: init.path,
|
|
6237
|
+
schema: init.schema,
|
|
6238
|
+
tables: init.tables ?? [],
|
|
6239
|
+
views: init.views ?? [],
|
|
6240
|
+
scalar_functions: init.scalar_functions ?? [],
|
|
6241
|
+
aggregate_functions: init.aggregate_functions ?? [],
|
|
6242
|
+
table_functions: init.table_functions ?? [],
|
|
6243
|
+
scalar_macros: init.scalar_macros ?? [],
|
|
6244
|
+
table_macros: init.table_macros ?? [],
|
|
6245
|
+
indexes: init.indexes ?? []
|
|
6246
|
+
};
|
|
6247
|
+
}
|
|
6248
|
+
function buildCatalogContentsResponse(init) {
|
|
6249
|
+
return {
|
|
6250
|
+
catalog_version: init.catalog_version,
|
|
6251
|
+
etag: init.etag ?? null,
|
|
6252
|
+
not_modified: init.not_modified ?? false,
|
|
6253
|
+
schemas: init.schemas ?? []
|
|
6254
|
+
};
|
|
6255
|
+
}
|
|
6256
|
+
|
|
6092
6257
|
// src/catalog/item-encoding.ts
|
|
6093
6258
|
var ENCODED = new WeakMap;
|
|
6094
6259
|
function encodeFunctionInfoOnce(info) {
|
|
@@ -6102,6 +6267,134 @@ function encodeFunctionInfoOnce(info) {
|
|
|
6102
6267
|
return encoded;
|
|
6103
6268
|
}
|
|
6104
6269
|
|
|
6270
|
+
// src/catalog/contents-digest.ts
|
|
6271
|
+
var KINDS = [
|
|
6272
|
+
"tables",
|
|
6273
|
+
"views",
|
|
6274
|
+
"scalar_functions",
|
|
6275
|
+
"aggregate_functions",
|
|
6276
|
+
"table_functions",
|
|
6277
|
+
"scalar_macros",
|
|
6278
|
+
"table_macros",
|
|
6279
|
+
"indexes"
|
|
6280
|
+
];
|
|
6281
|
+
async function catalogContentsDigest(schemas) {
|
|
6282
|
+
const utf8 = new TextEncoder;
|
|
6283
|
+
const parts = [];
|
|
6284
|
+
let total = 0;
|
|
6285
|
+
const count = (n) => {
|
|
6286
|
+
const b = new Uint8Array(8);
|
|
6287
|
+
new DataView(b.buffer).setBigUint64(0, BigInt(n), true);
|
|
6288
|
+
parts.push(b);
|
|
6289
|
+
total += 8;
|
|
6290
|
+
};
|
|
6291
|
+
const chunk = (data) => {
|
|
6292
|
+
count(data.byteLength);
|
|
6293
|
+
parts.push(data);
|
|
6294
|
+
total += data.byteLength;
|
|
6295
|
+
};
|
|
6296
|
+
const chunks = (values) => {
|
|
6297
|
+
count(values.length);
|
|
6298
|
+
for (const v of values)
|
|
6299
|
+
chunk(v);
|
|
6300
|
+
};
|
|
6301
|
+
count(schemas.length);
|
|
6302
|
+
for (const entry of schemas) {
|
|
6303
|
+
chunks(entry.path.map((p) => utf8.encode(p)));
|
|
6304
|
+
chunk(entry.schema);
|
|
6305
|
+
for (const kind of KINDS)
|
|
6306
|
+
chunks(entry[kind]);
|
|
6307
|
+
}
|
|
6308
|
+
const buf = new Uint8Array(total);
|
|
6309
|
+
let off = 0;
|
|
6310
|
+
for (const p of parts) {
|
|
6311
|
+
buf.set(p, off);
|
|
6312
|
+
off += p.byteLength;
|
|
6313
|
+
}
|
|
6314
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", buf));
|
|
6315
|
+
let hex = "";
|
|
6316
|
+
for (const b of digest)
|
|
6317
|
+
hex += b.toString(16).padStart(2, "0");
|
|
6318
|
+
return hex;
|
|
6319
|
+
}
|
|
6320
|
+
|
|
6321
|
+
// src/protocol/handlers/catalog/contents.ts
|
|
6322
|
+
var CACHE = new WeakMap;
|
|
6323
|
+
async function buildCatalogContents(cat, owner, attach, version, ifNoneMatch) {
|
|
6324
|
+
const result = await cat.catalogContents(attach, ifNoneMatch);
|
|
6325
|
+
const etag0 = result.etag ?? null;
|
|
6326
|
+
if (result.not_modified) {
|
|
6327
|
+
if (etag0 === null || ifNoneMatch === null || etag0 !== ifNoneMatch) {
|
|
6328
|
+
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)");
|
|
6329
|
+
}
|
|
6330
|
+
if (result.schemas && result.schemas.length > 0) {
|
|
6331
|
+
throw new Error("catalog_contents returned not_modified with schemas; it must return none");
|
|
6332
|
+
}
|
|
6333
|
+
return buildCatalogContentsResponse({ catalog_version: version, etag: etag0, not_modified: true });
|
|
6334
|
+
}
|
|
6335
|
+
const infos = [...result.schemas ?? []];
|
|
6336
|
+
const keys = infos.map((c) => schemaPathKey(c.schema.path));
|
|
6337
|
+
const keySet = new Set(keys);
|
|
6338
|
+
if (keySet.size !== keys.length)
|
|
6339
|
+
throw new Error("catalog_contents returned duplicate schema paths");
|
|
6340
|
+
for (const c of infos) {
|
|
6341
|
+
if (c.schema.path.length > 1 && !keySet.has(schemaPathKey(c.schema.path.slice(0, -1)))) {
|
|
6342
|
+
throw new Error(`catalog_contents returned schema path ${JSON.stringify(c.schema.path)} without its parent`);
|
|
6343
|
+
}
|
|
6344
|
+
}
|
|
6345
|
+
const schemas = infos.sort((a, b) => a.schema.path.length - b.schema.path.length).map((c) => buildSchemaContents({
|
|
6346
|
+
path: [...c.schema.path],
|
|
6347
|
+
schema: encodeSchemaInfo(c.schema),
|
|
6348
|
+
tables: c.tables.map((t) => encodeTableInfo(t)),
|
|
6349
|
+
views: c.views.map((v) => encodeViewInfo(v)),
|
|
6350
|
+
scalar_functions: c.scalar_functions.map((f) => encodeFunctionInfoOnce(f)),
|
|
6351
|
+
aggregate_functions: c.aggregate_functions.map((f) => encodeFunctionInfoOnce(f)),
|
|
6352
|
+
table_functions: c.table_functions.map((f) => encodeFunctionInfoOnce(f)),
|
|
6353
|
+
scalar_macros: c.scalar_macros.map((m) => encodeMacroInfo(m)),
|
|
6354
|
+
table_macros: c.table_macros.map((m) => encodeMacroInfo(m)),
|
|
6355
|
+
indexes: c.indexes.map((i) => encodeIndexInfo(i))
|
|
6356
|
+
}));
|
|
6357
|
+
let etag = etag0;
|
|
6358
|
+
if (etag === null && owner.catalogContentsEtag === "content-hash") {
|
|
6359
|
+
etag = await catalogContentsDigest(schemas);
|
|
6360
|
+
}
|
|
6361
|
+
if (etag !== null && ifNoneMatch !== null && etag === ifNoneMatch) {
|
|
6362
|
+
return buildCatalogContentsResponse({ catalog_version: version, etag, not_modified: true });
|
|
6363
|
+
}
|
|
6364
|
+
return buildCatalogContentsResponse({ catalog_version: version, etag, schemas });
|
|
6365
|
+
}
|
|
6366
|
+
async function serveCatalogContents(cat, attach, ifNoneMatch) {
|
|
6367
|
+
const owner = cat.catalogContentsOwner(attach);
|
|
6368
|
+
const version = Number(await cat.version(attach));
|
|
6369
|
+
if (owner.catalogContentsCacheable()) {
|
|
6370
|
+
let pending = CACHE.get(owner);
|
|
6371
|
+
let snapshot = pending ? await pending.catch(() => null) : null;
|
|
6372
|
+
if (!snapshot || snapshot.version !== version) {
|
|
6373
|
+
pending = (async () => {
|
|
6374
|
+
const built = await buildCatalogContents(cat, owner, attach, version, null);
|
|
6375
|
+
return {
|
|
6376
|
+
version,
|
|
6377
|
+
etag: built.etag ?? null,
|
|
6378
|
+
wire: wrapResult(built, CatalogContentsResultSchema)
|
|
6379
|
+
};
|
|
6380
|
+
})();
|
|
6381
|
+
CACHE.set(owner, pending);
|
|
6382
|
+
try {
|
|
6383
|
+
snapshot = await pending;
|
|
6384
|
+
} catch (err) {
|
|
6385
|
+
if (CACHE.get(owner) === pending)
|
|
6386
|
+
CACHE.delete(owner);
|
|
6387
|
+
throw err;
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6390
|
+
if (ifNoneMatch !== null && snapshot.etag !== null && ifNoneMatch === snapshot.etag) {
|
|
6391
|
+
return wrapResult(buildCatalogContentsResponse({ catalog_version: version, etag: snapshot.etag, not_modified: true }), CatalogContentsResultSchema);
|
|
6392
|
+
}
|
|
6393
|
+
return snapshot.wire;
|
|
6394
|
+
}
|
|
6395
|
+
return wrapResult(await buildCatalogContents(cat, owner, attach, version, ifNoneMatch), CatalogContentsResultSchema);
|
|
6396
|
+
}
|
|
6397
|
+
|
|
6105
6398
|
// src/catalog/interface.ts
|
|
6106
6399
|
var encodeCopyFromFormatInfo = (v) => encodeASD(CopyFromFormatInfoSchema, {
|
|
6107
6400
|
comment: v.comment ?? null,
|
|
@@ -6141,25 +6434,11 @@ function registerCatalogAdminMethods(protocol, getCatalog, signingKey) {
|
|
|
6141
6434
|
const optionsDict = decodeOptionsBatch(innerParams.options);
|
|
6142
6435
|
const result = await cat.attach(innerParams.name, optionsDict, innerParams.data_version_spec ?? null, innerParams.implementation_version ?? null);
|
|
6143
6436
|
const sealedAttach = await sealAttach(toUint8Array(result.attach_opaque_data), ctx?.auth, signingKey);
|
|
6144
|
-
return wrapResult({
|
|
6437
|
+
return wrapResult(buildCatalogAttachResult({
|
|
6438
|
+
...result,
|
|
6145
6439
|
attach_opaque_data: sealedAttach,
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
catalog_version_frozen: result.catalog_version_frozen,
|
|
6149
|
-
catalog_version: result.catalog_version,
|
|
6150
|
-
attach_opaque_data_required: result.attach_opaque_data_required ?? true,
|
|
6151
|
-
default_schema: result.default_schema ?? "main",
|
|
6152
|
-
settings: result.settings ?? [],
|
|
6153
|
-
secret_types: result.secret_types ?? [],
|
|
6154
|
-
attach_catalogs: result.attach_catalogs ?? [],
|
|
6155
|
-
comment: result.comment ?? null,
|
|
6156
|
-
tags: result.tags ?? {},
|
|
6157
|
-
supports_column_statistics: result.supports_column_statistics ?? true,
|
|
6158
|
-
global_functions: result.global_functions ?? [],
|
|
6159
|
-
global_function_prefix: result.global_function_prefix ?? "",
|
|
6160
|
-
resolved_data_version: result.resolved_data_version ?? null,
|
|
6161
|
-
resolved_implementation_version: result.resolved_implementation_version ?? null
|
|
6162
|
-
}, CatalogAttachResultSchema);
|
|
6440
|
+
supports_column_statistics: result.supports_column_statistics ?? true
|
|
6441
|
+
}), CatalogAttachResultSchema);
|
|
6163
6442
|
}
|
|
6164
6443
|
});
|
|
6165
6444
|
catalogUnary(protocol, signingKey, "catalog_detach", {
|
|
@@ -6240,6 +6519,14 @@ function registerCatalogAdminMethods(protocol, getCatalog, signingKey) {
|
|
|
6240
6519
|
}, CatalogSchemasResultSchema);
|
|
6241
6520
|
}
|
|
6242
6521
|
});
|
|
6522
|
+
catalogUnary(protocol, signingKey, "catalog_contents", {
|
|
6523
|
+
params: CatalogContentsParamsSchema,
|
|
6524
|
+
result: RESULT_BINARY_SCHEMA,
|
|
6525
|
+
handler: async (params) => {
|
|
6526
|
+
const ifNoneMatch = params.if_none_match == null ? null : String(params.if_none_match);
|
|
6527
|
+
return serveCatalogContents(getCatalog(), toUint8Array(params.attach_opaque_data), ifNoneMatch);
|
|
6528
|
+
}
|
|
6529
|
+
});
|
|
6243
6530
|
catalogUnary(protocol, signingKey, "catalog_copy_from_formats", {
|
|
6244
6531
|
params: CatalogCopyFromFormatsParamsSchema,
|
|
6245
6532
|
result: RESULT_BINARY_SCHEMA,
|
|
@@ -6534,7 +6821,7 @@ function registerCatalogMacroMethods(protocol, getCatalog, signingKey) {
|
|
|
6534
6821
|
result: emptyResultSchema,
|
|
6535
6822
|
handler: async (params) => {
|
|
6536
6823
|
const cat = getCatalog();
|
|
6537
|
-
const innerParams =
|
|
6824
|
+
const innerParams = params;
|
|
6538
6825
|
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);
|
|
6539
6826
|
return {};
|
|
6540
6827
|
}
|
|
@@ -6600,7 +6887,7 @@ function registerCatalogMethods(protocol, catalog, _catalogName, signingKey) {
|
|
|
6600
6887
|
// src/protocol/dispatch.ts
|
|
6601
6888
|
var VGI_PROTOCOL_NAME = "vgi.v2";
|
|
6602
6889
|
function buildVgiProtocol(config) {
|
|
6603
|
-
const protocol = new Protocol(VGI_PROTOCOL_NAME, { protocolVersion: "2.
|
|
6890
|
+
const protocol = new Protocol(VGI_PROTOCOL_NAME, { protocolVersion: "2.1.0" });
|
|
6604
6891
|
registerFunctionMethods(protocol, {
|
|
6605
6892
|
registry: config.registry,
|
|
6606
6893
|
signingKey: config.signingKey,
|
|
@@ -6715,6 +7002,93 @@ function createLandingRoutes(info) {
|
|
|
6715
7002
|
};
|
|
6716
7003
|
}
|
|
6717
7004
|
|
|
7005
|
+
// src/rpc-server.ts
|
|
7006
|
+
import {
|
|
7007
|
+
IdentityImpl,
|
|
7008
|
+
VgiRpcServer
|
|
7009
|
+
} from "@query-farm/vgi-rpc";
|
|
7010
|
+
var TRANSPORTS = new Set(["pipe", "unix", "tcp", "iroh", "stream", "http"]);
|
|
7011
|
+
var IDENTITY_TRANSPORTS = new Set(["http"]);
|
|
7012
|
+
var RESERVED_PREFIX = "vgi_rpc.";
|
|
7013
|
+
var INTROSPECT_PRINCIPALS_ENV = "VGI_INTROSPECT_PRINCIPALS";
|
|
7014
|
+
function buildRpcServer(primary, hosting, options) {
|
|
7015
|
+
if (!TRANSPORTS.has(options.transport)) {
|
|
7016
|
+
throw new Error(`Unknown transport ${JSON.stringify(options.transport)}; expected one of ${[...TRANSPORTS].join(", ")}.`);
|
|
7017
|
+
}
|
|
7018
|
+
const protocols = validatedHostedProtocols(hosting, primary);
|
|
7019
|
+
const identity = IDENTITY_TRANSPORTS.has(options.transport) ? buildIdentity(hosting, options.env) : undefined;
|
|
7020
|
+
return new VgiRpcServer(primary, {
|
|
7021
|
+
serverId: options.serverId,
|
|
7022
|
+
protocols,
|
|
7023
|
+
identity
|
|
7024
|
+
});
|
|
7025
|
+
}
|
|
7026
|
+
function validatedHostedProtocols(hosting, primary) {
|
|
7027
|
+
if (hosting.hostedProtocols === undefined)
|
|
7028
|
+
return [];
|
|
7029
|
+
const owner = "hostedProtocols()";
|
|
7030
|
+
if (typeof hosting.hostedProtocols !== "function") {
|
|
7031
|
+
throw new TypeError(`${owner} must be a function returning vgi-rpc Protocols, got ${typeof hosting.hostedProtocols}.`);
|
|
7032
|
+
}
|
|
7033
|
+
const raw = hosting.hostedProtocols();
|
|
7034
|
+
if (raw == null || typeof raw[Symbol.iterator] !== "function" || typeof raw === "string") {
|
|
7035
|
+
throw new TypeError(`${owner} must return an iterable of vgi-rpc Protocols, got ${String(raw)}.`);
|
|
7036
|
+
}
|
|
7037
|
+
const seen = new Set;
|
|
7038
|
+
const out = [];
|
|
7039
|
+
let index = 0;
|
|
7040
|
+
for (const proto of raw) {
|
|
7041
|
+
const p = proto;
|
|
7042
|
+
if (p == null || typeof p.name !== "string" || typeof p.getMethod !== "function") {
|
|
7043
|
+
throw new TypeError(`${owner} entry ${index} must be a vgi-rpc Protocol, got ${String(proto)}.`);
|
|
7044
|
+
}
|
|
7045
|
+
const name = p.name;
|
|
7046
|
+
if (name.startsWith(RESERVED_PREFIX)) {
|
|
7047
|
+
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.");
|
|
7048
|
+
}
|
|
7049
|
+
if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name)) {
|
|
7050
|
+
throw new Error(`${owner} entry ${index}: protocol name '${name}' is not an identifier, optionally dot-qualified ` + "(e.g. 'acme.Reports.v1').");
|
|
7051
|
+
}
|
|
7052
|
+
if (name === primary.name) {
|
|
7053
|
+
throw new Error(`${owner} entry ${index} is named '${name}', the worker's own protocol. Give it a distinct name.`);
|
|
7054
|
+
}
|
|
7055
|
+
if (seen.has(name)) {
|
|
7056
|
+
throw new Error(`${owner} lists protocol name '${name}' twice. The name is the routing key, so each hosted protocol ` + "needs a distinct name.");
|
|
7057
|
+
}
|
|
7058
|
+
seen.add(name);
|
|
7059
|
+
out.push(proto);
|
|
7060
|
+
index++;
|
|
7061
|
+
}
|
|
7062
|
+
return out;
|
|
7063
|
+
}
|
|
7064
|
+
function buildIdentity(hosting, env) {
|
|
7065
|
+
const { resolveToken, mintGrant } = hosting;
|
|
7066
|
+
if (!resolveToken && !mintGrant)
|
|
7067
|
+
return;
|
|
7068
|
+
return new IdentityImpl({
|
|
7069
|
+
resolveToken,
|
|
7070
|
+
mintGrant,
|
|
7071
|
+
introspectPrincipals: resolveToken ? resolveIntrospectPrincipals(hosting.introspectPrincipals, env) : undefined,
|
|
7072
|
+
maxAuthAge: hosting.maxAuthAge
|
|
7073
|
+
});
|
|
7074
|
+
}
|
|
7075
|
+
function resolveIntrospectPrincipals(explicit, env) {
|
|
7076
|
+
let principals;
|
|
7077
|
+
if (explicit !== undefined) {
|
|
7078
|
+
principals = [...explicit].map((p) => p.trim()).filter((p) => p !== "");
|
|
7079
|
+
} else {
|
|
7080
|
+
const source = env ?? globalThis.process?.env;
|
|
7081
|
+
const raw = source?.[INTROSPECT_PRINCIPALS_ENV] ?? "";
|
|
7082
|
+
principals = raw.split(",").map((p) => p.trim()).filter((p) => p !== "");
|
|
7083
|
+
}
|
|
7084
|
+
if (principals.length === 0) {
|
|
7085
|
+
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.
|
|
7086
|
+
|
|
7087
|
+
` + "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.");
|
|
7088
|
+
}
|
|
7089
|
+
return principals;
|
|
7090
|
+
}
|
|
7091
|
+
|
|
6718
7092
|
// src/http/fetch.ts
|
|
6719
7093
|
var requestAuthStorage;
|
|
6720
7094
|
var requestAuthStoragePending;
|
|
@@ -6753,7 +7127,8 @@ function createVgiFetch(opts) {
|
|
|
6753
7127
|
signingKey: opts.signingKey,
|
|
6754
7128
|
...opts.protocol
|
|
6755
7129
|
});
|
|
6756
|
-
const
|
|
7130
|
+
const server = buildRpcServer(protocol, opts, { transport: "http", serverId });
|
|
7131
|
+
const handler = createHttpHandler(server, {
|
|
6757
7132
|
prefix,
|
|
6758
7133
|
serverId,
|
|
6759
7134
|
tokenKey: opts.signingKey,
|
|
@@ -6855,7 +7230,12 @@ function createVgiWorkerFetch(opts) {
|
|
|
6855
7230
|
authenticate: opts.authenticate,
|
|
6856
7231
|
peerIdentityProviders: bridge ? [irohForwardedHeaderIdentityProvider({ issuer: bridge.issuer, trustedProxyAddresses })] : undefined,
|
|
6857
7232
|
peerAuthenticationPolicy: bridge ? bridge.authenticate === false ? observePeerIdentity : peerIdentityPrimary("iroh") : undefined,
|
|
6858
|
-
peerResolutionContext: bridge?.peerResolutionContext
|
|
7233
|
+
peerResolutionContext: bridge?.peerResolutionContext,
|
|
7234
|
+
hostedProtocols: opts.hostedProtocols,
|
|
7235
|
+
resolveToken: opts.resolveToken,
|
|
7236
|
+
mintGrant: opts.mintGrant,
|
|
7237
|
+
introspectPrincipals: opts.introspectPrincipals,
|
|
7238
|
+
maxAuthAge: opts.maxAuthAge
|
|
6859
7239
|
});
|
|
6860
7240
|
}
|
|
6861
7241
|
function serveVgiWorker(opts) {
|
|
@@ -6903,4 +7283,4 @@ export {
|
|
|
6903
7283
|
serveVgiWorker
|
|
6904
7284
|
};
|
|
6905
7285
|
|
|
6906
|
-
//# debugId=
|
|
7286
|
+
//# debugId=1342AF43ED836A9764756E2164756E21
|