@query-farm/vgi 0.14.0 → 0.17.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 +53 -0
- package/dist/cache-control.d.ts +90 -0
- package/dist/client-entry.js +3862 -1
- package/dist/client-entry.js.map +34 -3
- package/dist/functions/table.d.ts +12 -0
- package/dist/http/fetch.d.ts +35 -0
- package/dist/index.core.d.ts +1 -0
- package/dist/index.js +217 -2
- package/dist/index.js.map +9 -7
- package/dist/serve-entry.d.ts +84 -0
- package/dist/serve-entry.js +6428 -0
- package/dist/serve-entry.js.map +62 -0
- package/dist/worker-cf-entry.d.ts +4 -22
- package/dist/worker-cf-entry.js +451 -24
- package/dist/worker-cf-entry.js.map +9 -6
- package/package.json +18 -6
- package/src/cache-control.ts +133 -0
- package/src/functions/table.ts +25 -1
- package/src/http/describe-json.ts +6 -1
- package/src/http/fetch.ts +80 -0
- package/src/index.core.ts +21 -0
- package/src/serve-entry.ts +233 -0
- package/src/worker-cf-entry.ts +7 -51
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
/** Wire-protocol config (registry + catalogInterface). */
|
|
4
|
-
protocol: Omit<ProtocolConfig, "recoverExchangeState">;
|
|
5
|
-
/** HMAC key for state-token signing. Pass a stable, secret 32-byte key
|
|
6
|
-
* (e.g. derived from a Wrangler secret). Required because Workers don't
|
|
7
|
-
* preserve in-memory state across requests/instances. */
|
|
8
|
-
signingKey: Uint8Array;
|
|
9
|
-
/** State-token TTL in seconds (default 3600). */
|
|
10
|
-
tokenTtl?: number;
|
|
11
|
-
/** URL path prefix for VGI requests (default "/vgi"). */
|
|
12
|
-
prefix?: string;
|
|
13
|
-
/** Server ID for state-token attribution (default "vgi-cf"). */
|
|
14
|
-
serverId?: string;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Build a fetch handler suitable for `export default { fetch }` in a CF
|
|
18
|
-
* Worker module. The returned handler is async-safe across Workers'
|
|
19
|
-
* isolate-per-request execution model — all state round-trips through the
|
|
20
|
-
* signed state token created here.
|
|
21
|
-
*/
|
|
22
|
-
export declare function createVgiFetch(opts: VgiFetchOptions): (req: Request) => Promise<Response>;
|
|
1
|
+
export { createVgiFetch } from "./http/fetch.js";
|
|
2
|
+
export type { VgiFetchOptions } from "./http/fetch.js";
|
|
23
3
|
export { defineScalarFunction, defineTableFunction, defineAggregate, defineTableInOutFunction, FunctionRegistry, ReadOnlyCatalogInterface, CompositeCatalogInterface, CatalogInterface, Arguments, FunctionType, serializeAttachOptionSpec, serializeAttachOptionSpecs, serializeColumnStatistics, BindResultSchema, ScanFunctionResultSchema, } from "./index.core.js";
|
|
24
4
|
export type { AttachOptionSpec, ColumnStatistics, CatalogAttachResult, CatalogDescriptor, CatalogInfo, TableInfo, AttachOpaqueData, TransactionOpaqueData, SchemaInfo, VgiFunction, TableProcessParams, } from "./index.core.js";
|
|
25
5
|
export type { ProtocolConfig } from "./protocol/dispatch.js";
|
|
6
|
+
export { createLandingDescribe } from "./http/describe-json.js";
|
|
7
|
+
export type { LandingDescribeProvider, WorkerDescribeInfo } from "./http/describe-json.js";
|
|
26
8
|
export { TypeId, isNull, isInt, isFloat, isBinary, isUtf8, isBool, isDecimal, isDate, isTime, isTimestamp, isInterval, isList, isStruct, isUnion, isFixedSizeBinary, isFixedSizeList, isMap, isDuration, isDictionary, isBatch, backend, schema, field, nullType, bool, int, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float16, float32, float64, utf8, binary, fixedSizeBinary, decimal, decimal128, decimal256, date, dateDay, dateMillisecond, time, timeSecond, timeMillisecond, timeMicrosecond, timeNanosecond, timestamp, duration, interval, list, fixedSizeList, struct, map, dictionary, union, sparseUnion, denseUnion, TimeUnit, DateUnit, IntervalUnit, UnionMode, emptyBatch, batchFromRows, batchFromColumns, columnFromArray, iterRows, batchToScalarDict, batchToSecretDict, safeNumber, decodeDictValue, filterBatch, projectSchema, projectBatch, serializeSchema, deserializeSchema, serializeBatch, deserializeBatch, buildStatisticsBatch, } from "./arrow/index.js";
|
|
27
9
|
export type { VgiTypeId, VgiDataType, VgiField, VgiSchema, VgiColumn, VgiColumnData, VgiBatch, VgiBackendInfo, } from "./arrow/index.js";
|
|
28
10
|
export { arrowStateSerializer, EXCHANGE_STATE_SCHEMA } from "./protocol/state-serializer.js";
|
package/dist/worker-cf-entry.js
CHANGED
|
@@ -2543,7 +2543,7 @@ var init_storage = __esm(() => {
|
|
|
2543
2543
|
});
|
|
2544
2544
|
});
|
|
2545
2545
|
|
|
2546
|
-
// src/
|
|
2546
|
+
// src/http/fetch.ts
|
|
2547
2547
|
import { createHttpHandler, unpackStateToken } from "@query-farm/vgi-rpc";
|
|
2548
2548
|
|
|
2549
2549
|
// src/protocol/state-serializer.ts
|
|
@@ -7182,6 +7182,32 @@ function buildVgiProtocol(config) {
|
|
|
7182
7182
|
return protocol;
|
|
7183
7183
|
}
|
|
7184
7184
|
|
|
7185
|
+
// src/http/fetch.ts
|
|
7186
|
+
function createVgiFetch(opts) {
|
|
7187
|
+
const tokenTtl = opts.tokenTtl ?? 3600;
|
|
7188
|
+
const prefix = opts.prefix ?? "/vgi";
|
|
7189
|
+
const serverId = opts.serverId ?? "vgi-cf";
|
|
7190
|
+
const protocol = buildVgiProtocol({
|
|
7191
|
+
signingKey: opts.signingKey,
|
|
7192
|
+
...opts.protocol,
|
|
7193
|
+
recoverExchangeState: async (opaqueData) => {
|
|
7194
|
+
const tokenString = new TextDecoder().decode(opaqueData);
|
|
7195
|
+
const unpacked = await unpackStateToken(tokenString, opts.signingKey, tokenTtl, undefined);
|
|
7196
|
+
return arrowStateSerializer.deserialize(unpacked.stateBytes);
|
|
7197
|
+
}
|
|
7198
|
+
});
|
|
7199
|
+
const handler = createHttpHandler(protocol, {
|
|
7200
|
+
prefix,
|
|
7201
|
+
serverId,
|
|
7202
|
+
tokenKey: opts.signingKey,
|
|
7203
|
+
tokenTtl,
|
|
7204
|
+
stateSerializer: arrowStateSerializer,
|
|
7205
|
+
corsOrigins: opts.corsOrigins,
|
|
7206
|
+
repositoryUrl: opts.repositoryUrl,
|
|
7207
|
+
landingDescribe: opts.landingDescribe
|
|
7208
|
+
});
|
|
7209
|
+
return async (req) => handler(req);
|
|
7210
|
+
}
|
|
7185
7211
|
// src/functions/scalar.ts
|
|
7186
7212
|
init_arrow();
|
|
7187
7213
|
function defineScalarFunction(config) {
|
|
@@ -7340,6 +7366,12 @@ function defineScalarFunction(config) {
|
|
|
7340
7366
|
init_arrow();
|
|
7341
7367
|
init_registry();
|
|
7342
7368
|
init_storage();
|
|
7369
|
+
|
|
7370
|
+
// src/cache-control.ts
|
|
7371
|
+
var CACHE_IF_NONE_MATCH_KEY = "vgi.cache.if_none_match";
|
|
7372
|
+
var CACHE_IF_MODIFIED_SINCE_KEY = "vgi.cache.if_modified_since";
|
|
7373
|
+
|
|
7374
|
+
// src/functions/table.ts
|
|
7343
7375
|
function base64Decode(s) {
|
|
7344
7376
|
const bin = globalThis.atob ? globalThis.atob(s) : Buffer.from(s, "base64").toString("binary");
|
|
7345
7377
|
const out = new Uint8Array(bin.length);
|
|
@@ -7538,6 +7570,12 @@ function defineTableFunction(config) {
|
|
|
7538
7570
|
onTick: (pState, tickMetadata) => {
|
|
7539
7571
|
if (!tickMetadata)
|
|
7540
7572
|
return;
|
|
7573
|
+
const ifNoneMatch = tickMetadata.get(CACHE_IF_NONE_MATCH_KEY);
|
|
7574
|
+
const ifModifiedSince = tickMetadata.get(CACHE_IF_MODIFIED_SINCE_KEY);
|
|
7575
|
+
if (ifNoneMatch !== undefined)
|
|
7576
|
+
pState.processParams.ifNoneMatch = ifNoneMatch;
|
|
7577
|
+
if (ifModifiedSince !== undefined)
|
|
7578
|
+
pState.processParams.ifModifiedSince = ifModifiedSince;
|
|
7541
7579
|
const encoded = tickMetadata.get("vgi_pushdown_filters");
|
|
7542
7580
|
if (!encoded)
|
|
7543
7581
|
return;
|
|
@@ -8810,31 +8848,419 @@ function serializeAttachOptionSpec(spec) {
|
|
|
8810
8848
|
function serializeAttachOptionSpecs(specs) {
|
|
8811
8849
|
return Array.from(specs, serializeAttachOptionSpec);
|
|
8812
8850
|
}
|
|
8813
|
-
// src/
|
|
8851
|
+
// src/http/describe-json.ts
|
|
8814
8852
|
init_arrow();
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8853
|
+
var LANDING_SCHEMA_VERSION2 = 1;
|
|
8854
|
+
var CUPOLA_BASE2 = "https://cupola.query-farm.services";
|
|
8855
|
+
var STRING_TAGS = {
|
|
8856
|
+
title: "vgi.title",
|
|
8857
|
+
doc_md: "vgi.doc_md",
|
|
8858
|
+
source_url: "vgi.source_url",
|
|
8859
|
+
license: "vgi.license",
|
|
8860
|
+
author: "vgi.author",
|
|
8861
|
+
copyright: "vgi.copyright",
|
|
8862
|
+
support_contact: "vgi.support_contact",
|
|
8863
|
+
support_policy_url: "vgi.support_policy_url"
|
|
8864
|
+
};
|
|
8865
|
+
var KEYWORDS_TAG = "vgi.keywords";
|
|
8866
|
+
function typeToString(type) {
|
|
8867
|
+
if (isNull(type))
|
|
8868
|
+
return "NULL";
|
|
8869
|
+
if (isUtf8(type))
|
|
8870
|
+
return "VARCHAR";
|
|
8871
|
+
if (isBinary(type))
|
|
8872
|
+
return "BLOB";
|
|
8873
|
+
if (isBool(type))
|
|
8874
|
+
return "BOOLEAN";
|
|
8875
|
+
if (isInt(type)) {
|
|
8876
|
+
const bw = type.bitWidth ?? 32;
|
|
8877
|
+
return bw === 64 ? "BIGINT" : "INTEGER";
|
|
8878
|
+
}
|
|
8879
|
+
if (isFloat(type)) {
|
|
8880
|
+
const precision = type.precision ?? 2;
|
|
8881
|
+
return precision === 1 ? "FLOAT" : "DOUBLE";
|
|
8882
|
+
}
|
|
8883
|
+
const s = type.toString?.();
|
|
8884
|
+
return s ?? String(type.typeId);
|
|
8885
|
+
}
|
|
8886
|
+
function arrowTypeString(type) {
|
|
8887
|
+
if (isNull(type))
|
|
8888
|
+
return "null";
|
|
8889
|
+
if (isBool(type))
|
|
8890
|
+
return "bool";
|
|
8891
|
+
if (isUtf8(type))
|
|
8892
|
+
return "string";
|
|
8893
|
+
if (isBinary(type))
|
|
8894
|
+
return "binary";
|
|
8895
|
+
if (isInt(type)) {
|
|
8896
|
+
const bw = type.bitWidth ?? 32;
|
|
8897
|
+
const signed = type.isSigned ?? type.signed ?? true;
|
|
8898
|
+
return `${signed ? "" : "u"}int${bw}`;
|
|
8899
|
+
}
|
|
8900
|
+
if (isFloat(type)) {
|
|
8901
|
+
const precision = type.precision ?? 2;
|
|
8902
|
+
return precision === 0 ? "halffloat" : precision === 1 ? "float" : "double";
|
|
8903
|
+
}
|
|
8904
|
+
const s = type.toString?.();
|
|
8905
|
+
return (s ?? String(type.typeId)).toLowerCase();
|
|
8906
|
+
}
|
|
8907
|
+
function fieldMeta(field4, key) {
|
|
8908
|
+
return field4.metadata.get(key);
|
|
8909
|
+
}
|
|
8910
|
+
function fieldToColumn(field4) {
|
|
8911
|
+
const col = { name: field4.name, type: typeToString(field4.type) };
|
|
8912
|
+
const comment = fieldMeta(field4, "comment") ?? fieldMeta(field4, VGI_DOC_KEY);
|
|
8913
|
+
if (comment)
|
|
8914
|
+
col.comment = comment;
|
|
8915
|
+
return col;
|
|
8916
|
+
}
|
|
8917
|
+
function readSchemaSafe(bytes2) {
|
|
8918
|
+
if (!bytes2 || bytes2.length === 0)
|
|
8919
|
+
return null;
|
|
8920
|
+
try {
|
|
8921
|
+
return deserializeSchema(bytes2);
|
|
8922
|
+
} catch {
|
|
8923
|
+
return null;
|
|
8924
|
+
}
|
|
8925
|
+
}
|
|
8926
|
+
function functionDisplayType(fn) {
|
|
8927
|
+
const t = String(fn.function_type).toUpperCase();
|
|
8928
|
+
if (t === "SCALAR")
|
|
8929
|
+
return "scalar";
|
|
8930
|
+
if (t === "AGGREGATE")
|
|
8931
|
+
return "aggregate";
|
|
8932
|
+
if (fn.has_finalize)
|
|
8933
|
+
return "table_in_out";
|
|
8934
|
+
return "table";
|
|
8935
|
+
}
|
|
8936
|
+
function functionReturns(fn) {
|
|
8937
|
+
const schema4 = readSchemaSafe(fn.output_schema);
|
|
8938
|
+
if (schema4 === null || schema4.fields.length === 0)
|
|
8939
|
+
return;
|
|
8940
|
+
const t = String(fn.function_type).toUpperCase();
|
|
8941
|
+
if (t === "SCALAR" || t === "AGGREGATE") {
|
|
8942
|
+
return typeToString(schema4.fields[0].type);
|
|
8943
|
+
}
|
|
8944
|
+
const cols = schema4.fields.map((f) => `${f.name} ${typeToString(f.type)}`).join(", ");
|
|
8945
|
+
return `TABLE(${cols})`;
|
|
8946
|
+
}
|
|
8947
|
+
function functionArgs(fn) {
|
|
8948
|
+
const schema4 = readSchemaSafe(fn.arguments);
|
|
8949
|
+
if (schema4 === null)
|
|
8950
|
+
return [];
|
|
8951
|
+
const args = [];
|
|
8952
|
+
for (const field4 of schema4.fields) {
|
|
8953
|
+
if (fieldMeta(field4, VGI_TYPE_KEY) === VGI_TYPE_TABLE)
|
|
8954
|
+
continue;
|
|
8955
|
+
const arg = { name: field4.name, type: typeToString(field4.type) };
|
|
8956
|
+
if (fieldMeta(field4, VGI_ARG_KEY) === VGI_ARG_NAMED)
|
|
8957
|
+
arg.named = true;
|
|
8958
|
+
const doc = fieldMeta(field4, VGI_DOC_KEY);
|
|
8959
|
+
if (doc)
|
|
8960
|
+
arg.desc = doc;
|
|
8961
|
+
const rawDefault = fieldMeta(field4, VGI_DEFAULT_KEY);
|
|
8962
|
+
if (rawDefault !== undefined) {
|
|
8963
|
+
try {
|
|
8964
|
+
arg.default = JSON.stringify(JSON.parse(rawDefault));
|
|
8965
|
+
} catch {
|
|
8966
|
+
arg.default = rawDefault;
|
|
8967
|
+
}
|
|
8827
8968
|
}
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
serverId,
|
|
8832
|
-
tokenKey: opts.signingKey,
|
|
8833
|
-
tokenTtl,
|
|
8834
|
-
stateSerializer: arrowStateSerializer
|
|
8835
|
-
});
|
|
8836
|
-
return async (req) => handler(req);
|
|
8969
|
+
args.push(arg);
|
|
8970
|
+
}
|
|
8971
|
+
return args;
|
|
8837
8972
|
}
|
|
8973
|
+
function macroDisplayType(m) {
|
|
8974
|
+
return String(m.macro_type).toUpperCase() === "SCALAR" ? "scalar" : "table";
|
|
8975
|
+
}
|
|
8976
|
+
function macroDefaultJson(value) {
|
|
8977
|
+
if (typeof value === "bigint")
|
|
8978
|
+
return value.toString();
|
|
8979
|
+
try {
|
|
8980
|
+
return JSON.stringify(value);
|
|
8981
|
+
} catch {
|
|
8982
|
+
return String(value);
|
|
8983
|
+
}
|
|
8984
|
+
}
|
|
8985
|
+
function macroArgs(m) {
|
|
8986
|
+
const defaults = new Map;
|
|
8987
|
+
const defBytes = m.parameter_default_values;
|
|
8988
|
+
if (defBytes && defBytes.length > 0) {
|
|
8989
|
+
try {
|
|
8990
|
+
const batch = deserializeBatch(defBytes);
|
|
8991
|
+
for (const field4 of batch.schema.fields) {
|
|
8992
|
+
try {
|
|
8993
|
+
defaults.set(field4.name, batch.getChild(field4.name)?.get(0));
|
|
8994
|
+
} catch {}
|
|
8995
|
+
}
|
|
8996
|
+
} catch {}
|
|
8997
|
+
}
|
|
8998
|
+
const schema4 = readSchemaSafe(m.arguments_schema);
|
|
8999
|
+
const fields = schema4 ? schema4.fields : null;
|
|
9000
|
+
const fieldByName = new Map;
|
|
9001
|
+
if (fields)
|
|
9002
|
+
for (const f of fields)
|
|
9003
|
+
fieldByName.set(f.name, f);
|
|
9004
|
+
const names = fields ? fields.map((f) => f.name) : m.parameters;
|
|
9005
|
+
const args = [];
|
|
9006
|
+
for (const name of names) {
|
|
9007
|
+
const field4 = fieldByName.get(name);
|
|
9008
|
+
const arg = field4 !== undefined && !isNull(field4.type) ? { name, type: arrowTypeString(field4.type) } : { name, type: "ANY" };
|
|
9009
|
+
const doc = field4 !== undefined ? fieldMeta(field4, VGI_DOC_KEY) : undefined;
|
|
9010
|
+
if (doc)
|
|
9011
|
+
arg.desc = doc;
|
|
9012
|
+
if (defaults.has(name)) {
|
|
9013
|
+
arg.named = true;
|
|
9014
|
+
arg.default = macroDefaultJson(defaults.get(name));
|
|
9015
|
+
}
|
|
9016
|
+
args.push(arg);
|
|
9017
|
+
}
|
|
9018
|
+
return args;
|
|
9019
|
+
}
|
|
9020
|
+
function macroToObject(m) {
|
|
9021
|
+
return {
|
|
9022
|
+
name: m.name,
|
|
9023
|
+
type: macroDisplayType(m),
|
|
9024
|
+
doc: m.comment ?? "",
|
|
9025
|
+
args: macroArgs(m)
|
|
9026
|
+
};
|
|
9027
|
+
}
|
|
9028
|
+
async function schemaContents(iface, aod, name, kind) {
|
|
9029
|
+
try {
|
|
9030
|
+
if (kind === "TABLE") {
|
|
9031
|
+
return await iface.schemaContentsTables(aod, name);
|
|
9032
|
+
}
|
|
9033
|
+
return await iface.schemaContentsViews(aod, name);
|
|
9034
|
+
} catch {
|
|
9035
|
+
return [];
|
|
9036
|
+
}
|
|
9037
|
+
}
|
|
9038
|
+
async function schemaFunctions(iface, aod, name) {
|
|
9039
|
+
const out = [];
|
|
9040
|
+
for (const kind of ["SCALAR_FUNCTION", "TABLE_FUNCTION", "AGGREGATE_FUNCTION"]) {
|
|
9041
|
+
try {
|
|
9042
|
+
out.push(...await iface.schemaContentsFunctions(aod, name, kind));
|
|
9043
|
+
} catch {}
|
|
9044
|
+
}
|
|
9045
|
+
return out;
|
|
9046
|
+
}
|
|
9047
|
+
async function schemaMacros(iface, aod, name) {
|
|
9048
|
+
const out = [];
|
|
9049
|
+
for (const kind of ["SCALAR_MACRO", "TABLE_MACRO"]) {
|
|
9050
|
+
try {
|
|
9051
|
+
out.push(...await iface.schemaContentsMacros(aod, name, kind));
|
|
9052
|
+
} catch {}
|
|
9053
|
+
}
|
|
9054
|
+
return out;
|
|
9055
|
+
}
|
|
9056
|
+
async function buildSchemas(iface, aod) {
|
|
9057
|
+
let schemaInfos;
|
|
9058
|
+
try {
|
|
9059
|
+
schemaInfos = await iface.schemas(aod);
|
|
9060
|
+
} catch {
|
|
9061
|
+
return { schemas: [], counts: { schemas: 0, tables: 0, views: 0, functions: 0 } };
|
|
9062
|
+
}
|
|
9063
|
+
const schemas = [];
|
|
9064
|
+
const counts = { schemas: 0, tables: 0, views: 0, functions: 0 };
|
|
9065
|
+
for (const si of schemaInfos) {
|
|
9066
|
+
const tablesRaw = await schemaContents(iface, aod, si.name, "TABLE");
|
|
9067
|
+
const viewsRaw = await schemaContents(iface, aod, si.name, "VIEW");
|
|
9068
|
+
const funcsRaw = await schemaFunctions(iface, aod, si.name);
|
|
9069
|
+
const macrosRaw = await schemaMacros(iface, aod, si.name);
|
|
9070
|
+
const tables = tablesRaw.map((t) => {
|
|
9071
|
+
const schema4 = readSchemaSafe(t.columns);
|
|
9072
|
+
return { name: t.name, cols: schema4 ? schema4.fields.length : 0, comment: t.comment ?? "" };
|
|
9073
|
+
});
|
|
9074
|
+
const views = viewsRaw.map((v) => ({
|
|
9075
|
+
name: v.name,
|
|
9076
|
+
cols: Object.keys(v.column_comments ?? {}).length,
|
|
9077
|
+
comment: v.comment ?? "",
|
|
9078
|
+
def: v.definition
|
|
9079
|
+
}));
|
|
9080
|
+
const functions = funcsRaw.map((fn) => {
|
|
9081
|
+
const obj = {
|
|
9082
|
+
name: fn.name,
|
|
9083
|
+
type: functionDisplayType(fn),
|
|
9084
|
+
doc: fn.description ?? "",
|
|
9085
|
+
args: functionArgs(fn)
|
|
9086
|
+
};
|
|
9087
|
+
const ret = functionReturns(fn);
|
|
9088
|
+
if (ret)
|
|
9089
|
+
obj.returns = ret;
|
|
9090
|
+
return obj;
|
|
9091
|
+
});
|
|
9092
|
+
functions.push(...macrosRaw.map((m) => macroToObject(m)));
|
|
9093
|
+
functions.sort((a, b) => String(a.type).localeCompare(String(b.type)) || String(a.name).localeCompare(String(b.name)));
|
|
9094
|
+
const schemaObj = { name: si.name };
|
|
9095
|
+
if (si.comment)
|
|
9096
|
+
schemaObj.doc = si.comment;
|
|
9097
|
+
schemaObj.tables = tables;
|
|
9098
|
+
schemaObj.views = views;
|
|
9099
|
+
schemaObj.functions = functions;
|
|
9100
|
+
schemas.push(schemaObj);
|
|
9101
|
+
counts.schemas += 1;
|
|
9102
|
+
counts.tables += tables.length;
|
|
9103
|
+
counts.views += views.length;
|
|
9104
|
+
counts.functions += functions.length;
|
|
9105
|
+
}
|
|
9106
|
+
return { schemas, counts };
|
|
9107
|
+
}
|
|
9108
|
+
function catalogTags(result) {
|
|
9109
|
+
const tags = result?.tags;
|
|
9110
|
+
if (!tags)
|
|
9111
|
+
return {};
|
|
9112
|
+
const out = {};
|
|
9113
|
+
for (const [key, tag] of Object.entries(STRING_TAGS)) {
|
|
9114
|
+
const val = tags[tag];
|
|
9115
|
+
if (val)
|
|
9116
|
+
out[key] = val;
|
|
9117
|
+
}
|
|
9118
|
+
const kw = tags[KEYWORDS_TAG];
|
|
9119
|
+
if (kw) {
|
|
9120
|
+
try {
|
|
9121
|
+
const parsed = JSON.parse(kw);
|
|
9122
|
+
if (Array.isArray(parsed))
|
|
9123
|
+
out.keywords = parsed.map((k) => String(k));
|
|
9124
|
+
} catch {}
|
|
9125
|
+
}
|
|
9126
|
+
return out;
|
|
9127
|
+
}
|
|
9128
|
+
function decodeAttachOption(bytes2) {
|
|
9129
|
+
try {
|
|
9130
|
+
const batch = deserializeBatch(bytes2);
|
|
9131
|
+
if (batch.numRows === 0)
|
|
9132
|
+
return null;
|
|
9133
|
+
const name = String(batch.getChild("name")?.get(0) ?? "");
|
|
9134
|
+
const description = String(batch.getChild("description")?.get(0) ?? "");
|
|
9135
|
+
const typeBytes = batch.getChild("type")?.get(0);
|
|
9136
|
+
let type = "";
|
|
9137
|
+
const typeSchema = readSchemaSafe(typeBytes ?? null);
|
|
9138
|
+
if (typeSchema && typeSchema.fields.length > 0)
|
|
9139
|
+
type = typeToString(typeSchema.fields[0].type);
|
|
9140
|
+
let defaultStr = "";
|
|
9141
|
+
const defBytes = batch.getChild("default_value")?.get(0);
|
|
9142
|
+
if (defBytes) {
|
|
9143
|
+
try {
|
|
9144
|
+
const defBatch = deserializeBatch(defBytes);
|
|
9145
|
+
if (defBatch.numRows > 0) {
|
|
9146
|
+
const v = defBatch.getChild("value")?.get(0);
|
|
9147
|
+
defaultStr = v == null ? "" : String(v);
|
|
9148
|
+
}
|
|
9149
|
+
} catch {}
|
|
9150
|
+
}
|
|
9151
|
+
return { name, type, default: defaultStr, description };
|
|
9152
|
+
} catch {
|
|
9153
|
+
return null;
|
|
9154
|
+
}
|
|
9155
|
+
}
|
|
9156
|
+
async function attachCatalog(iface, name) {
|
|
9157
|
+
try {
|
|
9158
|
+
return await iface.attach(name, {}, null, null);
|
|
9159
|
+
} catch {
|
|
9160
|
+
return null;
|
|
9161
|
+
}
|
|
9162
|
+
}
|
|
9163
|
+
async function buildCatalog(iface, name, info) {
|
|
9164
|
+
const result = await attachCatalog(iface, name);
|
|
9165
|
+
const attachOptions = (info?.attach_option_specs ?? []).map((b) => decodeAttachOption(b)).filter((o) => o !== null);
|
|
9166
|
+
const dataVersions = (info?.releases ?? []).map((r) => r.summary ? { spec: r.version, label: r.summary } : { spec: r.version });
|
|
9167
|
+
let impl = info?.implementation_version ?? null;
|
|
9168
|
+
let dvs = info?.data_version_spec ?? null;
|
|
9169
|
+
if (result) {
|
|
9170
|
+
impl = result.resolved_implementation_version ?? impl;
|
|
9171
|
+
dvs = result.resolved_data_version ?? dvs;
|
|
9172
|
+
}
|
|
9173
|
+
let schemas = [];
|
|
9174
|
+
let counts = { schemas: 0, tables: 0, views: 0, functions: 0 };
|
|
9175
|
+
if (result) {
|
|
9176
|
+
const built = await buildSchemas(iface, result.attach_opaque_data);
|
|
9177
|
+
schemas = built.schemas;
|
|
9178
|
+
counts = built.counts;
|
|
9179
|
+
}
|
|
9180
|
+
return {
|
|
9181
|
+
name,
|
|
9182
|
+
implementation_version: impl,
|
|
9183
|
+
data_version_spec: dvs,
|
|
9184
|
+
data_versions: dataVersions,
|
|
9185
|
+
attach_options: attachOptions,
|
|
9186
|
+
tags: catalogTags(result),
|
|
9187
|
+
counts,
|
|
9188
|
+
schemas
|
|
9189
|
+
};
|
|
9190
|
+
}
|
|
9191
|
+
async function catalogInfoByName(iface) {
|
|
9192
|
+
const map4 = new Map;
|
|
9193
|
+
if (typeof iface.catalogsInfo === "function") {
|
|
9194
|
+
try {
|
|
9195
|
+
const infos = await iface.catalogsInfo();
|
|
9196
|
+
for (const info of infos)
|
|
9197
|
+
map4.set(info.name, info);
|
|
9198
|
+
} catch {}
|
|
9199
|
+
}
|
|
9200
|
+
return map4;
|
|
9201
|
+
}
|
|
9202
|
+
async function buildDescribeJson2(iface, worker, opts = {}) {
|
|
9203
|
+
const infos = await catalogInfoByName(iface);
|
|
9204
|
+
let names;
|
|
9205
|
+
try {
|
|
9206
|
+
names = iface.catalogs();
|
|
9207
|
+
} catch {
|
|
9208
|
+
names = [];
|
|
9209
|
+
}
|
|
9210
|
+
const catalogs = [];
|
|
9211
|
+
for (const name of names) {
|
|
9212
|
+
catalogs.push(await buildCatalog(iface, name, infos.get(name)));
|
|
9213
|
+
}
|
|
9214
|
+
return {
|
|
9215
|
+
landing_schema_version: LANDING_SCHEMA_VERSION2,
|
|
9216
|
+
worker: {
|
|
9217
|
+
name: worker.name,
|
|
9218
|
+
doc: worker.doc ?? "",
|
|
9219
|
+
version: worker.version ?? "unknown",
|
|
9220
|
+
lang: "typescript"
|
|
9221
|
+
},
|
|
9222
|
+
server_id: opts.serverId ?? "",
|
|
9223
|
+
oauth: opts.oauth ?? false,
|
|
9224
|
+
cupola_base: opts.cupolaBase ?? CUPOLA_BASE2,
|
|
9225
|
+
catalogs
|
|
9226
|
+
};
|
|
9227
|
+
}
|
|
9228
|
+
async function buildColumnsJson2(iface, catalog, schema4, table) {
|
|
9229
|
+
const result = await attachCatalog(iface, catalog);
|
|
9230
|
+
if (!result)
|
|
9231
|
+
return null;
|
|
9232
|
+
const aod = result.attach_opaque_data;
|
|
9233
|
+
const tables = await schemaContents(iface, aod, schema4, "TABLE");
|
|
9234
|
+
for (const t of tables) {
|
|
9235
|
+
if (t.name === table) {
|
|
9236
|
+
const arrow = readSchemaSafe(t.columns);
|
|
9237
|
+
return { columns: (arrow?.fields ?? []).map((f) => fieldToColumn(f)) };
|
|
9238
|
+
}
|
|
9239
|
+
}
|
|
9240
|
+
const views = await schemaContents(iface, aod, schema4, "VIEW");
|
|
9241
|
+
for (const v of views) {
|
|
9242
|
+
if (v.name === table) {
|
|
9243
|
+
return {
|
|
9244
|
+
columns: Object.entries(v.column_comments ?? {}).map(([name, comment]) => ({
|
|
9245
|
+
name,
|
|
9246
|
+
type: "",
|
|
9247
|
+
comment
|
|
9248
|
+
}))
|
|
9249
|
+
};
|
|
9250
|
+
}
|
|
9251
|
+
}
|
|
9252
|
+
return null;
|
|
9253
|
+
}
|
|
9254
|
+
function createLandingDescribe2(iface, worker, opts = {}) {
|
|
9255
|
+
return {
|
|
9256
|
+
describe: (ctx) => buildDescribeJson2(iface, worker, { ...ctx, cupolaBase: opts.cupolaBase }),
|
|
9257
|
+
columns: (catalog, schema4, table) => buildColumnsJson2(iface, catalog, schema4, table)
|
|
9258
|
+
};
|
|
9259
|
+
}
|
|
9260
|
+
|
|
9261
|
+
// src/worker-cf-entry.ts
|
|
9262
|
+
init_arrow();
|
|
9263
|
+
import { OutputCollector as OutputCollector2, AuthContext as AuthContext2 } from "@query-farm/vgi-rpc";
|
|
8838
9264
|
export {
|
|
8839
9265
|
utf82 as utf8,
|
|
8840
9266
|
union2 as union,
|
|
@@ -8914,6 +9340,7 @@ export {
|
|
|
8914
9340
|
dateDay2 as dateDay,
|
|
8915
9341
|
date2 as date,
|
|
8916
9342
|
createVgiFetch,
|
|
9343
|
+
createLandingDescribe2 as createLandingDescribe,
|
|
8917
9344
|
columnFromArray,
|
|
8918
9345
|
buildStatisticsBatch,
|
|
8919
9346
|
bool2 as bool,
|
|
@@ -8942,4 +9369,4 @@ export {
|
|
|
8942
9369
|
Arguments
|
|
8943
9370
|
};
|
|
8944
9371
|
|
|
8945
|
-
//# debugId=
|
|
9372
|
+
//# debugId=C67D053F70399BE264756E2164756E21
|