@query-farm/vgi 0.24.1 → 0.24.2

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.
@@ -21,6 +21,16 @@ export interface AttachOptionSpec {
21
21
  * the options dict delivered to attach()).
22
22
  */
23
23
  default?: unknown;
24
+ /**
25
+ * The caller must supply this option at ATTACH time. A catalog that cannot
26
+ * be attached without it advertises that fact at discovery, so a client can
27
+ * say so before attempting the attach rather than surfacing a failure that
28
+ * reads like an empty catalog.
29
+ *
30
+ * Mutually exclusive with `default` — an option that falls back to a value
31
+ * is by definition satisfiable without the caller.
32
+ */
33
+ required?: boolean;
24
34
  }
25
35
  /**
26
36
  * Serialize an AttachOptionSpec to the wire format the extension expects
@@ -31,3 +41,23 @@ export declare function serializeAttachOptionSpec(spec: AttachOptionSpec): Uint8
31
41
  * Convenience: serialize many specs at once for CatalogInfo.attach_option_specs.
32
42
  */
33
43
  export declare function serializeAttachOptionSpecs(specs: Iterable<AttachOptionSpec>): Uint8Array[];
44
+ /**
45
+ * Raised when `attach` omits options declared `required`.
46
+ *
47
+ * Carries the option names in `missing` so a caller can act on them without
48
+ * parsing the message. Mirrors `MissingAttachOptionsError` on the Python side,
49
+ * message included — the extension's integration suite matches on its text.
50
+ */
51
+ export declare class MissingAttachOptionsError extends Error {
52
+ readonly missing: string[];
53
+ constructor(catalogName: string, missing: string[]);
54
+ }
55
+ /**
56
+ * Throw if any `required` spec has no corresponding entry in `options`.
57
+ *
58
+ * Option names are matched case-insensitively, mirroring DuckDB's handling of
59
+ * ATTACH option keys.
60
+ *
61
+ * @throws {MissingAttachOptionsError} If a required option was not supplied.
62
+ */
63
+ export declare function validateRequiredAttachOptions(catalogName: string, specs: Iterable<AttachOptionSpec>, options: Record<string, unknown>): void;
@@ -1,6 +1,7 @@
1
1
  import { CatalogInterface, type AttachOpaqueData, type TransactionOpaqueData, type CatalogAttachResult, type SchemaInfo, type CatalogInfo, type TableInfo, type ViewInfo, type FunctionInfo, type MacroInfo, type IndexInfo, type CopyFromFormatInfo } from "./interface.js";
2
2
  import type { CatalogDescriptor } from "./descriptors.js";
3
3
  import type { FunctionRegistry } from "../functions/registry.js";
