@useairfoil/flight 0.3.0 → 0.4.1
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/chunk-Bp6m_JJh.js +13 -0
- package/dist/{src/index.d.ts → index.d.ts} +96 -67
- package/dist/{src/index.js → index.js} +113 -101
- package/dist/index.js.map +1 -0
- package/dist/proto/Flight.proto +4 -11
- package/package.json +20 -33
- package/src/arrow-flight-client.ts +168 -0
- package/src/arrow-flight-sql-client.ts +147 -0
- package/src/arrow-utils.ts +5 -4
- package/src/flight-client-error.ts +27 -0
- package/src/flight-data-encoder.ts +5 -13
- package/src/index.ts +12 -8
- package/src/proto/google/protobuf/descriptor.ts +12 -1
- package/src/proto/google/protobuf/timestamp.ts +7 -6
- package/src/proto-utils.ts +1 -5
- package/src/record-batch-decoder.ts +32 -66
- package/src/record-batch-with-metadata.ts +6 -0
- package/dist/src/index.js.map +0 -1
- package/dist/test/index.d.ts +0 -30
- package/dist/test/index.js +0 -80
- package/dist/test/index.js.map +0 -1
- package/src/arrow-flight-sql.ts +0 -121
- package/src/arrow-flight.ts +0 -149
package/dist/proto/Flight.proto
CHANGED
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
syntax = "proto3";
|
|
20
|
-
import "google/protobuf/timestamp.proto";
|
|
21
20
|
|
|
22
21
|
package arrow.flight.protocol;
|
|
23
22
|
|
|
23
|
+
import "google/protobuf/timestamp.proto";
|
|
24
|
+
|
|
24
25
|
/*
|
|
25
26
|
* A flight service is an endpoint for retrieving or storing Arrow data. A
|
|
26
27
|
* flight service can expose one or more predefined endpoints that can be
|
|
@@ -28,7 +29,6 @@ package arrow.flight.protocol;
|
|
|
28
29
|
* can expose a set of actions that are available.
|
|
29
30
|
*/
|
|
30
31
|
service FlightService {
|
|
31
|
-
|
|
32
32
|
/*
|
|
33
33
|
* Handshake between client and server. Depending on the server, the
|
|
34
34
|
* handshake may be required to determine the token that should be used for
|
|
@@ -93,7 +93,7 @@ service FlightService {
|
|
|
93
93
|
* GetFlightInfo this interface may generate a new flight that was not previously
|
|
94
94
|
* available in ListFlights.
|
|
95
95
|
*/
|
|
96
|
-
|
|
96
|
+
rpc GetSchema(FlightDescriptor) returns (SchemaResult) {}
|
|
97
97
|
|
|
98
98
|
/*
|
|
99
99
|
* Retrieve a single stream associated with a particular descriptor
|
|
@@ -138,14 +138,12 @@ service FlightService {
|
|
|
138
138
|
* understand the capabilities of the flight service.
|
|
139
139
|
*/
|
|
140
140
|
rpc ListActions(Empty) returns (stream ActionType) {}
|
|
141
|
-
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
/*
|
|
145
144
|
* The request that a client provides to a server on handshake.
|
|
146
145
|
*/
|
|
147
146
|
message HandshakeRequest {
|
|
148
|
-
|
|
149
147
|
/*
|
|
150
148
|
* A defined protocol version
|
|
151
149
|
*/
|
|
@@ -158,7 +156,6 @@ message HandshakeRequest {
|
|
|
158
156
|
}
|
|
159
157
|
|
|
160
158
|
message HandshakeResponse {
|
|
161
|
-
|
|
162
159
|
/*
|
|
163
160
|
* A defined protocol version
|
|
164
161
|
*/
|
|
@@ -276,12 +273,10 @@ message SchemaResult {
|
|
|
276
273
|
* a flight or be used to expose a set of previously defined flights.
|
|
277
274
|
*/
|
|
278
275
|
message FlightDescriptor {
|
|
279
|
-
|
|
280
276
|
/*
|
|
281
277
|
* Describes what type of descriptor is defined.
|
|
282
278
|
*/
|
|
283
279
|
enum DescriptorType {
|
|
284
|
-
|
|
285
280
|
// Protobuf pattern, not used.
|
|
286
281
|
UNKNOWN = 0;
|
|
287
282
|
|
|
@@ -424,7 +419,6 @@ message PollInfo {
|
|
|
424
419
|
* A particular stream or split associated with a flight.
|
|
425
420
|
*/
|
|
426
421
|
message FlightEndpoint {
|
|
427
|
-
|
|
428
422
|
/*
|
|
429
423
|
* Token used to retrieve this stream.
|
|
430
424
|
*/
|
|
@@ -490,7 +484,6 @@ message Ticket {
|
|
|
490
484
|
* A batch of Arrow data as part of a stream of batches.
|
|
491
485
|
*/
|
|
492
486
|
message FlightData {
|
|
493
|
-
|
|
494
487
|
/*
|
|
495
488
|
* The descriptor of the data. This is only relevant when a client is
|
|
496
489
|
* starting a new DoPut stream.
|
|
@@ -521,4 +514,4 @@ message FlightData {
|
|
|
521
514
|
*/
|
|
522
515
|
message PutResult {
|
|
523
516
|
bytes app_metadata = 1;
|
|
524
|
-
}
|
|
517
|
+
}
|
package/package.json
CHANGED
|
@@ -1,50 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useairfoil/flight",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"repository": "useairfoil/typescript-sdk",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
7
|
"src",
|
|
8
8
|
"README.md"
|
|
9
9
|
],
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
12
13
|
"exports": {
|
|
13
14
|
".": {
|
|
14
|
-
"types": "./dist/
|
|
15
|
-
"import": "./dist/
|
|
16
|
-
"default": "./dist/
|
|
17
|
-
},
|
|
18
|
-
"./test": {
|
|
19
|
-
"types": "./dist/test/index.d.ts",
|
|
20
|
-
"import": "./dist/test/index.js",
|
|
21
|
-
"default": "./dist/test/index.js"
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"default": "./dist/index.js"
|
|
22
18
|
}
|
|
23
19
|
},
|
|
24
20
|
"scripts": {
|
|
25
21
|
"build": "tsdown",
|
|
26
22
|
"build:proto": "buf generate proto",
|
|
27
|
-
"typecheck": "tsc --noEmit"
|
|
28
|
-
"format": "biome format --write .",
|
|
29
|
-
"lint": "biome check .",
|
|
30
|
-
"lint:fix": "biome check . --write",
|
|
31
|
-
"test": "vitest",
|
|
32
|
-
"test:ci": "vitest run"
|
|
33
|
-
},
|
|
34
|
-
"peerDependencies": {
|
|
35
|
-
"effect": "^4.0.0-beta.25"
|
|
36
|
-
},
|
|
37
|
-
"optionalDependencies": {
|
|
38
|
-
"testcontainers": "^11.11.0"
|
|
39
|
-
},
|
|
40
|
-
"devDependencies": {
|
|
41
|
-
"@bufbuild/buf": "^1.57.2",
|
|
42
|
-
"@effect/vitest": "4.0.0-beta.25",
|
|
43
|
-
"@rollup/plugin-typescript": "^12.1.4",
|
|
44
|
-
"effect": "^4.0.0-beta.25",
|
|
45
|
-
"testcontainers": "^11.11.0",
|
|
46
|
-
"tsdown": "^0.15.6",
|
|
47
|
-
"vitest": "^3.2.4"
|
|
23
|
+
"typecheck": "tsc --noEmit"
|
|
48
24
|
},
|
|
49
25
|
"dependencies": {
|
|
50
26
|
"@bufbuild/protobuf": "^2.9.0",
|
|
@@ -54,5 +30,16 @@
|
|
|
54
30
|
"long": "^5.3.2",
|
|
55
31
|
"nice-grpc": "^2.1.13",
|
|
56
32
|
"nice-grpc-common": "^2.0.2"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@bufbuild/buf": "^1.5.7",
|
|
36
|
+
"@effect/vitest": "4.0.0-beta.83",
|
|
37
|
+
"@types/node": "^24.2.0",
|
|
38
|
+
"effect": "4.0.0-beta.83",
|
|
39
|
+
"tsdown": "^0.15.6",
|
|
40
|
+
"vitest": "^3.2.4"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"effect": "4.0.0-beta.83"
|
|
57
44
|
}
|
|
58
45
|
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type { RecordBatch, Schema } from "apache-arrow";
|
|
2
|
+
|
|
3
|
+
import { Config, Context, Effect, Layer, Scope, Stream } from "effect";
|
|
4
|
+
import {
|
|
5
|
+
type CallOptions,
|
|
6
|
+
createClient,
|
|
7
|
+
type DefaultCallOptions,
|
|
8
|
+
type NormalizedServiceDefinition,
|
|
9
|
+
} from "nice-grpc";
|
|
10
|
+
|
|
11
|
+
import type { RecordBatchWithMetadata } from "./record-batch-with-metadata";
|
|
12
|
+
|
|
13
|
+
import { decodeFlightDataStream, decodeSchemaFromFlightInfo } from "./arrow-utils";
|
|
14
|
+
import {
|
|
15
|
+
FlightDecodeError,
|
|
16
|
+
type FlightClientErrorLike,
|
|
17
|
+
FlightProtocolError,
|
|
18
|
+
FlightTransportError,
|
|
19
|
+
} from "./flight-client-error";
|
|
20
|
+
import { type ClientOptions, createChannelFromConfig, type HostOrChannel } from "./proto-utils";
|
|
21
|
+
import {
|
|
22
|
+
type FlightData,
|
|
23
|
+
type FlightDescriptor,
|
|
24
|
+
type FlightInfo,
|
|
25
|
+
type FlightServiceClient,
|
|
26
|
+
FlightServiceDefinition,
|
|
27
|
+
type HandshakeRequest,
|
|
28
|
+
type HandshakeResponse,
|
|
29
|
+
type PutResult,
|
|
30
|
+
type Ticket,
|
|
31
|
+
} from "./proto/Flight";
|
|
32
|
+
|
|
33
|
+
export type ArrowFlightClientOptions = HostOrChannel & {
|
|
34
|
+
readonly defaultCallOptions?: DefaultCallOptions<
|
|
35
|
+
NormalizedServiceDefinition<FlightServiceDefinition>
|
|
36
|
+
>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export interface ArrowFlightClientService {
|
|
40
|
+
readonly handshake: (
|
|
41
|
+
request: AsyncIterable<HandshakeRequest>,
|
|
42
|
+
options?: CallOptions,
|
|
43
|
+
) => Stream.Stream<HandshakeResponse, FlightClientErrorLike>;
|
|
44
|
+
readonly getFlightInfo: (
|
|
45
|
+
request: FlightDescriptor,
|
|
46
|
+
options?: CallOptions,
|
|
47
|
+
) => Effect.Effect<FlightInfo, FlightClientErrorLike>;
|
|
48
|
+
readonly doGet: (
|
|
49
|
+
request: Ticket,
|
|
50
|
+
options: { readonly schema: Schema } & CallOptions,
|
|
51
|
+
) => Stream.Stream<RecordBatchWithMetadata, FlightClientErrorLike>;
|
|
52
|
+
readonly doPut: (
|
|
53
|
+
request: AsyncIterable<FlightData>,
|
|
54
|
+
options?: CallOptions,
|
|
55
|
+
) => AsyncIterable<PutResult>;
|
|
56
|
+
readonly executeFlightInfo: (
|
|
57
|
+
info: FlightInfo,
|
|
58
|
+
options?: CallOptions,
|
|
59
|
+
) => Stream.Stream<RecordBatchWithMetadata, FlightClientErrorLike>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class ArrowFlightClient extends Context.Service<
|
|
63
|
+
ArrowFlightClient,
|
|
64
|
+
ArrowFlightClientService
|
|
65
|
+
>()("@useairfoil/flight/ArrowFlightClient") {}
|
|
66
|
+
|
|
67
|
+
const mapTransportError = (message: string, cause: unknown) =>
|
|
68
|
+
new FlightTransportError({
|
|
69
|
+
message,
|
|
70
|
+
cause,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const mapDecodeError = (message: string, cause: unknown) =>
|
|
74
|
+
new FlightDecodeError({
|
|
75
|
+
message,
|
|
76
|
+
cause,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const streamFromAsyncIterable = <A>(
|
|
80
|
+
iterable: AsyncIterable<A>,
|
|
81
|
+
message: string,
|
|
82
|
+
): Stream.Stream<A, FlightTransportError> =>
|
|
83
|
+
Stream.fromAsyncIterable(iterable, (cause) => mapTransportError(message, cause));
|
|
84
|
+
|
|
85
|
+
export const make = Effect.fnUntraced(function* (
|
|
86
|
+
options: ArrowFlightClientOptions,
|
|
87
|
+
): Effect.fn.Return<ArrowFlightClientService, never, Scope.Scope> {
|
|
88
|
+
const ownsChannel = "host" in options;
|
|
89
|
+
const channel = createChannelFromConfig(options);
|
|
90
|
+
const client: FlightServiceClient = createClient(
|
|
91
|
+
FlightServiceDefinition,
|
|
92
|
+
channel,
|
|
93
|
+
options.defaultCallOptions,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (ownsChannel) {
|
|
97
|
+
const scope = yield* Scope.Scope;
|
|
98
|
+
yield* Scope.addFinalizer(
|
|
99
|
+
scope,
|
|
100
|
+
Effect.sync(() => {
|
|
101
|
+
channel.close();
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const doGet = (
|
|
107
|
+
request: Ticket,
|
|
108
|
+
options: { readonly schema: Schema } & CallOptions,
|
|
109
|
+
): Stream.Stream<RecordBatchWithMetadata, FlightClientErrorLike> => {
|
|
110
|
+
const { schema: expectedSchema } = options;
|
|
111
|
+
return Stream.fromAsyncIterable(
|
|
112
|
+
decodeFlightDataStream(client.doGet(request, options), { expectedSchema }),
|
|
113
|
+
(cause) => mapDecodeError("Flight batch decoding failed", cause),
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const executeFlightInfo = (
|
|
118
|
+
info: FlightInfo,
|
|
119
|
+
options?: CallOptions,
|
|
120
|
+
): Stream.Stream<RecordBatchWithMetadata, FlightClientErrorLike> => {
|
|
121
|
+
const schema = decodeSchemaFromFlightInfo(info);
|
|
122
|
+
if (!schema) {
|
|
123
|
+
return Stream.fail(
|
|
124
|
+
new FlightProtocolError({
|
|
125
|
+
message: "FlightInfo must include a schema",
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return Stream.fromIterable(info.endpoint).pipe(
|
|
131
|
+
Stream.flatMap((endpoint) =>
|
|
132
|
+
endpoint.ticket === undefined
|
|
133
|
+
? Stream.empty
|
|
134
|
+
: doGet(endpoint.ticket, {
|
|
135
|
+
schema,
|
|
136
|
+
...options,
|
|
137
|
+
}),
|
|
138
|
+
),
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
return ArrowFlightClient.of({
|
|
143
|
+
handshake: (request, options) =>
|
|
144
|
+
streamFromAsyncIterable(client.handshake(request, options), "Flight handshake failed"),
|
|
145
|
+
getFlightInfo: (request, options) =>
|
|
146
|
+
Effect.tryPromise({
|
|
147
|
+
try: () => client.getFlightInfo(request, options),
|
|
148
|
+
catch: (cause) => mapTransportError("Flight getFlightInfo failed", cause),
|
|
149
|
+
}),
|
|
150
|
+
doGet,
|
|
151
|
+
doPut: (request, options) => client.doPut(request, options),
|
|
152
|
+
executeFlightInfo,
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
export const layer = (options: ArrowFlightClientOptions): Layer.Layer<ArrowFlightClient> =>
|
|
157
|
+
Layer.effect(ArrowFlightClient, make(options));
|
|
158
|
+
|
|
159
|
+
export const layerConfig = (options: Config.Wrap<ArrowFlightClientOptions>) =>
|
|
160
|
+
Layer.effect(
|
|
161
|
+
ArrowFlightClient,
|
|
162
|
+
Effect.gen(function* () {
|
|
163
|
+
const resolved = yield* Config.unwrap(options);
|
|
164
|
+
return yield* make(resolved);
|
|
165
|
+
}),
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
export type { CallOptions, ClientOptions, HostOrChannel, RecordBatch, RecordBatchWithMetadata };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { CallOptions } from "nice-grpc";
|
|
2
|
+
|
|
3
|
+
import { Config, Context, Effect, Layer, Scope, Stream } from "effect";
|
|
4
|
+
|
|
5
|
+
import type { FlightClientErrorLike } from "./flight-client-error";
|
|
6
|
+
import type { RemoveTypeUrl } from "./proto-utils";
|
|
7
|
+
import type { RecordBatchWithMetadata } from "./record-batch-with-metadata";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
make as makeArrowFlightClient,
|
|
11
|
+
type ArrowFlightClientOptions,
|
|
12
|
+
type ArrowFlightClientService,
|
|
13
|
+
} from "./arrow-flight-client";
|
|
14
|
+
import { Any } from "./proto/any";
|
|
15
|
+
import { FlightDescriptor, FlightDescriptor_DescriptorType, type FlightInfo } from "./proto/Flight";
|
|
16
|
+
import {
|
|
17
|
+
CommandGetCatalogs,
|
|
18
|
+
CommandGetDbSchemas,
|
|
19
|
+
CommandGetTables,
|
|
20
|
+
CommandGetTableTypes,
|
|
21
|
+
CommandStatementQuery,
|
|
22
|
+
} from "./proto/FlightSql";
|
|
23
|
+
|
|
24
|
+
export type ArrowFlightSqlClientOptions = ArrowFlightClientOptions;
|
|
25
|
+
|
|
26
|
+
export interface ArrowFlightSqlClientService {
|
|
27
|
+
readonly executeFlightInfo: (
|
|
28
|
+
info: FlightInfo,
|
|
29
|
+
options?: CallOptions,
|
|
30
|
+
) => Stream.Stream<RecordBatchWithMetadata, FlightClientErrorLike>;
|
|
31
|
+
readonly getCatalogs: (
|
|
32
|
+
request: RemoveTypeUrl<CommandGetCatalogs>,
|
|
33
|
+
options?: CallOptions,
|
|
34
|
+
) => Effect.Effect<FlightInfo, FlightClientErrorLike>;
|
|
35
|
+
readonly getDbSchemas: (
|
|
36
|
+
request: RemoveTypeUrl<CommandGetDbSchemas>,
|
|
37
|
+
options?: CallOptions,
|
|
38
|
+
) => Effect.Effect<FlightInfo, FlightClientErrorLike>;
|
|
39
|
+
readonly getTables: (
|
|
40
|
+
request: RemoveTypeUrl<CommandGetTables>,
|
|
41
|
+
options?: CallOptions,
|
|
42
|
+
) => Effect.Effect<FlightInfo, FlightClientErrorLike>;
|
|
43
|
+
readonly getTableTypes: (
|
|
44
|
+
request: RemoveTypeUrl<CommandGetTableTypes>,
|
|
45
|
+
options?: CallOptions,
|
|
46
|
+
) => Effect.Effect<FlightInfo, FlightClientErrorLike>;
|
|
47
|
+
readonly executeQuery: (
|
|
48
|
+
request: RemoveTypeUrl<CommandStatementQuery>,
|
|
49
|
+
options?: CallOptions,
|
|
50
|
+
) => Effect.Effect<FlightInfo, FlightClientErrorLike>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class ArrowFlightSqlClient extends Context.Service<
|
|
54
|
+
ArrowFlightSqlClient,
|
|
55
|
+
ArrowFlightSqlClientService
|
|
56
|
+
>()("@useairfoil/flight/ArrowFlightSqlClient") {}
|
|
57
|
+
|
|
58
|
+
export const make = Effect.fnUntraced(function* (
|
|
59
|
+
options: ArrowFlightSqlClientOptions,
|
|
60
|
+
): Effect.fn.Return<ArrowFlightSqlClientService, never, Scope.Scope> {
|
|
61
|
+
const inner: ArrowFlightClientService = yield* makeArrowFlightClient(options);
|
|
62
|
+
|
|
63
|
+
return ArrowFlightSqlClient.of({
|
|
64
|
+
executeFlightInfo: (info, options) => inner.executeFlightInfo(info, options),
|
|
65
|
+
getCatalogs: (request, options) =>
|
|
66
|
+
inner.getFlightInfo(
|
|
67
|
+
createCommandDescriptor(
|
|
68
|
+
CommandGetCatalogs.$type,
|
|
69
|
+
CommandGetCatalogs.encode({
|
|
70
|
+
$type: CommandGetCatalogs.$type,
|
|
71
|
+
...request,
|
|
72
|
+
}).finish(),
|
|
73
|
+
),
|
|
74
|
+
options,
|
|
75
|
+
),
|
|
76
|
+
getDbSchemas: (request, options) =>
|
|
77
|
+
inner.getFlightInfo(
|
|
78
|
+
createCommandDescriptor(
|
|
79
|
+
CommandGetDbSchemas.$type,
|
|
80
|
+
CommandGetDbSchemas.encode({
|
|
81
|
+
$type: CommandGetDbSchemas.$type,
|
|
82
|
+
...request,
|
|
83
|
+
}).finish(),
|
|
84
|
+
),
|
|
85
|
+
options,
|
|
86
|
+
),
|
|
87
|
+
getTables: (request, options) =>
|
|
88
|
+
inner.getFlightInfo(
|
|
89
|
+
createCommandDescriptor(
|
|
90
|
+
CommandGetTables.$type,
|
|
91
|
+
CommandGetTables.encode({
|
|
92
|
+
$type: CommandGetTables.$type,
|
|
93
|
+
...request,
|
|
94
|
+
}).finish(),
|
|
95
|
+
),
|
|
96
|
+
options,
|
|
97
|
+
),
|
|
98
|
+
getTableTypes: (request, options) =>
|
|
99
|
+
inner.getFlightInfo(
|
|
100
|
+
createCommandDescriptor(
|
|
101
|
+
CommandGetTableTypes.$type,
|
|
102
|
+
CommandGetTableTypes.encode({
|
|
103
|
+
$type: CommandGetTableTypes.$type,
|
|
104
|
+
...request,
|
|
105
|
+
}).finish(),
|
|
106
|
+
),
|
|
107
|
+
options,
|
|
108
|
+
),
|
|
109
|
+
executeQuery: (request, options) =>
|
|
110
|
+
inner.getFlightInfo(
|
|
111
|
+
createCommandDescriptor(
|
|
112
|
+
CommandStatementQuery.$type,
|
|
113
|
+
CommandStatementQuery.encode({
|
|
114
|
+
$type: CommandStatementQuery.$type,
|
|
115
|
+
...request,
|
|
116
|
+
}).finish(),
|
|
117
|
+
),
|
|
118
|
+
options,
|
|
119
|
+
),
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export const layer = (options: ArrowFlightSqlClientOptions): Layer.Layer<ArrowFlightSqlClient> =>
|
|
124
|
+
Layer.effect(ArrowFlightSqlClient, make(options));
|
|
125
|
+
|
|
126
|
+
export const layerConfig = (options: Config.Wrap<ArrowFlightSqlClientOptions>) =>
|
|
127
|
+
Layer.effect(
|
|
128
|
+
ArrowFlightSqlClient,
|
|
129
|
+
Effect.gen(function* () {
|
|
130
|
+
const resolved = yield* Config.unwrap(options);
|
|
131
|
+
return yield* make(resolved);
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
function createCommandDescriptor(typeUrl: string, value: Uint8Array): FlightDescriptor {
|
|
136
|
+
const cmd = Any.create({
|
|
137
|
+
typeUrl: `type.googleapis.com/${typeUrl}`,
|
|
138
|
+
value,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return FlightDescriptor.create({
|
|
142
|
+
type: FlightDescriptor_DescriptorType.CMD,
|
|
143
|
+
cmd: Any.encode(cmd).finish(),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export type { CallOptions, FlightInfo, RecordBatchWithMetadata };
|
package/src/arrow-utils.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Message, type Schema } from "apache-arrow";
|
|
2
|
+
|
|
2
3
|
import type { FlightData, FlightInfo } from "./proto/Flight";
|
|
4
|
+
import type { RecordBatchWithMetadata } from "./record-batch-with-metadata";
|
|
5
|
+
|
|
3
6
|
import { RecordBatchStreamReaderFromFlightData } from "./record-batch-decoder";
|
|
4
7
|
|
|
5
|
-
export function decodeSchemaFromFlightInfo(
|
|
6
|
-
info: FlightInfo,
|
|
7
|
-
): Schema | undefined {
|
|
8
|
+
export function decodeSchemaFromFlightInfo(info: FlightInfo): Schema | undefined {
|
|
8
9
|
// Notice that the `info.schema` field has the following format:
|
|
9
10
|
// The schema of the dataset in its IPC form:
|
|
10
11
|
// 4 bytes - an optional IPC_CONTINUATION_TOKEN prefix
|
|
@@ -24,7 +25,7 @@ export function getMessageSchema(message: Message): Schema | undefined {
|
|
|
24
25
|
export function decodeFlightDataStream(
|
|
25
26
|
stream: AsyncIterable<FlightData>,
|
|
26
27
|
{ expectedSchema: _expectedSchema }: { expectedSchema: Schema },
|
|
27
|
-
) {
|
|
28
|
+
): AsyncIterable<RecordBatchWithMetadata> {
|
|
28
29
|
// TODO: we want to validate the schema of the stream?
|
|
29
30
|
return new RecordBatchStreamReaderFromFlightData(stream);
|
|
30
31
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Data } from "effect";
|
|
2
|
+
|
|
3
|
+
export class FlightClientError extends Data.TaggedError("FlightClientError")<{
|
|
4
|
+
readonly message: string;
|
|
5
|
+
readonly cause?: unknown;
|
|
6
|
+
}> {}
|
|
7
|
+
|
|
8
|
+
export class FlightTransportError extends Data.TaggedError("FlightTransportError")<{
|
|
9
|
+
readonly message: string;
|
|
10
|
+
readonly cause?: unknown;
|
|
11
|
+
}> {}
|
|
12
|
+
|
|
13
|
+
export class FlightDecodeError extends Data.TaggedError("FlightDecodeError")<{
|
|
14
|
+
readonly message: string;
|
|
15
|
+
readonly cause?: unknown;
|
|
16
|
+
}> {}
|
|
17
|
+
|
|
18
|
+
export class FlightProtocolError extends Data.TaggedError("FlightProtocolError")<{
|
|
19
|
+
readonly message: string;
|
|
20
|
+
readonly cause?: unknown;
|
|
21
|
+
}> {}
|
|
22
|
+
|
|
23
|
+
export type FlightClientErrorLike =
|
|
24
|
+
| FlightClientError
|
|
25
|
+
| FlightTransportError
|
|
26
|
+
| FlightDecodeError
|
|
27
|
+
| FlightProtocolError;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Message, type RecordBatch, type Schema } from "apache-arrow";
|
|
2
2
|
import * as metadata from "apache-arrow/ipc/metadata/message";
|
|
3
3
|
import { VectorAssembler } from "apache-arrow/visitor/vectorassembler";
|
|
4
|
+
|
|
4
5
|
import { FlightData, type FlightDescriptor } from "./proto/Flight";
|
|
5
6
|
|
|
6
7
|
export const FlightDataEncoder = {
|
|
@@ -23,21 +24,12 @@ export const FlightDataEncoder = {
|
|
|
23
24
|
{
|
|
24
25
|
appMetadata,
|
|
25
26
|
}: {
|
|
26
|
-
appMetadata?: (args: {
|
|
27
|
-
index: number;
|
|
28
|
-
length: number;
|
|
29
|
-
}) => Uint8Array | undefined;
|
|
27
|
+
appMetadata?: (args: { index: number; length: number }) => Uint8Array | undefined;
|
|
30
28
|
} = {},
|
|
31
29
|
): ReadonlyArray<FlightData> {
|
|
32
|
-
const { byteLength, nodes, bufferRegions, buffers } =
|
|
33
|
-
VectorAssembler.assemble(batch);
|
|
30
|
+
const { byteLength, nodes, bufferRegions, buffers } = VectorAssembler.assemble(batch);
|
|
34
31
|
|
|
35
|
-
const metadataRecordBatch = new metadata.RecordBatch(
|
|
36
|
-
batch.numRows,
|
|
37
|
-
nodes,
|
|
38
|
-
bufferRegions,
|
|
39
|
-
null,
|
|
40
|
-
);
|
|
32
|
+
const metadataRecordBatch = new metadata.RecordBatch(batch.numRows, nodes, bufferRegions, null);
|
|
41
33
|
|
|
42
34
|
const message = Message.from(metadataRecordBatch, byteLength);
|
|
43
35
|
|
|
@@ -77,7 +69,7 @@ function encodeRecordBatchContent(
|
|
|
77
69
|
): Uint8Array {
|
|
78
70
|
const out = new Uint8Array(byteLength);
|
|
79
71
|
const bufGroupSize = compression != null ? 2 : 1;
|
|
80
|
-
const bufs =
|
|
72
|
+
const bufs = Array.from<ArrayBufferView<ArrayBufferLike>>({ length: bufGroupSize });
|
|
81
73
|
let pos = 0;
|
|
82
74
|
|
|
83
75
|
for (let i = 0; i < buffers.length; i += bufGroupSize) {
|
package/src/index.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export * as ArrowFlightClient from "./arrow-flight-client";
|
|
2
|
+
export * as ArrowFlightSqlClient from "./arrow-flight-sql-client";
|
|
3
|
+
export * as FlightClientError from "./flight-client-error";
|
|
4
|
+
export type { ArrowFlightClientOptions, ArrowFlightClientService } from "./arrow-flight-client";
|
|
5
|
+
export type {
|
|
6
|
+
ArrowFlightSqlClientOptions,
|
|
7
|
+
ArrowFlightSqlClientService,
|
|
8
|
+
} from "./arrow-flight-sql-client";
|
|
9
|
+
export type { FlightClientErrorLike } from "./flight-client-error";
|
|
4
10
|
export { FlightDataEncoder } from "./flight-data-encoder";
|
|
5
11
|
export {
|
|
6
12
|
FlightData,
|
|
7
13
|
FlightDescriptor,
|
|
8
14
|
FlightDescriptor_DescriptorType,
|
|
15
|
+
FlightInfo,
|
|
9
16
|
PutResult,
|
|
10
17
|
Ticket,
|
|
11
18
|
} from "./proto/Flight";
|
|
12
|
-
export {
|
|
13
|
-
|
|
14
|
-
createChannelFromConfig,
|
|
15
|
-
type HostOrChannel,
|
|
16
|
-
} from "./proto-utils";
|
|
19
|
+
export { type ClientOptions, createChannelFromConfig, type HostOrChannel } from "./proto-utils";
|
|
20
|
+
export type { RecordBatchWithMetadata } from "./record-batch-with-metadata";
|
|
@@ -34,6 +34,8 @@ PROTO3 = 999,
|
|
|
34
34
|
*/
|
|
35
35
|
2023 = 1000,
|
|
36
36
|
2024 = 1001,
|
|
37
|
+
/** UNSTABLE - A placeholder edition for developing and testing unscheduled features. */
|
|
38
|
+
UNSTABLE = 9999,
|
|
37
39
|
/**
|
|
38
40
|
* 1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be
|
|
39
41
|
* used or relied on outside of tests.
|
|
@@ -72,6 +74,9 @@ case 1000:
|
|
|
72
74
|
case 1001:
|
|
73
75
|
case "EDITION_2024":
|
|
74
76
|
return Edition.2024;
|
|
77
|
+
case 9999:
|
|
78
|
+
case "EDITION_UNSTABLE":
|
|
79
|
+
return Edition.UNSTABLE;
|
|
75
80
|
case 1:
|
|
76
81
|
case "EDITION_1_TEST_ONLY":
|
|
77
82
|
return Edition.1_TEST_ONLY;
|
|
@@ -105,6 +110,7 @@ case Edition.PROTO2: return "EDITION_PROTO2";
|
|
|
105
110
|
case Edition.PROTO3: return "EDITION_PROTO3";
|
|
106
111
|
case Edition.2023: return "EDITION_2023";
|
|
107
112
|
case Edition.2024: return "EDITION_2024";
|
|
113
|
+
case Edition.UNSTABLE: return "EDITION_UNSTABLE";
|
|
108
114
|
case Edition.1_TEST_ONLY: return "EDITION_1_TEST_ONLY";
|
|
109
115
|
case Edition.2_TEST_ONLY: return "EDITION_2_TEST_ONLY";
|
|
110
116
|
case Edition.99997_TEST_ONLY: return "EDITION_99997_TEST_ONLY";
|
|
@@ -1001,7 +1007,12 @@ readonly unverifiedLazy?: boolean | undefined,
|
|
|
1001
1007
|
* is a formalization for deprecating fields.
|
|
1002
1008
|
*/
|
|
1003
1009
|
readonly deprecated?: boolean | undefined,
|
|
1004
|
-
/**
|
|
1010
|
+
/**
|
|
1011
|
+
* DEPRECATED. DO NOT USE!
|
|
1012
|
+
* For Google-internal migration only. Do not use.
|
|
1013
|
+
*
|
|
1014
|
+
* @deprecated
|
|
1015
|
+
*/
|
|
1005
1016
|
readonly weak?: boolean | undefined,
|
|
1006
1017
|
/**
|
|
1007
1018
|
* Indicate that the field value should not be printed out when using debug
|
|
@@ -104,15 +104,16 @@ export const protobufPackage = "google.protobuf";
|
|
|
104
104
|
export interface Timestamp {
|
|
105
105
|
$type: "google.protobuf.Timestamp";
|
|
106
106
|
/**
|
|
107
|
-
* Represents seconds of UTC time since Unix epoch
|
|
108
|
-
*
|
|
109
|
-
* 9999-12-31T23:59:59Z
|
|
107
|
+
* Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must
|
|
108
|
+
* be between -315576000000 and 315576000000 inclusive (which corresponds to
|
|
109
|
+
* 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z).
|
|
110
110
|
*/
|
|
111
111
|
readonly seconds: bigint;
|
|
112
112
|
/**
|
|
113
|
-
* Non-negative fractions of a second at nanosecond resolution.
|
|
114
|
-
*
|
|
115
|
-
*
|
|
113
|
+
* Non-negative fractions of a second at nanosecond resolution. This field is
|
|
114
|
+
* the nanosecond portion of the duration, not an alternative to seconds.
|
|
115
|
+
* Negative second values with fractions must still have non-negative nanos
|
|
116
|
+
* values that count forward in time. Must be between 0 and 999,999,999
|
|
116
117
|
* inclusive.
|
|
117
118
|
*/
|
|
118
119
|
readonly nanos: number;
|
package/src/proto-utils.ts
CHANGED
|
@@ -28,11 +28,7 @@ export type HostOrChannel =
|
|
|
28
28
|
|
|
29
29
|
export function createChannelFromConfig(config: HostOrChannel): Channel {
|
|
30
30
|
if (config.host !== undefined) {
|
|
31
|
-
return createChannel(
|
|
32
|
-
config.host,
|
|
33
|
-
config.credentials,
|
|
34
|
-
config.channelOptions,
|
|
35
|
-
);
|
|
31
|
+
return createChannel(config.host, config.credentials, config.channelOptions);
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
return config.channel;
|