@query-farm/vgi 0.38.0 → 0.40.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.
@@ -30,7 +30,7 @@ export interface CopyToOption {
30
30
  * Optional allowed value set, validated worker-side at bind. Mirrors
31
31
  * vgi-python's `Arg(..., choices=[...])`.
32
32
  */
33
- choices?: unknown[];
33
+ choices?: readonly unknown[];
34
34
  /**
35
35
  * Optional inclusive lower bound for numeric options, validated worker-side at
36
36
  * bind. Mirrors vgi-python's `Arg(..., ge=...)`.
@@ -39,11 +39,11 @@ export type { ScalarComputeRow, ScalarOutputValue, ScalarComputeResult } from ".
39
39
  export { type FunctionStorage, type WorkerStateKey, FunctionStorageSqlite, BoundStorage, UnknownInvocationError, resolveStorageFromEnv, setStorage, storage as functionStorage, } from "./functions/storage.js";
40
40
  export { FunctionStorageCfDo, type FetchLike } from "./functions/storage-cf-do.js";
41
41
  export { VgiClient, VgiClientError } from "./client/client.js";
42
- export type { VgiClientOptions, TableFunctionOptions, ScalarFunctionOptions, TableInOutFunctionOptions, OnCreateConflict, CatalogFunctionType as ClientCatalogFunctionType, CatalogAttachOptions, AttachOptionValue, } from "./client/types.js";
42
+ export type { VgiClientOptions, TableFunctionOptions, ScalarFunctionOptions, TableInOutFunctionOptions, OnCreateConflict, CatalogFunctionType as ClientCatalogFunctionType, CatalogAttachOptions, AttachOptionValue, CatalogSnapshot, LoadCatalogOptions, } from "./client/types.js";
43
43
  export { str, bytes, int, int32, float, float32, bool, toSchema, OutputCollector, AuthContext } from "@query-farm/vgi-rpc";
44
44
  export { subprocessConnect, httpConnect, tcpConnect } from "@query-farm/vgi-rpc";
45
45
  export type { RpcClient, StreamSession, LogMessage } from "@query-farm/vgi-rpc";
46
- export { buildRpcServer, INTROSPECT_PRINCIPALS_ENV, type BuildRpcServerOptions, type HostingOptions, type ServerTransport, } from "./rpc-server.js";
47
- export { AuthUnavailableError, GrantRefusedError, IdentityUnavailableError, StatusError, } from "@query-farm/vgi-rpc";
46
+ export { buildRpcServer, grantKeysFromArgv, INTROSPECT_PRINCIPALS_ENV, type BuildRpcServerOptions, type HostingOptions, type ServerTransport, } from "./rpc-server.js";
47
+ export { AuthUnavailableError, GrantKeys, GrantRefusedError, IdentityUnavailableError, StatusError, } from "@query-farm/vgi-rpc";
48
48
  export type { GrantMinter, IssuedGrant, TokenIdentity, TokenResolver } from "@query-farm/vgi-rpc";
49
49
  export { normalizeSchemaPath, schemaPathDisplay, schemaPathKey, schemaPathsEqual, type SchemaPath } from "./schema-path.js";
package/dist/index.js CHANGED
@@ -7139,21 +7139,23 @@ function normalizeValue(raw, type) {
7139
7139
  return out;
7140
7140
  }
7141
7141
  if (isMap(type)) {
7142
+ const entries = type.children[0].type;
7143
+ const valueType = entries.children[1].type;
7142
7144
  const out = {};
7145
+ const put = (k, v) => {
7146
+ out[String(k)] = normalizeValue(v, valueType);
7147
+ };
7143
7148
  if (raw[Symbol.iterator]) {
7144
7149
  for (const entry of raw) {
7145
7150
  if (Array.isArray(entry)) {
7146
- out[String(entry[0])] = String(entry[1] ?? "");
7151
+ put(entry[0], entry[1]);
7147
7152
  } else if (entry && typeof entry === "object") {
7148
- const k = entry.key ?? entry[0];
7149
- const v = entry.value ?? entry[1];
7150
- out[String(k)] = v == null ? "" : String(v);
7153
+ put(entry.key ?? entry[0], entry.value ?? entry[1]);
7151
7154
  }
7152
7155
  }
7153
7156
  } else if (typeof raw === "object") {
7154
- for (const [k, v] of Object.entries(raw)) {
7155
- out[String(k)] = v == null ? "" : String(v);
7156
- }
7157
+ for (const [k, v] of Object.entries(raw))
7158
+ put(k, v);
7157
7159
  }
7158
7160
  return out;
7159
7161
  }
@@ -13226,6 +13228,84 @@ class VgiClient {
13226
13228
  schemas
13227
13229
  };
13228
13230
  }
13231
+ async loadCatalog(attach, opts) {
13232
+ const attachOpaqueData = attach.attach_opaque_data;
13233
+ const previous = opts?.previous ?? null;
13234
+ const useContents = attach.supports_catalog_contents === true && opts?.useCatalogContents !== false && opts?.transactionOpaqueData == null;
13235
+ if (!useContents) {
13236
+ return this._loadCatalogPerSchema(attachOpaqueData, opts?.transactionOpaqueData, null);
13237
+ }
13238
+ let fallbackError = null;
13239
+ const ifNoneMatch = previous?.etag ?? null;
13240
+ const knownVersion = previous?.catalog_version ?? 0;
13241
+ for (let attempt = 0;attempt < 2; attempt++) {
13242
+ let response;
13243
+ try {
13244
+ response = await this.catalogContents(attachOpaqueData, ifNoneMatch);
13245
+ } catch (err) {
13246
+ fallbackError = err instanceof Error ? err.message : String(err);
13247
+ break;
13248
+ }
13249
+ if (response.not_modified) {
13250
+ if (previous == null || ifNoneMatch == null) {
13251
+ fallbackError = "catalog_contents answered not_modified to an unconditional request";
13252
+ break;
13253
+ }
13254
+ return {
13255
+ ...previous,
13256
+ catalog_version: response.catalog_version !== 0 ? response.catalog_version : previous.catalog_version,
13257
+ etag: response.etag ?? ifNoneMatch,
13258
+ not_modified: true,
13259
+ fallback_error: null
13260
+ };
13261
+ }
13262
+ if (response.catalog_version !== 0 && knownVersion !== 0 && response.catalog_version < knownVersion) {
13263
+ fallbackError = `catalog_contents snapshot version ${response.catalog_version} is older than the known version ${knownVersion}`;
13264
+ continue;
13265
+ }
13266
+ return {
13267
+ catalog_version: response.catalog_version,
13268
+ etag: response.etag,
13269
+ source: "catalog_contents",
13270
+ not_modified: false,
13271
+ fallback_error: null,
13272
+ schemas: response.schemas
13273
+ };
13274
+ }
13275
+ return this._loadCatalogPerSchema(attachOpaqueData, undefined, fallbackError);
13276
+ }
13277
+ async _loadCatalogPerSchema(attachOpaqueData, transactionOpaqueData, fallbackError) {
13278
+ const schemas = await this.schemas(attachOpaqueData, transactionOpaqueData);
13279
+ const out = [];
13280
+ for (const schema of schemas) {
13281
+ const counts = schema.estimated_object_count ?? {};
13282
+ const path = schema.path;
13283
+ const has = (kind) => {
13284
+ const n = counts[kind];
13285
+ return n == null || Number(n) !== 0;
13286
+ };
13287
+ const t = transactionOpaqueData;
13288
+ out.push({
13289
+ schema,
13290
+ tables: has("table") ? await this.schemaContentsTables(attachOpaqueData, path, t) : [],
13291
+ views: has("view") ? await this.schemaContentsViews(attachOpaqueData, path, t) : [],
13292
+ scalar_functions: has("scalar_function") ? await this.schemaContentsFunctions(attachOpaqueData, path, "SCALAR_FUNCTION", t) : [],
13293
+ aggregate_functions: has("aggregate_function") ? await this.schemaContentsFunctions(attachOpaqueData, path, "AGGREGATE_FUNCTION", t) : [],
13294
+ table_functions: has("table_function") ? await this.schemaContentsFunctions(attachOpaqueData, path, "TABLE_FUNCTION", t) : [],
13295
+ scalar_macros: has("macro") ? await this.schemaContentsMacros(attachOpaqueData, path, "SCALAR_MACRO", t) : [],
13296
+ table_macros: has("macro") ? await this.schemaContentsMacros(attachOpaqueData, path, "TABLE_MACRO", t) : [],
13297
+ indexes: has("index") ? await this.schemaContentsIndexes(attachOpaqueData, path, t) : []
13298
+ });
13299
+ }
13300
+ return {
13301
+ catalog_version: null,
13302
+ etag: null,
13303
+ source: "per_schema",
13304
+ not_modified: false,
13305
+ fallback_error: fallbackError,
13306
+ schemas: out
13307
+ };
13308
+ }
13229
13309
  async catalogDetach(attachOpaqueData) {
13230
13310
  await this.rpc.call("catalog_detach", { attach_opaque_data: attachOpaqueData });
13231
13311
  }
@@ -13364,6 +13444,17 @@ class VgiClient {
13364
13444
  const inner = unwrapResult(result);
13365
13445
  return deserializeInfoList(inner.items, decodeFunctionInfo);
13366
13446
  }
13447
+ async schemaContentsIndexes(attachOpaqueData, path, transactionOpaqueData) {
13448
+ const result = await this.rpc.call("catalog_schema_contents_indexes", {
13449
+ attach_opaque_data: attachOpaqueData,
13450
+ path: normalizeSchemaPath(path),
13451
+ transaction_opaque_data: transactionOpaqueData ?? null
13452
+ });
13453
+ if (!result)
13454
+ return [];
13455
+ const inner = unwrapResult(result);
13456
+ return deserializeInfoList(inner.items, decodeIndexInfo);
13457
+ }
13367
13458
  async tableGet(attachOpaqueData, schemaPath, name, transactionOpaqueData) {
13368
13459
  const result = await this.rpc.call("catalog_table_get", {
13369
13460
  attach_opaque_data: attachOpaqueData,
@@ -13631,6 +13722,7 @@ import { subprocessConnect, httpConnect, tcpConnect } from "@query-farm/vgi-rpc"
13631
13722
 
13632
13723
  // src/rpc-server.ts
13633
13724
  import {
13725
+ GrantKeys,
13634
13726
  IdentityImpl,
13635
13727
  VgiRpcServer
13636
13728
  } from "@query-farm/vgi-rpc";
@@ -13647,7 +13739,8 @@ function buildRpcServer(primary, hosting, options) {
13647
13739
  return new VgiRpcServer(primary, {
13648
13740
  serverId: options.serverId,
13649
13741
  protocols,
13650
- identity
13742
+ identity,
13743
+ grantKeys: null
13651
13744
  });
13652
13745
  }
13653
13746
  function validatedHostedProtocols(hosting, primary) {
@@ -13690,11 +13783,13 @@ function validatedHostedProtocols(hosting, primary) {
13690
13783
  }
13691
13784
  function buildIdentity(hosting, env) {
13692
13785
  const { resolveToken, mintGrant } = hosting;
13693
- if (!resolveToken && !mintGrant)
13786
+ const grantKeys = hosting.grantKeys === undefined ? GrantKeys.fromEnv(env ?? processEnv()) : hosting.grantKeys;
13787
+ if (!resolveToken && !mintGrant && !grantKeys)
13694
13788
  return;
13695
13789
  return new IdentityImpl({
13696
13790
  resolveToken,
13697
13791
  mintGrant,
13792
+ grantKeys: grantKeys ?? undefined,
13698
13793
  introspectPrincipals: resolveToken ? resolveIntrospectPrincipals(hosting.introspectPrincipals, env) : undefined,
13699
13794
  maxAuthAge: hosting.maxAuthAge
13700
13795
  });
@@ -13715,10 +13810,31 @@ function resolveIntrospectPrincipals(explicit, env) {
13715
13810
  }
13716
13811
  return principals;
13717
13812
  }
13813
+ function processEnv() {
13814
+ return globalThis.process?.env;
13815
+ }
13816
+ function grantKeysFromArgv(argv, env = processEnv()) {
13817
+ const keys = [];
13818
+ for (let i = 0;i < argv.length; i++) {
13819
+ const a = argv[i];
13820
+ if (a === "--grant-key") {
13821
+ if (i + 1 >= argv.length)
13822
+ throw new Error("--grant-key requires a value");
13823
+ keys.push(argv[++i]);
13824
+ } else if (a.startsWith("--grant-key=")) {
13825
+ keys.push(a.slice("--grant-key=".length));
13826
+ }
13827
+ }
13828
+ if (keys.length === 0)
13829
+ return;
13830
+ const fromEnv = GrantKeys.fromEnv({ ...env ?? {}, VGI_RPC_GRANT_KEYS: keys.join(",") });
13831
+ return fromEnv ?? undefined;
13832
+ }
13718
13833
 
13719
13834
  // src/index.core.ts
13720
13835
  import {
13721
13836
  AuthUnavailableError,
13837
+ GrantKeys as GrantKeys2,
13722
13838
  GrantRefusedError,
13723
13839
  IdentityUnavailableError,
13724
13840
  StatusError
@@ -13951,6 +14067,7 @@ export {
13951
14067
  FunctionStorageSqlite,
13952
14068
  FunctionType,
13953
14069
  GROUP_COLUMN_NAME,
14070
+ GrantKeys2 as GrantKeys,
13954
14071
  GrantRefusedError,
13955
14072
  INTROSPECT_PRINCIPALS_ENV,
13956
14073
  IdentityUnavailableError,
@@ -14072,6 +14189,7 @@ export {
14072
14189
  fromBrandedBigInt,
14073
14190
  fromBrandedNumber,
14074
14191
  storage as functionStorage,
14192
+ grantKeysFromArgv,
14075
14193
  httpConnect,
14076
14194
  int3 as int,
14077
14195
  int162 as int16,
@@ -14159,4 +14277,4 @@ export {
14159
14277
  utf82 as utf8
14160
14278
  };
14161
14279
 
14162
- //# debugId=B9E14A528C9EAE0164756E2164756E21
14280
+ //# debugId=E43EFCB3DEBB959264756E2164756E21