4
+ import { type AttachOptionSpec } from "./attach-option.js";
4
5
  export declare class ReadOnlyCatalogInterface extends CatalogInterface {
5
6
  private _descriptor;
6
7
  private _registry;
@@ -8,6 +9,16 @@ export declare class ReadOnlyCatalogInterface extends CatalogInterface {
8
9
  private _version;
9
10
  constructor(descriptor: CatalogDescriptor, registry: FunctionRegistry);
10
11
  catalogs(): string[];
12
+ /**
13
+ * Attach-time options this catalog declares, for the named catalog.
14
+ *
15
+ * Empty by default — the declarative descriptor path carries no attach
16
+ * options. A subclass that advertises specs in `catalogsInfo()` should
17
+ * return the same specs here so `attach()` enforces the `required` ones it
18
+ * advertised. Takes the catalog name because one interface may serve
19
+ * several catalogs with different option sets.
20
+ */
21
+ attachOptionSpecs(_name: string): AttachOptionSpec[];
11
22
  catalogsInfo(): CatalogInfo[];
12
23
  attach(name: string, options?: Record<string, unknown>, dataVersionSpec?: string | null, implementationVersion?: string | null): CatalogAttachResult | Promise<CatalogAttachResult>;
13
24
  detach(attachOpaqueData: AttachOpaqueData): void;
package/dist/index.js CHANGED
@@ -7022,6 +7022,56 @@ function resolveMetadata(func) {
7022
7022
  };
7023
7023
  }
7024
7024
 
7025
+ // src/catalog/attach-option.ts
7026
+ init_arrow();
7027
+ var SPEC_SCHEMA = schema2([
7028
+ field2("name", utf82(), false),
7029
+ field2("description", utf82(), false),
7030
+ field2("type", binary2(), false),
7031
+ field2("default_value", binary2(), true),
7032
+ field2("required", bool2(), true)
7033
+ ]);
7034
+ function serializeAttachOptionSpec(spec) {
7035
+ if (spec.required && spec.default !== undefined && spec.default !== null) {
7036
+ throw new Error(`Attach option '${spec.name}' is required but also declares a default ` + `(${JSON.stringify(spec.default)}); an option with a default is always ` + "satisfiable without the caller. Drop one.");
7037
+ }
7038
+ const typeSchema = schema2([field2("value", spec.type, true)]);
7039
+ const typeBytes = serializeSchema(typeSchema);
7040
+ let defaultBytes = null;
7041
+ if (spec.default !== undefined && spec.default !== null) {
7042
+ const defaultBatch = batchFromColumns({ value: [spec.default] }, typeSchema);
7043
+ defaultBytes = serializeBatch(defaultBatch);
7044
+ }
7045
+ const batch = batchFromColumns({
7046
+ name: [spec.name],
7047
+ description: [spec.description],
7048
+ type: [typeBytes],
7049
+ default_value: [defaultBytes],
7050
+ required: [spec.required ?? false]
7051
+ }, SPEC_SCHEMA);
7052
+ return serializeBatch(batch);
7053
+ }
7054
+ function serializeAttachOptionSpecs(specs) {
7055
+ return Array.from(specs, serializeAttachOptionSpec);
7056
+ }
7057
+
7058
+ class MissingAttachOptionsError extends Error {
7059
+ missing;
7060
+ constructor(catalogName, missing) {
7061
+ const joined = missing.map((name) => `'${name}'`).join(", ");
7062
+ super(`Catalog '${catalogName}' cannot be attached without the required ` + `option${missing.length > 1 ? "s" : ""} ${joined}.`);
7063
+ this.name = "MissingAttachOptionsError";
7064
+ this.missing = missing;
7065
+ }
7066
+ }
7067
+ function validateRequiredAttachOptions(catalogName, specs, options) {
7068
+ const supplied = new Set(Object.keys(options).map((key) => key.toLowerCase()));
7069
+ const missing = Array.from(specs).filter((spec) => spec.required && !supplied.has(spec.name.toLowerCase())).map((spec) => spec.name);
7070
+ if (missing.length > 0) {
7071
+ throw new MissingAttachOptionsError(catalogName, missing);
7072
+ }
7073
+ }
7074
+
7025
7075
  // src/catalog/read-only.ts
7026
7076
  class ReadOnlyCatalogInterface extends CatalogInterface {
7027
7077
  _descriptor;
@@ -7047,6 +7097,9 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
7047
7097
  catalogs() {
7048
7098
  return [this._descriptor.name];
7049
7099
  }
7100
+ attachOptionSpecs(_name) {
7101
+ return [];
7102
+ }
7050
7103
  catalogsInfo() {
7051
7104
  return [{
7052
7105
  name: this._descriptor.name,
@@ -7061,6 +7114,7 @@ class ReadOnlyCatalogInterface extends CatalogInterface {
7061
7114
  if (!this.catalogs().includes(name)) {
7062
7115
  throw new Error(`No worker handles catalog '${name}'`);
7063
7116
  }
7117
+ validateRequiredAttachOptions(name, this.attachOptionSpecs(name), options ?? {});
7064
7118
  const attachOpaqueData = new Uint8Array(16);
7065
7119
  crypto.getRandomValues(attachOpaqueData);
7066
7120
  this._attachments.set(name, attachOpaqueData);
@@ -10861,33 +10915,6 @@ function createLandingDescribe(iface, worker, opts = {}) {
10861
10915
  columns: (catalog, schema3, table) => buildColumnsJson(iface, catalog, schema3, table)
10862
10916
  };
10863
10917
  }
10864
- // src/catalog/attach-option.ts
10865
- init_arrow();
10866
- var SPEC_SCHEMA = schema2([
10867
- field2("name", utf82(), false),
10868
- field2("description", utf82(), false),
10869
- field2("type", binary2(), false),
10870
- field2("default_value", binary2(), true)
10871
- ]);
10872
- function serializeAttachOptionSpec(spec) {
10873
- const typeSchema = schema2([field2("value", spec.type, true)]);
10874
- const typeBytes = serializeSchema(typeSchema);
10875
- let defaultBytes = null;
10876
- if (spec.default !== undefined && spec.default !== null) {
10877
- const defaultBatch = batchFromColumns({ value: [spec.default] }, typeSchema);
10878
- defaultBytes = serializeBatch(defaultBatch);
10879
- }
10880
- const batch = batchFromColumns({
10881
- name: [spec.name],
10882
- description: [spec.description],
10883
- type: [typeBytes],
10884
- default_value: [defaultBytes]
10885
- }, SPEC_SCHEMA);
10886
- return serializeBatch(batch);
10887
- }
10888
- function serializeAttachOptionSpecs(specs) {
10889
- return Array.from(specs, serializeAttachOptionSpec);
10890
- }
10891
10918
  // src/secrets/helpers.ts
10892
10919
  function scalarStr(v) {
10893
10920
  if (v === null || v === undefined)
@@ -12170,4 +12197,4 @@ export {
12170
12197
  ArgumentValidationError
12171
12198
  };
12172
12199
 
12173
- //# debugId=F2B3478BD764EF8C64756E2164756E21
12200
+ //# debugId=266210B03996D0CD64756E2164756E21