@query-farm/vgi 0.24.2 → 0.25.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/dist/catalog/attach-option.d.ts +10 -0
- package/dist/client-entry.d.ts +2 -0
- package/dist/client-entry.js +76 -1
- package/dist/client-entry.js.map +5 -4
- package/dist/http/fetch.d.ts +5 -5
- package/dist/index.core.d.ts +2 -2
- package/dist/index.js +30 -415
- package/dist/index.js.map +5 -6
- package/dist/serve-entry.js +7 -446
- package/dist/serve-entry.js.map +5 -7
- package/dist/worker-cf-entry.d.ts +1 -2
- package/dist/worker-cf-entry.js +2 -414
- package/dist/worker-cf-entry.js.map +6 -7
- package/package.json +3 -3
- package/src/catalog/attach-option.ts +54 -0
- package/src/client-entry.ts +11 -0
- package/src/http/fetch.ts +6 -6
- package/src/index.core.ts +6 -13
- package/src/serve-entry.ts +2 -7
- package/src/worker-cf-entry.ts +4 -4
- package/dist/http/describe-json.d.ts +0 -62
- package/src/http/describe-json.ts +0 -644
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@query-farm/vgi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "TypeScript framework for extending DuckDB with user-defined functions via the Vector Gateway Interface (VGI) over Arrow IPC.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Query Farm LLC (https://query.farm)",
|
|
@@ -90,12 +90,12 @@
|
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
92
92
|
"@query-farm/apache-arrow": "^21.1.1",
|
|
93
|
-
"@query-farm/vgi-rpc": ">=0.
|
|
93
|
+
"@query-farm/vgi-rpc": ">=0.19.0 <0.20.0"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
96
|
"@duckdb/node-api": "^1.5.2-r.1",
|
|
97
97
|
"@query-farm/apache-arrow": "^21.1.1",
|
|
98
|
-
"@query-farm/vgi-rpc": "^0.
|
|
98
|
+
"@query-farm/vgi-rpc": "^0.19.0",
|
|
99
99
|
"@types/bun": "latest",
|
|
100
100
|
"typescript": "^6.0.3"
|
|
101
101
|
},
|
|
@@ -35,9 +35,13 @@ import {
|
|
|
35
35
|
binary,
|
|
36
36
|
bool,
|
|
37
37
|
batchFromColumns,
|
|
38
|
+
iterRows,
|
|
38
39
|
serializeBatch,
|
|
40
|
+
deserializeBatch,
|
|
39
41
|
serializeSchema,
|
|
42
|
+
deserializeSchema,
|
|
40
43
|
} from "../arrow/index.js";
|
|
44
|
+
import { toUint8Array } from "../util/bytes.js";
|
|
41
45
|
|
|
42
46
|
/**
|
|
43
47
|
* Declarative spec for a single attach-time option.
|
|
@@ -137,6 +141,56 @@ export function serializeAttachOptionSpecs(
|
|
|
137
141
|
return Array.from(specs, serializeAttachOptionSpec);
|
|
138
142
|
}
|
|
139
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Deserialize one AttachOptionSpec from the wire format above.
|
|
146
|
+
*
|
|
147
|
+
* Reads by column name, so a spec written by a peer that predates the
|
|
148
|
+
* `required` column deserializes with `required: false` rather than failing —
|
|
149
|
+
* the same tolerance the Python and C++ readers have.
|
|
150
|
+
*/
|
|
151
|
+
export function deserializeAttachOptionSpec(
|
|
152
|
+
bytes: Uint8Array,
|
|
153
|
+
): AttachOptionSpec {
|
|
154
|
+
const row = [...iterRows(deserializeBatch(bytes))][0] as
|
|
155
|
+
| Record<string, unknown>
|
|
156
|
+
| undefined;
|
|
157
|
+
if (row === undefined) {
|
|
158
|
+
throw new Error("Cannot deserialize AttachOptionSpec from an empty batch");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// `type` is a serialized Arrow Schema whose single "value" field carries the
|
|
162
|
+
// option's DataType.
|
|
163
|
+
const typeSchema = deserializeSchema(toUint8Array(row.type as Uint8Array));
|
|
164
|
+
const type = typeSchema.fields[0]!.type;
|
|
165
|
+
|
|
166
|
+
let value: unknown;
|
|
167
|
+
const defaultBytes = row.default_value;
|
|
168
|
+
if (defaultBytes != null) {
|
|
169
|
+
const asBytes = toUint8Array(defaultBytes as Uint8Array);
|
|
170
|
+
if (asBytes.length > 0) {
|
|
171
|
+
const defaultRow = [...iterRows(deserializeBatch(asBytes))][0] as
|
|
172
|
+
| Record<string, unknown>
|
|
173
|
+
| undefined;
|
|
174
|
+
value = defaultRow?.value;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
name: String(row.name),
|
|
180
|
+
description: String(row.description ?? ""),
|
|
181
|
+
type,
|
|
182
|
+
...(value === undefined || value === null ? {} : { default: value }),
|
|
183
|
+
required: row.required === true,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Deserialize many specs — the shape `CatalogInfo.attach_option_specs` holds. */
|
|
188
|
+
export function deserializeAttachOptionSpecs(
|
|
189
|
+
specs: Iterable<Uint8Array>,
|
|
190
|
+
): AttachOptionSpec[] {
|
|
191
|
+
return Array.from(specs, deserializeAttachOptionSpec);
|
|
192
|
+
}
|
|
193
|
+
|
|
140
194
|
/**
|
|
141
195
|
* Raised when `attach` omits options declared `required`.
|
|
142
196
|
*
|
package/src/client-entry.ts
CHANGED
|
@@ -103,6 +103,17 @@ export {
|
|
|
103
103
|
deserializeBatch,
|
|
104
104
|
} from "./util/arrow/index.js";
|
|
105
105
|
|
|
106
|
+
// Arrow type identification — lets a consumer render a DataType for display
|
|
107
|
+
// without reaching into the backend implementation.
|
|
108
|
+
export { TypeId, typeSignature } from "./arrow/predicates.js";
|
|
109
|
+
|
|
110
|
+
// Attach options — the page-facing decoder for CatalogInfo.attach_option_specs.
|
|
111
|
+
export {
|
|
112
|
+
type AttachOptionSpec,
|
|
113
|
+
deserializeAttachOptionSpec,
|
|
114
|
+
deserializeAttachOptionSpecs,
|
|
115
|
+
} from "./catalog/attach-option.js";
|
|
116
|
+
|
|
106
117
|
// Byte utilities
|
|
107
118
|
export { toUint8Array } from "./util/bytes.js";
|
|
108
119
|
|
package/src/http/fetch.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { createHttpHandler, unpackStateToken, type Protocol } from "@query-farm/vgi-rpc";
|
|
14
14
|
import { arrowStateSerializer } from "../protocol/state-serializer.js";
|
|
15
15
|
import { buildVgiProtocol, type ProtocolConfig } from "../protocol/dispatch.js";
|
|
16
|
-
import type {
|
|
16
|
+
import type { LandingInfo } from "@query-farm/vgi-rpc";
|
|
17
17
|
|
|
18
18
|
export interface VgiFetchOptions {
|
|
19
19
|
/** Wire-protocol config (registry + catalogInterface). */
|
|
@@ -36,10 +36,10 @@ export interface VgiFetchOptions {
|
|
|
36
36
|
/** Public source-repository URL, surfaced on the landing page. */
|
|
37
37
|
repositoryUrl?: string;
|
|
38
38
|
/** Enables the standardized VGI landing surface: `GET /` serves the shared
|
|
39
|
-
* landing.html
|
|
40
|
-
* `GET /
|
|
41
|
-
*
|
|
42
|
-
|
|
39
|
+
* landing.html plus a JSON status document carrying this identity, and
|
|
40
|
+
* `GET /vgi-client.js` serves the browser client build the page reads the
|
|
41
|
+
* catalog with. */
|
|
42
|
+
landingInfo?: LandingInfo;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -74,7 +74,7 @@ export function createVgiFetch(opts: VgiFetchOptions): (req: Request) => Promise
|
|
|
74
74
|
stateSerializer: arrowStateSerializer,
|
|
75
75
|
corsOrigins: opts.corsOrigins,
|
|
76
76
|
repositoryUrl: opts.repositoryUrl,
|
|
77
|
-
|
|
77
|
+
landingInfo: opts.landingInfo,
|
|
78
78
|
});
|
|
79
79
|
return async (req: Request) => handler(req);
|
|
80
80
|
}
|
package/src/index.core.ts
CHANGED
|
@@ -153,25 +153,18 @@ export { arrowStateSerializer, EXCHANGE_STATE_SCHEMA, serializeUserState, deseri
|
|
|
153
153
|
// Protocol assembly (for embedding the worker dispatcher in a custom HTTP server).
|
|
154
154
|
export { buildVgiProtocol, type ProtocolConfig } from "./protocol/dispatch.js";
|
|
155
155
|
|
|
156
|
-
// VGI HTTP landing surface
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
buildDescribeJson,
|
|
162
|
-
createLandingDescribe,
|
|
163
|
-
CUPOLA_BASE,
|
|
164
|
-
LANDING_SCHEMA_VERSION,
|
|
165
|
-
type LandingDescribeProvider,
|
|
166
|
-
type WorkerDescribeInfo,
|
|
167
|
-
} from "./http/describe-json.js";
|
|
156
|
+
// VGI HTTP landing surface. The shared landing.html reads catalog metadata by
|
|
157
|
+
// speaking the protocol through the client bundle the worker serves beside it,
|
|
158
|
+
// so a worker supplies only its own identity via `createHttpHandler`'s
|
|
159
|
+
// `landingInfo` option.
|
|
160
|
+
export type { LandingInfo } from "@query-farm/vgi-rpc";
|
|
168
161
|
|
|
169
162
|
// Wire schemas — needed by workers that synthesize TableInfo.bind_result /
|
|
170
163
|
// TableInfo.scan_function bytes to short-circuit per-scan RPCs.
|
|
171
164
|
export { BindResultSchema, ScanFunctionResultSchema } from "./generated/vgi-protocol-schemas.js";
|
|
172
165
|
|
|
173
166
|
// Attach-option specs (for catalogs that advertise typed ATTACH options).
|
|
174
|
-
export { type AttachOptionSpec, serializeAttachOptionSpec, serializeAttachOptionSpecs } from "./catalog/attach-option.js";
|
|
167
|
+
export { type AttachOptionSpec, serializeAttachOptionSpec, serializeAttachOptionSpecs, deserializeAttachOptionSpec, deserializeAttachOptionSpecs } from "./catalog/attach-option.js";
|
|
175
168
|
|
|
176
169
|
// Column statistics (for inlining on TableInfo.column_statistics).
|
|
177
170
|
export { type ColumnStatistics, serializeColumnStatistics } from "./util/statistics.js";
|
package/src/serve-entry.ts
CHANGED
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
|
|
24
24
|
import type { CatalogInterface } from "./catalog/interface.js";
|
|
25
25
|
import type { FunctionRegistry } from "./functions/registry.js";
|
|
26
|
-
import { createLandingDescribe } from "./http/describe-json.js";
|
|
27
26
|
import { createVgiFetch } from "./http/fetch.js";
|
|
28
27
|
|
|
29
28
|
/** Environment variables `serveVgiWorker` reads. Injectable for testing. */
|
|
@@ -192,11 +191,7 @@ export function createVgiWorkerFetch(
|
|
|
192
191
|
serverId: opts.serverId ?? opts.name,
|
|
193
192
|
corsOrigins,
|
|
194
193
|
repositoryUrl: opts.repositoryUrl,
|
|
195
|
-
|
|
196
|
-
name: opts.name,
|
|
197
|
-
doc: opts.doc,
|
|
198
|
-
version: opts.version,
|
|
199
|
-
}),
|
|
194
|
+
landingInfo: { name: opts.name, doc: opts.doc, version: opts.version },
|
|
200
195
|
});
|
|
201
196
|
}
|
|
202
197
|
|
|
@@ -225,7 +220,7 @@ export function serveVgiWorker(opts: ServeVgiWorkerOptions): VgiHttpServer {
|
|
|
225
220
|
const base = `http://localhost:${server.port}`;
|
|
226
221
|
console.log(`${opts.name} VGI HTTP worker listening on ${base}`);
|
|
227
222
|
console.log(` landing page ${base}/`);
|
|
228
|
-
console.log(`
|
|
223
|
+
console.log(` client bundle ${base}/vgi-client.js`);
|
|
229
224
|
console.log(` health ${base}/health`);
|
|
230
225
|
console.log(` attach ATTACH '${opts.name}' AS ${opts.name} (TYPE vgi, LOCATION '${base}');`);
|
|
231
226
|
}
|
package/src/worker-cf-entry.ts
CHANGED
|
@@ -53,10 +53,10 @@ export type {
|
|
|
53
53
|
|
|
54
54
|
export type { ProtocolConfig } from "./protocol/dispatch.js";
|
|
55
55
|
|
|
56
|
-
// Landing surface. CF workers pass
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
export type {
|
|
56
|
+
// Landing surface. CF workers pass their identity as `landingInfo` so `GET /`
|
|
57
|
+
// serves the standardized VGI landing page, and `GET /vgi-client.js` the
|
|
58
|
+
// browser client build it reads the catalog with.
|
|
59
|
+
export type { LandingInfo } from "@query-farm/vgi-rpc";
|
|
60
60
|
|
|
61
61
|
// Backend-agnostic Arrow facade. Same source resolves to arrow-js on
|
|
62
62
|
// Node/Bun and flechette under workerd/worker/browser via the package's
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { CatalogInterface } from "../catalog/interface.js";
|
|
2
|
-
export declare const LANDING_SCHEMA_VERSION = 1;
|
|
3
|
-
export declare const CUPOLA_BASE = "https://cupola.query-farm.services";
|
|
4
|
-
/**
|
|
5
|
-
* Producer for the VGI landing surface, passed to `createHttpHandler`'s
|
|
6
|
-
* `landingDescribe` option. Declared locally (structurally identical to
|
|
7
|
-
* `@query-farm/vgi-rpc`'s `LandingDescribeProvider`) so this package does not
|
|
8
|
-
* hard-couple to a specific vgi-rpc version.
|
|
9
|
-
*/
|
|
10
|
-
export interface LandingDescribeProvider {
|
|
11
|
-
describe(ctx: {
|
|
12
|
-
serverId: string;
|
|
13
|
-
oauth: boolean;
|
|
14
|
-
}): unknown | Promise<unknown>;
|
|
15
|
-
columns(catalog: string, schema: string, table: string): unknown | null | Promise<unknown | null>;
|
|
16
|
-
}
|
|
17
|
-
/** Identity of the worker software surfaced in `describe.json` → `worker`. */
|
|
18
|
-
export interface WorkerDescribeInfo {
|
|
19
|
-
/** Worker name (e.g. class or catalog name). */
|
|
20
|
-
name: string;
|
|
21
|
-
/** One-line worker description. */
|
|
22
|
-
doc?: string;
|
|
23
|
-
/** Worker software version. */
|
|
24
|
-
version?: string;
|
|
25
|
-
}
|
|
26
|
-
interface ColumnJson {
|
|
27
|
-
name: string;
|
|
28
|
-
type: string;
|
|
29
|
-
comment?: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Build the full `describe.json` document for a worker's catalog interface.
|
|
33
|
-
*
|
|
34
|
-
* `oauth` and `serverId` are supplied by the HTTP server (they depend on runtime
|
|
35
|
-
* config, not the catalog).
|
|
36
|
-
*/
|
|
37
|
-
export declare function buildDescribeJson(iface: CatalogInterface, worker: WorkerDescribeInfo, opts?: {
|
|
38
|
-
oauth?: boolean;
|
|
39
|
-
serverId?: string;
|
|
40
|
-
cupolaBase?: string;
|
|
41
|
-
}): Promise<Record<string, unknown>>;
|
|
42
|
-
/**
|
|
43
|
-
* Build the lazy per-object column payload for one table or view.
|
|
44
|
-
*
|
|
45
|
-
* Returns `{ columns: [{ name, type, comment? }] }`, or `null` when the object
|
|
46
|
-
* can't be found. Tables deserialize their Arrow column schema; views expose
|
|
47
|
-
* their declared column comments (types are only known after binding the SQL,
|
|
48
|
-
* which the worker does not do here).
|
|
49
|
-
*/
|
|
50
|
-
export declare function buildColumnsJson(iface: CatalogInterface, catalog: string, schema: string, table: string): Promise<{
|
|
51
|
-
columns: ColumnJson[];
|
|
52
|
-
} | null>;
|
|
53
|
-
/**
|
|
54
|
-
* Build a {@link LandingDescribeProvider} to pass to `createHttpHandler` from
|
|
55
|
-
* `@query-farm/vgi-rpc`. Wires the worker's catalog interface into the
|
|
56
|
-
* standardized landing surface (`GET {prefix}/describe.json` and the lazy
|
|
57
|
-
* per-object column endpoint).
|
|
58
|
-
*/
|
|
59
|
-
export declare function createLandingDescribe(iface: CatalogInterface, worker: WorkerDescribeInfo, opts?: {
|
|
60
|
-
cupolaBase?: string;
|
|
61
|
-
}): LandingDescribeProvider;
|
|
62
|
-
export {};
|