@query-farm/vgi-rpc 0.6.4 → 0.7.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/access-log.d.ts +50 -0
- package/dist/access-log.d.ts.map +1 -0
- package/dist/arrow/impl-arrowjs/index.d.ts +96 -0
- package/dist/arrow/impl-arrowjs/index.d.ts.map +1 -0
- package/dist/arrow/impl-flechette/index.d.ts +102 -0
- package/dist/arrow/impl-flechette/index.d.ts.map +1 -0
- package/dist/arrow/impl-flechette/message-meta.d.ts +11 -0
- package/dist/arrow/impl-flechette/message-meta.d.ts.map +1 -0
- package/dist/arrow/index.d.ts +4 -0
- package/dist/arrow/index.d.ts.map +1 -0
- package/dist/arrow/predicates.d.ts +44 -0
- package/dist/arrow/predicates.d.ts.map +1 -0
- package/dist/arrow/types.d.ts +62 -0
- package/dist/arrow/types.d.ts.map +1 -0
- package/dist/client/capabilities.d.ts +25 -0
- package/dist/client/capabilities.d.ts.map +1 -0
- package/dist/client/connect.d.ts.map +1 -1
- package/dist/client/introspect.d.ts +7 -0
- package/dist/client/introspect.d.ts.map +1 -1
- package/dist/client/ipc.d.ts +8 -2
- package/dist/client/ipc.d.ts.map +1 -1
- package/dist/client/pipe.d.ts.map +1 -1
- package/dist/client/stream.d.ts +11 -2
- package/dist/client/stream.d.ts.map +1 -1
- package/dist/client/uploadUrl.d.ts +25 -0
- package/dist/client/uploadUrl.d.ts.map +1 -0
- package/dist/constants.d.ts +15 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/crypto.d.ts +22 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/dispatch/describe.d.ts +10 -6
- package/dist/dispatch/describe.d.ts.map +1 -1
- package/dist/dispatch/stream.d.ts +2 -2
- package/dist/dispatch/stream.d.ts.map +1 -1
- package/dist/dispatch/unary.d.ts +2 -2
- package/dist/dispatch/unary.d.ts.map +1 -1
- package/dist/errors.d.ts +46 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/external.d.ts +25 -5
- package/dist/external.d.ts.map +1 -1
- package/dist/http/bearer.d.ts.map +1 -1
- package/dist/http/common.d.ts +42 -7
- package/dist/http/common.d.ts.map +1 -1
- package/dist/http/dispatch.d.ts +20 -2
- package/dist/http/dispatch.d.ts.map +1 -1
- package/dist/http/handler.d.ts.map +1 -1
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/mtls.d.ts +2 -1
- package/dist/http/mtls.d.ts.map +1 -1
- package/dist/http/oauth-pkce.d.ts +141 -0
- package/dist/http/oauth-pkce.d.ts.map +1 -0
- package/dist/http/pages.d.ts +3 -0
- package/dist/http/pages.d.ts.map +1 -1
- package/dist/http/sticky.d.ts +124 -0
- package/dist/http/sticky.d.ts.map +1 -0
- package/dist/http/token.d.ts +38 -12
- package/dist/http/token.d.ts.map +1 -1
- package/dist/http/types.d.ts +66 -5
- package/dist/http/types.d.ts.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1275 -3511
- package/dist/index.js.map +19 -37
- package/dist/launcher/hash.d.ts +22 -0
- package/dist/launcher/hash.d.ts.map +1 -0
- package/dist/launcher/index.d.ts +23 -0
- package/dist/launcher/index.d.ts.map +1 -0
- package/dist/launcher/launch.d.ts +27 -0
- package/dist/launcher/launch.d.ts.map +1 -0
- package/dist/launcher/lock.d.ts +19 -0
- package/dist/launcher/lock.d.ts.map +1 -0
- package/dist/launcher/serve-unix.d.ts +54 -0
- package/dist/launcher/serve-unix.d.ts.map +1 -0
- package/dist/launcher/state.d.ts +59 -0
- package/dist/launcher/state.d.ts.map +1 -0
- package/dist/otel.d.ts.map +1 -1
- package/dist/protocol.d.ts +16 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/schema.d.ts +45 -18
- package/dist/schema.d.ts.map +1 -1
- package/dist/server.d.ts +23 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/types.d.ts +216 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/util/gzip.d.ts +10 -0
- package/dist/util/gzip.d.ts.map +1 -0
- package/dist/util/schema.d.ts +3 -15
- package/dist/util/schema.d.ts.map +1 -1
- package/dist/util/web-crypto.d.ts +22 -0
- package/dist/util/web-crypto.d.ts.map +1 -0
- package/dist/util/zstd.d.ts +26 -3
- package/dist/util/zstd.d.ts.map +1 -1
- package/dist/wire/opaque.d.ts +11 -0
- package/dist/wire/opaque.d.ts.map +1 -0
- package/dist/wire/reader.d.ts +5 -5
- package/dist/wire/reader.d.ts.map +1 -1
- package/dist/wire/request.d.ts +11 -3
- package/dist/wire/request.d.ts.map +1 -1
- package/dist/wire/response.d.ts +6 -6
- package/dist/wire/response.d.ts.map +1 -1
- package/dist/wire/writer.d.ts +49 -39
- package/dist/wire/writer.d.ts.map +1 -1
- package/package.json +24 -10
- package/src/access-log.ts +195 -0
- package/src/arrow/impl-arrowjs/index.ts +433 -0
- package/src/arrow/impl-flechette/index.ts +414 -0
- package/src/arrow/impl-flechette/message-meta.ts +174 -0
- package/src/arrow/index.ts +89 -0
- package/src/arrow/predicates.ts +56 -0
- package/src/arrow/types.ts +73 -0
- package/src/client/capabilities.ts +84 -0
- package/src/client/connect.ts +103 -26
- package/src/client/introspect.ts +60 -38
- package/src/client/ipc.ts +37 -27
- package/src/client/pipe.ts +12 -9
- package/src/client/stream.ts +34 -19
- package/src/client/uploadUrl.ts +169 -0
- package/src/constants.ts +18 -1
- package/src/crypto.ts +95 -0
- package/src/dispatch/describe.ts +146 -107
- package/src/dispatch/stream.ts +53 -24
- package/src/dispatch/unary.ts +5 -4
- package/src/errors.ts +76 -0
- package/src/external.ts +43 -29
- package/src/http/bearer.ts +2 -5
- package/src/http/common.ts +90 -23
- package/src/http/dispatch.ts +373 -46
- package/src/http/handler.ts +790 -68
- package/src/http/index.ts +1 -0
- package/src/http/mtls.ts +18 -3
- package/src/http/oauth-pkce.ts +1035 -0
- package/src/http/pages.ts +30 -15
- package/src/http/sticky.ts +429 -0
- package/src/http/token.ts +165 -75
- package/src/http/types.ts +67 -5
- package/src/index.ts +40 -1
- package/src/launcher/hash.ts +104 -0
- package/src/launcher/index.ts +35 -0
- package/src/launcher/launch.ts +284 -0
- package/src/launcher/lock.ts +171 -0
- package/src/launcher/serve-unix.ts +385 -0
- package/src/launcher/state.ts +245 -0
- package/src/otel.ts +39 -33
- package/src/protocol.ts +27 -3
- package/src/schema.ts +107 -56
- package/src/server.ts +196 -20
- package/src/types.ts +322 -18
- package/src/util/gzip.ts +63 -0
- package/src/util/schema.ts +4 -22
- package/src/util/web-crypto.ts +98 -0
- package/src/util/zstd.ts +133 -14
- package/src/wire/opaque.ts +37 -0
- package/src/wire/reader.ts +5 -4
- package/src/wire/request.ts +67 -8
- package/src/wire/response.ts +51 -85
- package/src/wire/writer.ts +165 -69
- package/dist/util/conform.d.ts +0 -18
- package/dist/util/conform.d.ts.map +0 -1
- package/src/util/conform.ts +0 -94
package/src/otel.ts
CHANGED
|
@@ -119,42 +119,48 @@ export function createOtelHook(config?: OtelConfig): DispatchHook {
|
|
|
119
119
|
const durationS = (performance.now() - t.startTime) / 1000;
|
|
120
120
|
const status = error ? "error" : "ok";
|
|
121
121
|
|
|
122
|
-
// Finalize span
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
122
|
+
// Finalize span — wrap in try/finally so metric recording still
|
|
123
|
+
// runs if an exporter inside span.end() raises. Mirrors the Python
|
|
124
|
+
// fix that detaches the otel context unconditionally; TS doesn't
|
|
125
|
+
// attach context, but the same shape protects metric counters from
|
|
126
|
+
// a single misbehaving exporter taking out request observability.
|
|
127
|
+
try {
|
|
128
|
+
if (t.span) {
|
|
129
|
+
if (stats) {
|
|
130
|
+
t.span.setAttributes({
|
|
131
|
+
"rpc.vgi_rpc.input_batches": stats.inputBatches,
|
|
132
|
+
"rpc.vgi_rpc.output_batches": stats.outputBatches,
|
|
133
|
+
"rpc.vgi_rpc.input_rows": stats.inputRows,
|
|
134
|
+
"rpc.vgi_rpc.output_rows": stats.outputRows,
|
|
135
|
+
"rpc.vgi_rpc.input_bytes": stats.inputBytes,
|
|
136
|
+
"rpc.vgi_rpc.output_bytes": stats.outputBytes,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
134
139
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
if (error) {
|
|
141
|
+
t.span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
142
|
+
t.span.setAttribute("rpc.vgi_rpc.error_type", error.constructor.name);
|
|
143
|
+
if (recordExceptions) {
|
|
144
|
+
t.span.recordException(error);
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
t.span.setStatus({ code: SpanStatusCode.OK });
|
|
140
148
|
}
|
|
141
|
-
|
|
142
|
-
|
|
149
|
+
t.span.end();
|
|
150
|
+
}
|
|
151
|
+
} finally {
|
|
152
|
+
// Record metrics — runs even if span finalisation above raises.
|
|
153
|
+
if (enableMetrics) {
|
|
154
|
+
const metricAttrs: Attributes = {
|
|
155
|
+
"rpc.system": "vgi_rpc",
|
|
156
|
+
"rpc.service": serviceName,
|
|
157
|
+
"rpc.method": info.method,
|
|
158
|
+
"rpc.vgi_rpc.method_type": info.methodType,
|
|
159
|
+
status,
|
|
160
|
+
};
|
|
161
|
+
requestCounter?.add(1, metricAttrs);
|
|
162
|
+
durationHistogram?.record(durationS, metricAttrs);
|
|
143
163
|
}
|
|
144
|
-
t.span.end();
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Record metrics
|
|
148
|
-
if (enableMetrics) {
|
|
149
|
-
const metricAttrs: Attributes = {
|
|
150
|
-
"rpc.system": "vgi_rpc",
|
|
151
|
-
"rpc.service": serviceName,
|
|
152
|
-
"rpc.method": info.method,
|
|
153
|
-
"rpc.vgi_rpc.method_type": info.methodType,
|
|
154
|
-
status,
|
|
155
|
-
};
|
|
156
|
-
requestCounter?.add(1, metricAttrs);
|
|
157
|
-
durationHistogram?.record(durationS, metricAttrs);
|
|
158
164
|
}
|
|
159
165
|
},
|
|
160
166
|
};
|
package/src/protocol.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// © Copyright 2025-2026, Query.Farm LLC - https://query.farm
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { schema as makeSchema } from "./arrow/index.js";
|
|
5
|
+
import { parseProtocolVersion } from "./errors.js";
|
|
5
6
|
import { inferParamTypes, type SchemaLike, toSchema } from "./schema.js";
|
|
6
7
|
import {
|
|
7
8
|
type ExchangeFn,
|
|
@@ -9,12 +10,13 @@ import {
|
|
|
9
10
|
type HeaderInit,
|
|
10
11
|
type MethodDefinition,
|
|
11
12
|
MethodType,
|
|
13
|
+
type OnCancelFn,
|
|
12
14
|
type ProducerFn,
|
|
13
15
|
type ProducerInit,
|
|
14
16
|
type UnaryHandler,
|
|
15
17
|
} from "./types.js";
|
|
16
18
|
|
|
17
|
-
const EMPTY_SCHEMA =
|
|
19
|
+
const EMPTY_SCHEMA = makeSchema([]);
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Fluent builder for defining RPC methods.
|
|
@@ -22,10 +24,28 @@ const EMPTY_SCHEMA = new Schema([]);
|
|
|
22
24
|
*/
|
|
23
25
|
export class Protocol {
|
|
24
26
|
readonly name: string;
|
|
27
|
+
/**
|
|
28
|
+
* Application protocol surface version. When non-empty, the server enforces
|
|
29
|
+
* exact major+minor match (patch ignored) against every request's
|
|
30
|
+
* `vgi_rpc.protocol_version` metadata; clients bound to this Protocol emit
|
|
31
|
+
* the value on every request. Format: canonical semver MAJOR.MINOR.PATCH.
|
|
32
|
+
* Mirrors Python's `Protocol.protocol_version` ClassVar.
|
|
33
|
+
*/
|
|
34
|
+
readonly protocolVersion: string;
|
|
35
|
+
/** Parsed semver tuple; null when `protocolVersion` is unset. */
|
|
36
|
+
readonly protocolVersionParts: readonly [number, number, number] | null;
|
|
25
37
|
private _methods: Map<string, MethodDefinition> = new Map();
|
|
26
38
|
|
|
27
|
-
constructor(name: string) {
|
|
39
|
+
constructor(name: string, options?: { protocolVersion?: string }) {
|
|
28
40
|
this.name = name;
|
|
41
|
+
const raw = options?.protocolVersion;
|
|
42
|
+
if (raw === undefined || raw === "") {
|
|
43
|
+
this.protocolVersion = "";
|
|
44
|
+
this.protocolVersionParts = null;
|
|
45
|
+
} else {
|
|
46
|
+
this.protocolVersion = raw;
|
|
47
|
+
this.protocolVersionParts = parseProtocolVersion(raw);
|
|
48
|
+
}
|
|
29
49
|
}
|
|
30
50
|
|
|
31
51
|
/**
|
|
@@ -74,6 +94,7 @@ export class Protocol {
|
|
|
74
94
|
outputSchema: SchemaLike;
|
|
75
95
|
init: ProducerInit<S>;
|
|
76
96
|
produce: ProducerFn<S>;
|
|
97
|
+
onCancel?: OnCancelFn<S>;
|
|
77
98
|
headerSchema?: SchemaLike;
|
|
78
99
|
headerInit?: HeaderInit;
|
|
79
100
|
doc?: string;
|
|
@@ -91,6 +112,7 @@ export class Protocol {
|
|
|
91
112
|
inputSchema: EMPTY_SCHEMA,
|
|
92
113
|
producerInit: config.init as ProducerInit,
|
|
93
114
|
producerFn: config.produce as ProducerFn,
|
|
115
|
+
onCancel: config.onCancel as OnCancelFn | undefined,
|
|
94
116
|
headerSchema: config.headerSchema ? toSchema(config.headerSchema) : undefined,
|
|
95
117
|
headerInit: config.headerInit,
|
|
96
118
|
doc: config.doc,
|
|
@@ -112,6 +134,7 @@ export class Protocol {
|
|
|
112
134
|
outputSchema: SchemaLike;
|
|
113
135
|
init: ExchangeInit<S>;
|
|
114
136
|
exchange: ExchangeFn<S>;
|
|
137
|
+
onCancel?: OnCancelFn<S>;
|
|
115
138
|
headerSchema?: SchemaLike;
|
|
116
139
|
headerInit?: HeaderInit;
|
|
117
140
|
doc?: string;
|
|
@@ -129,6 +152,7 @@ export class Protocol {
|
|
|
129
152
|
outputSchema: toSchema(config.outputSchema),
|
|
130
153
|
exchangeInit: config.init as ExchangeInit,
|
|
131
154
|
exchangeFn: config.exchange as ExchangeFn,
|
|
155
|
+
onCancel: config.onCancel as OnCancelFn | undefined,
|
|
132
156
|
headerSchema: config.headerSchema ? toSchema(config.headerSchema) : undefined,
|
|
133
157
|
headerInit: config.headerInit,
|
|
134
158
|
doc: config.doc,
|
package/src/schema.ts
CHANGED
|
@@ -2,109 +2,160 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
binary,
|
|
6
|
+
bool as boolType,
|
|
7
|
+
float32 as float32Type,
|
|
8
|
+
float64 as float64Type,
|
|
9
|
+
int8 as int8Type,
|
|
10
|
+
int16 as int16Type,
|
|
11
|
+
int32 as int32Type,
|
|
12
|
+
int64 as int64Type,
|
|
13
|
+
isBinary,
|
|
14
|
+
isBool,
|
|
15
|
+
isFloat,
|
|
16
|
+
isInt,
|
|
17
|
+
isUtf8,
|
|
18
|
+
field as makeField,
|
|
19
|
+
schema as makeSchema,
|
|
20
|
+
uint8 as uint8Type,
|
|
21
|
+
uint16 as uint16Type,
|
|
22
|
+
uint32 as uint32Type,
|
|
23
|
+
uint64 as uint64Type,
|
|
24
|
+
utf8,
|
|
25
|
+
type VgiDataType,
|
|
26
|
+
type VgiField,
|
|
27
|
+
type VgiSchema,
|
|
28
|
+
} from "./arrow/index.js";
|
|
17
29
|
|
|
18
30
|
// ---------------------------------------------------------------------------
|
|
19
31
|
// Convenient DataType singletons — re-export so users avoid arrow imports
|
|
20
32
|
// ---------------------------------------------------------------------------
|
|
21
33
|
|
|
22
34
|
/** Apache Arrow Utf8 type. Use as schema shorthand: `{ name: str }` */
|
|
23
|
-
export const str =
|
|
35
|
+
export const str = utf8();
|
|
24
36
|
/** Apache Arrow Binary type. Use as schema shorthand: `{ data: bytes }` */
|
|
25
|
-
export const bytes =
|
|
37
|
+
export const bytes = binary();
|
|
26
38
|
/** Apache Arrow Int64 type. Use as schema shorthand: `{ count: int }` */
|
|
27
|
-
export const int =
|
|
39
|
+
export const int = int64Type();
|
|
28
40
|
/** Apache Arrow Int32 type. Use as schema shorthand: `{ count: int32 }` */
|
|
29
|
-
export const int32 =
|
|
41
|
+
export const int32 = int32Type();
|
|
42
|
+
/** Apache Arrow Int16 type. Use as schema shorthand: `{ count: int16 }` */
|
|
43
|
+
export const int16 = int16Type();
|
|
44
|
+
/** Apache Arrow Int8 type. Use as schema shorthand: `{ count: int8 }` */
|
|
45
|
+
export const int8 = int8Type();
|
|
46
|
+
/** Apache Arrow Uint8 type. Use as schema shorthand: `{ count: uint8 }` */
|
|
47
|
+
export const uint8 = uint8Type();
|
|
48
|
+
/** Apache Arrow Uint16 type. Use as schema shorthand: `{ count: uint16 }` */
|
|
49
|
+
export const uint16 = uint16Type();
|
|
50
|
+
/** Apache Arrow Uint32 type. Use as schema shorthand: `{ count: uint32 }` */
|
|
51
|
+
export const uint32 = uint32Type();
|
|
52
|
+
/** Apache Arrow Uint64 type. Use as schema shorthand: `{ count: uint64 }` */
|
|
53
|
+
export const uint64 = uint64Type();
|
|
30
54
|
/** Apache Arrow Float64 type. Use as schema shorthand: `{ value: float }` */
|
|
31
|
-
export const float =
|
|
55
|
+
export const float = float64Type();
|
|
32
56
|
/** Apache Arrow Float32 type. Use as schema shorthand: `{ value: float32 }` */
|
|
33
|
-
export const float32 =
|
|
57
|
+
export const float32 = float32Type();
|
|
34
58
|
/** Apache Arrow Bool type. Use as schema shorthand: `{ flag: bool }` */
|
|
35
|
-
export const bool =
|
|
59
|
+
export const bool = boolType();
|
|
36
60
|
|
|
37
61
|
// ---------------------------------------------------------------------------
|
|
38
62
|
// SchemaLike — shorthand for declaring schemas
|
|
39
63
|
// ---------------------------------------------------------------------------
|
|
40
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Structural minimum that any backend's Schema must satisfy. arrow-js's
|
|
67
|
+
* `Schema`, vgi-typescript's `VgiSchema`, and flechette's `Schema` all match
|
|
68
|
+
* this shape. Used so vgi-rpc consumers don't have to know which Arrow
|
|
69
|
+
* library is on the other side of the wire.
|
|
70
|
+
*
|
|
71
|
+
* Kept exported for backwards compatibility — equivalent to `VgiSchema`.
|
|
72
|
+
*/
|
|
73
|
+
export interface SchemaShape {
|
|
74
|
+
readonly fields: ReadonlyArray<{
|
|
75
|
+
readonly name: string;
|
|
76
|
+
readonly type: { readonly typeId: number };
|
|
77
|
+
readonly nullable?: boolean;
|
|
78
|
+
readonly metadata?: Map<string, string>;
|
|
79
|
+
}>;
|
|
80
|
+
readonly metadata?: Map<string, string> | null;
|
|
81
|
+
}
|
|
82
|
+
|
|
41
83
|
/**
|
|
42
84
|
* A schema specification that accepts:
|
|
43
|
-
* - A real `
|
|
44
|
-
* -
|
|
85
|
+
* - A real `VgiSchema` (passed through)
|
|
86
|
+
* - Anything structurally `SchemaShape`
|
|
87
|
+
* - A record mapping field names to `VgiDataType` instances or `VgiField` instances
|
|
45
88
|
* - An empty `{}` for an empty schema
|
|
46
89
|
*/
|
|
47
|
-
export type SchemaLike =
|
|
90
|
+
export type SchemaLike = VgiSchema | SchemaShape | Record<string, VgiDataType | VgiField>;
|
|
91
|
+
|
|
92
|
+
function isField(x: unknown): x is VgiField {
|
|
93
|
+
return (
|
|
94
|
+
x != null &&
|
|
95
|
+
typeof (x as any).name === "string" &&
|
|
96
|
+
(x as any).type != null &&
|
|
97
|
+
typeof (x as any).nullable === "boolean"
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function isDataType(x: unknown): x is VgiDataType {
|
|
102
|
+
return x != null && typeof (x as any).typeId === "number";
|
|
103
|
+
}
|
|
48
104
|
|
|
49
105
|
/**
|
|
50
|
-
* Convert a SchemaLike spec into a real `
|
|
51
|
-
*
|
|
52
|
-
* - `Schema` → returned as-is
|
|
53
|
-
* - `Record<string, DataType>` → each entry becomes `new Field(name, type, false)`
|
|
54
|
-
* - `Record<string, Field>` → each entry is passed through
|
|
55
|
-
* - `{}` → `new Schema([])`
|
|
106
|
+
* Convert a SchemaLike spec into a real `VgiSchema`.
|
|
56
107
|
*/
|
|
57
|
-
export function toSchema(spec: SchemaLike):
|
|
58
|
-
|
|
108
|
+
export function toSchema(spec: SchemaLike): VgiSchema {
|
|
109
|
+
// VgiSchema / SchemaShape branch: anything with a `fields` array.
|
|
110
|
+
const maybeFields = (spec as { fields?: unknown }).fields;
|
|
111
|
+
if (Array.isArray(maybeFields)) {
|
|
112
|
+
const out: VgiField[] = [];
|
|
113
|
+
for (const f of maybeFields as ReadonlyArray<any>) {
|
|
114
|
+
if (isField(f)) {
|
|
115
|
+
out.push(f);
|
|
116
|
+
} else {
|
|
117
|
+
out.push(makeField(f.name, f.type, f.nullable ?? true, f.metadata));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return makeSchema(out);
|
|
121
|
+
}
|
|
59
122
|
|
|
60
|
-
const fields:
|
|
123
|
+
const fields: VgiField[] = [];
|
|
61
124
|
for (const [name, value] of Object.entries(spec)) {
|
|
62
|
-
if (value
|
|
125
|
+
if (isField(value)) {
|
|
63
126
|
fields.push(value);
|
|
64
|
-
} else if (value
|
|
65
|
-
fields.push(
|
|
127
|
+
} else if (isDataType(value)) {
|
|
128
|
+
fields.push(makeField(name, value, false));
|
|
66
129
|
} else {
|
|
67
130
|
throw new TypeError(`Invalid schema value for "${name}": expected DataType or Field, got ${typeof value}`);
|
|
68
131
|
}
|
|
69
132
|
}
|
|
70
|
-
return
|
|
133
|
+
return makeSchema(fields);
|
|
71
134
|
}
|
|
72
135
|
|
|
73
136
|
// ---------------------------------------------------------------------------
|
|
74
137
|
// inferParamTypes — derive paramTypes from a schema spec
|
|
75
138
|
// ---------------------------------------------------------------------------
|
|
76
139
|
|
|
77
|
-
const TYPE_MAP: [new (...args: any[]) => DataType, string][] = [
|
|
78
|
-
[Utf8, "str"],
|
|
79
|
-
[Binary, "bytes"],
|
|
80
|
-
[Bool, "bool"],
|
|
81
|
-
[Float64, "float"],
|
|
82
|
-
[Float32, "float"],
|
|
83
|
-
[Int64, "int"],
|
|
84
|
-
[Int32, "int"],
|
|
85
|
-
[Int16, "int"],
|
|
86
|
-
];
|
|
87
|
-
|
|
88
140
|
/**
|
|
89
141
|
* Derive a `paramTypes` record from a SchemaLike spec.
|
|
90
142
|
* Maps common Arrow scalar types to Python-style type strings.
|
|
91
143
|
* Returns `undefined` if any field has a complex type (List, Map_, Dictionary, etc.).
|
|
92
144
|
*/
|
|
93
145
|
export function inferParamTypes(spec: SchemaLike): Record<string, string> | undefined {
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
146
|
+
const sch = toSchema(spec);
|
|
147
|
+
if (sch.fields.length === 0) return undefined;
|
|
96
148
|
|
|
97
149
|
const result: Record<string, string> = {};
|
|
98
|
-
for (const
|
|
150
|
+
for (const f of sch.fields) {
|
|
99
151
|
let mapped: string | undefined;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
152
|
+
if (isUtf8(f.type)) mapped = "str";
|
|
153
|
+
else if (isBinary(f.type)) mapped = "bytes";
|
|
154
|
+
else if (isBool(f.type)) mapped = "bool";
|
|
155
|
+
else if (isFloat(f.type)) mapped = "float";
|
|
156
|
+
else if (isInt(f.type)) mapped = "int";
|
|
106
157
|
if (!mapped) return undefined;
|
|
107
|
-
result[
|
|
158
|
+
result[f.name] = mapped;
|
|
108
159
|
}
|
|
109
160
|
return result;
|
|
110
161
|
}
|