@query-farm/vgi-rpc 0.4.0 → 0.6.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/README.md +47 -0
- package/dist/client/connect.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/oauth.d.ts +36 -0
- package/dist/client/oauth.d.ts.map +1 -1
- package/dist/client/pipe.d.ts +3 -0
- package/dist/client/pipe.d.ts.map +1 -1
- package/dist/client/stream.d.ts +3 -0
- package/dist/client/stream.d.ts.map +1 -1
- package/dist/client/types.d.ts +4 -0
- package/dist/client/types.d.ts.map +1 -1
- package/dist/constants.d.ts +3 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/dispatch/describe.d.ts.map +1 -1
- package/dist/dispatch/stream.d.ts +2 -1
- package/dist/dispatch/stream.d.ts.map +1 -1
- package/dist/dispatch/unary.d.ts +2 -1
- package/dist/dispatch/unary.d.ts.map +1 -1
- package/dist/external.d.ts +45 -0
- package/dist/external.d.ts.map +1 -0
- package/dist/gcs.d.ts +38 -0
- package/dist/gcs.d.ts.map +1 -0
- package/dist/http/auth.d.ts +13 -2
- package/dist/http/auth.d.ts.map +1 -1
- package/dist/http/bearer.d.ts +34 -0
- package/dist/http/bearer.d.ts.map +1 -0
- package/dist/http/dispatch.d.ts +2 -0
- package/dist/http/dispatch.d.ts.map +1 -1
- package/dist/http/handler.d.ts.map +1 -1
- package/dist/http/index.d.ts +4 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/jwt.d.ts +2 -2
- package/dist/http/jwt.d.ts.map +1 -1
- package/dist/http/mtls.d.ts +78 -0
- package/dist/http/mtls.d.ts.map +1 -0
- package/dist/http/pages.d.ts +9 -0
- package/dist/http/pages.d.ts.map +1 -0
- package/dist/http/types.d.ts +17 -1
- package/dist/http/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1119 -230
- package/dist/index.js.map +24 -20
- package/dist/otel.d.ts +47 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/s3.d.ts +43 -0
- package/dist/s3.d.ts.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +44 -1
- package/src/client/connect.ts +13 -5
- package/src/client/index.ts +10 -1
- package/src/client/introspect.ts +1 -1
- package/src/client/oauth.ts +94 -1
- package/src/client/pipe.ts +19 -4
- package/src/client/stream.ts +20 -7
- package/src/client/types.ts +4 -0
- package/src/constants.ts +4 -1
- package/src/dispatch/describe.ts +20 -0
- package/src/dispatch/stream.ts +7 -1
- package/src/dispatch/unary.ts +6 -1
- package/src/external.ts +209 -0
- package/src/gcs.ts +86 -0
- package/src/http/auth.ts +67 -4
- package/src/http/bearer.ts +107 -0
- package/src/http/dispatch.ts +26 -6
- package/src/http/handler.ts +81 -4
- package/src/http/index.ts +10 -0
- package/src/http/jwt.ts +17 -3
- package/src/http/mtls.ts +298 -0
- package/src/http/pages.ts +298 -0
- package/src/http/types.ts +17 -1
- package/src/index.ts +25 -0
- package/src/otel.ts +161 -0
- package/src/s3.ts +94 -0
- package/src/server.ts +42 -8
- package/src/types.ts +34 -0
package/dist/otel.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry instrumentation for vgi-rpc TypeScript servers.
|
|
3
|
+
*
|
|
4
|
+
* Implements {@link DispatchHook} to add distributed tracing (spans) and
|
|
5
|
+
* metrics (request counter, duration histogram) to RPC dispatch.
|
|
6
|
+
*
|
|
7
|
+
* Requires `@opentelemetry/api` as a peer dependency.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { createOtelHook } from "vgi-rpc/otel";
|
|
12
|
+
* import { createHttpHandler } from "vgi-rpc";
|
|
13
|
+
*
|
|
14
|
+
* const handler = createHttpHandler(protocol, {
|
|
15
|
+
* dispatchHook: createOtelHook(),
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import { type Meter, type Tracer } from "@opentelemetry/api";
|
|
20
|
+
import type { DispatchHook } from "./types.js";
|
|
21
|
+
/** Configuration for OpenTelemetry instrumentation. */
|
|
22
|
+
export interface OtelConfig {
|
|
23
|
+
/** Custom TracerProvider; uses the global provider when omitted. */
|
|
24
|
+
tracerProvider?: {
|
|
25
|
+
getTracer(name: string): Tracer;
|
|
26
|
+
};
|
|
27
|
+
/** Custom MeterProvider; uses the global provider when omitted. */
|
|
28
|
+
meterProvider?: {
|
|
29
|
+
getMeter(name: string): Meter;
|
|
30
|
+
};
|
|
31
|
+
/** Enable span creation. Default: true. */
|
|
32
|
+
enableTracing?: boolean;
|
|
33
|
+
/** Enable counter/histogram recording. Default: true. */
|
|
34
|
+
enableMetrics?: boolean;
|
|
35
|
+
/** Record exceptions on error spans. Default: true. */
|
|
36
|
+
recordExceptions?: boolean;
|
|
37
|
+
/** Service name for the rpc.service attribute. Default: "TypeScriptRpcServer". */
|
|
38
|
+
serviceName?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a {@link DispatchHook} that instruments RPC calls with OpenTelemetry.
|
|
42
|
+
*
|
|
43
|
+
* Creates a span for each RPC call with method attributes, and records
|
|
44
|
+
* request count and duration metrics.
|
|
45
|
+
*/
|
|
46
|
+
export declare function createOtelHook(config?: OtelConfig): DispatchHook;
|
|
47
|
+
//# sourceMappingURL=otel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel.d.ts","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAIL,KAAK,KAAK,EAKV,KAAK,MAAM,EAEZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAkB,YAAY,EAA2B,MAAM,YAAY,CAAC;AAIxF,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,cAAc,CAAC,EAAE;QAAE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACrD,mEAAmE;IACnE,aAAa,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAC;IAClD,2CAA2C;IAC3C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yDAAyD;IACzD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAOD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,YAAY,CA+FhE"}
|
package/dist/s3.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 storage backend for external storage of large Arrow IPC batches.
|
|
3
|
+
*
|
|
4
|
+
* Requires `@aws-sdk/client-s3` and `@aws-sdk/s3-request-presigner`
|
|
5
|
+
* as peer dependencies.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { createS3Storage } from "@query-farm/vgi-rpc/s3";
|
|
10
|
+
*
|
|
11
|
+
* const storage = createS3Storage({
|
|
12
|
+
* bucket: "my-bucket",
|
|
13
|
+
* prefix: "vgi-rpc/",
|
|
14
|
+
* });
|
|
15
|
+
* const handler = createHttpHandler(protocol, {
|
|
16
|
+
* externalLocation: { storage, externalizeThresholdBytes: 1_048_576 },
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import type { ExternalStorage } from "./external.js";
|
|
21
|
+
/** Configuration for the S3 storage backend. */
|
|
22
|
+
export interface S3StorageConfig {
|
|
23
|
+
/** S3 bucket name. */
|
|
24
|
+
bucket: string;
|
|
25
|
+
/** Key prefix for uploaded objects. Default: "vgi-rpc/". */
|
|
26
|
+
prefix?: string;
|
|
27
|
+
/** Lifetime of pre-signed GET URLs in seconds. Default: 3600 (1 hour). */
|
|
28
|
+
presignExpirySeconds?: number;
|
|
29
|
+
/** AWS region. If omitted, uses default SDK config. */
|
|
30
|
+
region?: string;
|
|
31
|
+
/** Custom S3 endpoint URL (for MinIO, LocalStack, etc.). */
|
|
32
|
+
endpointUrl?: string;
|
|
33
|
+
/** Force path-style addressing (required for some S3-compatible services). */
|
|
34
|
+
forcePathStyle?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create an S3-backed ExternalStorage.
|
|
38
|
+
*
|
|
39
|
+
* Lazily imports `@aws-sdk/client-s3` and `@aws-sdk/s3-request-presigner`
|
|
40
|
+
* on first upload to avoid loading the AWS SDK unless needed.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createS3Storage(config: S3StorageConfig): ExternalStorage;
|
|
43
|
+
//# sourceMappingURL=s3.d.ts.map
|
package/dist/s3.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../src/s3.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CA8CxE"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { ExternalLocationConfig } from "./external.js";
|
|
1
2
|
import type { Protocol } from "./protocol.js";
|
|
3
|
+
import { type DispatchHook } from "./types.js";
|
|
2
4
|
/**
|
|
3
5
|
* RPC server that reads Arrow IPC requests from stdin and writes responses to stdout.
|
|
4
6
|
* Supports unary and streaming (producer/exchange) methods.
|
|
@@ -8,9 +10,13 @@ export declare class VgiRpcServer {
|
|
|
8
10
|
private enableDescribe;
|
|
9
11
|
private serverId;
|
|
10
12
|
private describeBatch;
|
|
13
|
+
private dispatchHook;
|
|
14
|
+
private externalConfig;
|
|
11
15
|
constructor(protocol: Protocol, options?: {
|
|
12
16
|
enableDescribe?: boolean;
|
|
13
17
|
serverId?: string;
|
|
18
|
+
dispatchHook?: DispatchHook;
|
|
19
|
+
externalLocation?: ExternalLocationConfig;
|
|
14
20
|
});
|
|
15
21
|
/** Start the server loop. Reads requests until stdin closes. */
|
|
16
22
|
run(): Promise<void>;
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAuB,KAAK,YAAY,EAAiC,MAAM,YAAY,CAAC;AAQnG;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA+D;IACpF,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAAqC;gBAGzD,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE;QACR,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,YAAY,CAAC;QAC5B,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;KAC3C;IAcH,gEAAgE;IAC1D,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;YAwCZ,QAAQ;CA+EvB"}
|
package/dist/types.d.ts
CHANGED
|
@@ -42,6 +42,36 @@ export interface MethodDefinition {
|
|
|
42
42
|
defaults?: Record<string, any>;
|
|
43
43
|
paramTypes?: Record<string, string>;
|
|
44
44
|
}
|
|
45
|
+
/** Metadata passed to dispatch hooks before and after RPC method execution. */
|
|
46
|
+
export interface DispatchInfo {
|
|
47
|
+
/** RPC method name. */
|
|
48
|
+
method: string;
|
|
49
|
+
/** "unary" or "stream". */
|
|
50
|
+
methodType: string;
|
|
51
|
+
/** Server identifier. */
|
|
52
|
+
serverId: string;
|
|
53
|
+
/** Client-supplied request identifier, or null. */
|
|
54
|
+
requestId: string | null;
|
|
55
|
+
}
|
|
56
|
+
/** Per-call I/O counters, matching Python's CallStatistics. */
|
|
57
|
+
export interface CallStatistics {
|
|
58
|
+
inputBatches: number;
|
|
59
|
+
outputBatches: number;
|
|
60
|
+
inputRows: number;
|
|
61
|
+
outputRows: number;
|
|
62
|
+
inputBytes: number;
|
|
63
|
+
outputBytes: number;
|
|
64
|
+
}
|
|
65
|
+
/** Opaque token returned by onDispatchStart, passed back to onDispatchEnd. */
|
|
66
|
+
export type HookToken = unknown;
|
|
67
|
+
/**
|
|
68
|
+
* Observability hook called around RPC dispatch.
|
|
69
|
+
* Implementations must be safe for concurrent use (HTTP transport is concurrent).
|
|
70
|
+
*/
|
|
71
|
+
export interface DispatchHook {
|
|
72
|
+
onDispatchStart(info: DispatchInfo): HookToken;
|
|
73
|
+
onDispatchEnd(token: HookToken, info: DispatchInfo, stats: CallStatistics, error?: Error): void;
|
|
74
|
+
}
|
|
45
75
|
export interface EmittedBatch {
|
|
46
76
|
batch: RecordBatch;
|
|
47
77
|
metadata?: Map<string, string>;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@query-farm/vgi-rpc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://vgi-rpc-typescript.query.farm",
|
|
6
6
|
"repository": {
|
|
@@ -15,6 +15,21 @@
|
|
|
15
15
|
"import": "./dist/index.js",
|
|
16
16
|
"types": "./dist/index.d.ts",
|
|
17
17
|
"bun": "./src/index.ts"
|
|
18
|
+
},
|
|
19
|
+
"./otel": {
|
|
20
|
+
"import": "./dist/otel.js",
|
|
21
|
+
"types": "./dist/otel.d.ts",
|
|
22
|
+
"bun": "./src/otel.ts"
|
|
23
|
+
},
|
|
24
|
+
"./s3": {
|
|
25
|
+
"import": "./dist/s3.js",
|
|
26
|
+
"types": "./dist/s3.d.ts",
|
|
27
|
+
"bun": "./src/s3.ts"
|
|
28
|
+
},
|
|
29
|
+
"./gcs": {
|
|
30
|
+
"import": "./dist/gcs.js",
|
|
31
|
+
"types": "./dist/gcs.d.ts",
|
|
32
|
+
"bun": "./src/gcs.ts"
|
|
18
33
|
}
|
|
19
34
|
},
|
|
20
35
|
"files": [
|
|
@@ -25,8 +40,36 @@
|
|
|
25
40
|
"@query-farm/apache-arrow": "*",
|
|
26
41
|
"oauth4webapi": "^3.8.5"
|
|
27
42
|
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@opentelemetry/api": ">=1.4.0",
|
|
45
|
+
"@aws-sdk/client-s3": ">=3.0.0",
|
|
46
|
+
"@aws-sdk/s3-request-presigner": ">=3.0.0",
|
|
47
|
+
"@google-cloud/storage": ">=7.0.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"@opentelemetry/api": {
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"@aws-sdk/client-s3": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
56
|
+
"@aws-sdk/s3-request-presigner": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@google-cloud/storage": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
},
|
|
28
63
|
"devDependencies": {
|
|
29
64
|
"@biomejs/biome": "^2.4.5",
|
|
65
|
+
"@opentelemetry/api": "^1.9.0",
|
|
66
|
+
"@opentelemetry/resources": "^2.6.0",
|
|
67
|
+
"@opentelemetry/sdk-metrics": "^2.6.0",
|
|
68
|
+
"@opentelemetry/sdk-trace-base": "^2.6.0",
|
|
69
|
+
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
70
|
+
"@aws-sdk/client-s3": "^3.750.0",
|
|
71
|
+
"@aws-sdk/s3-request-presigner": "^3.750.0",
|
|
72
|
+
"@google-cloud/storage": "^7.15.0",
|
|
30
73
|
"@types/bun": "latest"
|
|
31
74
|
},
|
|
32
75
|
"scripts": {
|
package/src/client/connect.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { RecordBatch, Schema } from "@query-farm/apache-arrow";
|
|
5
5
|
import { LOG_LEVEL_KEY, STATE_KEY } from "../constants.js";
|
|
6
6
|
import { RpcError } from "../errors.js";
|
|
7
|
+
import { isExternalLocationBatch, resolveExternalLocation } from "../external.js";
|
|
7
8
|
import { ARROW_CONTENT_TYPE } from "../http/common.js";
|
|
8
9
|
import { httpIntrospect, type MethodInfo, type ServiceDescription } from "./introspect.js";
|
|
9
10
|
import {
|
|
@@ -27,10 +28,11 @@ export interface RpcClient {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export function httpConnect(baseUrl: string, options?: HttpConnectOptions): RpcClient {
|
|
30
|
-
const prefix = (options?.prefix ?? "
|
|
31
|
+
const prefix = (options?.prefix ?? "").replace(/\/+$/, "");
|
|
31
32
|
const onLog = options?.onLog;
|
|
32
33
|
const compressionLevel = options?.compressionLevel;
|
|
33
34
|
const authorization = options?.authorization;
|
|
35
|
+
const externalConfig = options?.externalLocation;
|
|
34
36
|
|
|
35
37
|
let methodCache: Map<string, MethodInfo> | null = null;
|
|
36
38
|
let compressFn: CompressFn | undefined;
|
|
@@ -114,12 +116,17 @@ export function httpConnect(baseUrl: string, options?: HttpConnectOptions): RpcC
|
|
|
114
116
|
const responseBody = await readResponse(resp);
|
|
115
117
|
const { batches } = await readResponseBatches(responseBody);
|
|
116
118
|
|
|
117
|
-
// Process batches: dispatch logs, find result
|
|
119
|
+
// Process batches: dispatch logs, resolve external pointers, find result
|
|
118
120
|
let resultBatch: RecordBatch | null = null;
|
|
119
|
-
for (
|
|
121
|
+
for (let batch of batches) {
|
|
120
122
|
if (batch.numRows === 0) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
// Check for external location pointer batch
|
|
124
|
+
if (isExternalLocationBatch(batch)) {
|
|
125
|
+
batch = await resolveExternalLocation(batch, externalConfig);
|
|
126
|
+
} else {
|
|
127
|
+
dispatchLogOrError(batch, onLog);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
123
130
|
}
|
|
124
131
|
resultBatch = batch;
|
|
125
132
|
}
|
|
@@ -302,6 +309,7 @@ export function httpConnect(baseUrl: string, options?: HttpConnectOptions): RpcC
|
|
|
302
309
|
compressFn,
|
|
303
310
|
decompressFn,
|
|
304
311
|
authorization,
|
|
312
|
+
externalConfig,
|
|
305
313
|
});
|
|
306
314
|
},
|
|
307
315
|
|
package/src/client/index.ts
CHANGED
|
@@ -4,7 +4,16 @@
|
|
|
4
4
|
export { httpConnect, type RpcClient } from "./connect.js";
|
|
5
5
|
export { httpIntrospect, type MethodInfo, parseDescribeResponse, type ServiceDescription } from "./introspect.js";
|
|
6
6
|
export type { OAuthResourceMetadataResponse } from "./oauth.js";
|
|
7
|
-
export {
|
|
7
|
+
export {
|
|
8
|
+
fetchOAuthMetadata,
|
|
9
|
+
httpOAuthMetadata,
|
|
10
|
+
parseClientId,
|
|
11
|
+
parseClientSecret,
|
|
12
|
+
parseDeviceCodeClientId,
|
|
13
|
+
parseDeviceCodeClientSecret,
|
|
14
|
+
parseResourceMetadataUrl,
|
|
15
|
+
parseUseIdTokenAsBearer,
|
|
16
|
+
} from "./oauth.js";
|
|
8
17
|
export { PipeStreamSession, pipeConnect, subprocessConnect } from "./pipe.js";
|
|
9
18
|
export { HttpStreamSession } from "./stream.js";
|
|
10
19
|
export type {
|
package/src/client/introspect.ts
CHANGED
|
@@ -121,7 +121,7 @@ export async function httpIntrospect(
|
|
|
121
121
|
baseUrl: string,
|
|
122
122
|
options?: { prefix?: string; authorization?: string },
|
|
123
123
|
): Promise<ServiceDescription> {
|
|
124
|
-
const prefix = options?.prefix ?? "
|
|
124
|
+
const prefix = options?.prefix ?? "";
|
|
125
125
|
const emptySchema = new ArrowSchema([]);
|
|
126
126
|
const body = buildRequestIpc(emptySchema, {}, DESCRIBE_METHOD_NAME);
|
|
127
127
|
|
package/src/client/oauth.ts
CHANGED
|
@@ -7,10 +7,21 @@ export interface OAuthResourceMetadataResponse {
|
|
|
7
7
|
authorizationServers: string[];
|
|
8
8
|
scopesSupported?: string[];
|
|
9
9
|
bearerMethodsSupported?: string[];
|
|
10
|
+
resourceSigningAlgValuesSupported?: string[];
|
|
10
11
|
resourceName?: string;
|
|
11
12
|
resourceDocumentation?: string;
|
|
12
13
|
resourcePolicyUri?: string;
|
|
13
14
|
resourceTosUri?: string;
|
|
15
|
+
/** OAuth client_id advertised by the server. */
|
|
16
|
+
clientId?: string;
|
|
17
|
+
/** OAuth client_secret advertised by the server. */
|
|
18
|
+
clientSecret?: string;
|
|
19
|
+
/** When true, use the OIDC id_token as the Bearer token instead of access_token. */
|
|
20
|
+
useIdTokenAsBearer?: boolean;
|
|
21
|
+
/** OAuth client_id for device code flow. */
|
|
22
|
+
deviceCodeClientId?: string;
|
|
23
|
+
/** OAuth client_secret for device code flow. */
|
|
24
|
+
deviceCodeClientSecret?: string;
|
|
14
25
|
}
|
|
15
26
|
|
|
16
27
|
function parseMetadataJson(json: Record<string, any>): OAuthResourceMetadataResponse {
|
|
@@ -20,10 +31,17 @@ function parseMetadataJson(json: Record<string, any>): OAuthResourceMetadataResp
|
|
|
20
31
|
};
|
|
21
32
|
if (json.scopes_supported) result.scopesSupported = json.scopes_supported;
|
|
22
33
|
if (json.bearer_methods_supported) result.bearerMethodsSupported = json.bearer_methods_supported;
|
|
34
|
+
if (json.resource_signing_alg_values_supported)
|
|
35
|
+
result.resourceSigningAlgValuesSupported = json.resource_signing_alg_values_supported;
|
|
23
36
|
if (json.resource_name) result.resourceName = json.resource_name;
|
|
24
37
|
if (json.resource_documentation) result.resourceDocumentation = json.resource_documentation;
|
|
25
38
|
if (json.resource_policy_uri) result.resourcePolicyUri = json.resource_policy_uri;
|
|
26
39
|
if (json.resource_tos_uri) result.resourceTosUri = json.resource_tos_uri;
|
|
40
|
+
if (json.client_id) result.clientId = json.client_id;
|
|
41
|
+
if (json.client_secret) result.clientSecret = json.client_secret;
|
|
42
|
+
if (json.use_id_token_as_bearer) result.useIdTokenAsBearer = json.use_id_token_as_bearer;
|
|
43
|
+
if (json.device_code_client_id) result.deviceCodeClientId = json.device_code_client_id;
|
|
44
|
+
if (json.device_code_client_secret) result.deviceCodeClientSecret = json.device_code_client_secret;
|
|
27
45
|
return result;
|
|
28
46
|
}
|
|
29
47
|
|
|
@@ -35,7 +53,7 @@ export async function httpOAuthMetadata(
|
|
|
35
53
|
baseUrl: string,
|
|
36
54
|
prefix?: string,
|
|
37
55
|
): Promise<OAuthResourceMetadataResponse | null> {
|
|
38
|
-
const effectivePrefix = (prefix ?? "
|
|
56
|
+
const effectivePrefix = (prefix ?? "").replace(/\/+$/, "");
|
|
39
57
|
const metadataUrl = `${baseUrl.replace(/\/+$/, "")}/.well-known/oauth-protected-resource${effectivePrefix}`;
|
|
40
58
|
|
|
41
59
|
try {
|
|
@@ -72,3 +90,78 @@ export function parseResourceMetadataUrl(wwwAuthenticate: string): string | null
|
|
|
72
90
|
|
|
73
91
|
return metadataMatch[1];
|
|
74
92
|
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extract the `client_id` from a WWW-Authenticate Bearer challenge.
|
|
96
|
+
* Returns `null` if no client_id parameter is found.
|
|
97
|
+
*/
|
|
98
|
+
export function parseClientId(wwwAuthenticate: string): string | null {
|
|
99
|
+
const bearerMatch = wwwAuthenticate.match(/^Bearer\s+(.*)/i);
|
|
100
|
+
if (!bearerMatch) return null;
|
|
101
|
+
|
|
102
|
+
const params = bearerMatch[1];
|
|
103
|
+
const clientIdMatch = params.match(/client_id="([^"]+)"/);
|
|
104
|
+
if (!clientIdMatch) return null;
|
|
105
|
+
|
|
106
|
+
return clientIdMatch[1];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Extract the `client_secret` from a WWW-Authenticate Bearer challenge.
|
|
111
|
+
* Returns `null` if no client_secret parameter is found.
|
|
112
|
+
*/
|
|
113
|
+
export function parseClientSecret(wwwAuthenticate: string): string | null {
|
|
114
|
+
const bearerMatch = wwwAuthenticate.match(/^Bearer\s+(.*)/i);
|
|
115
|
+
if (!bearerMatch) return null;
|
|
116
|
+
|
|
117
|
+
const params = bearerMatch[1];
|
|
118
|
+
const match = params.match(/client_secret="([^"]+)"/);
|
|
119
|
+
if (!match) return null;
|
|
120
|
+
|
|
121
|
+
return match[1];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Extract the `use_id_token_as_bearer` flag from a WWW-Authenticate Bearer challenge.
|
|
126
|
+
* Returns `true` if the parameter is present and set to "true", `false` otherwise.
|
|
127
|
+
*/
|
|
128
|
+
export function parseUseIdTokenAsBearer(wwwAuthenticate: string): boolean {
|
|
129
|
+
const bearerMatch = wwwAuthenticate.match(/^Bearer\s+(.*)/i);
|
|
130
|
+
if (!bearerMatch) return false;
|
|
131
|
+
|
|
132
|
+
const params = bearerMatch[1];
|
|
133
|
+
const match = params.match(/use_id_token_as_bearer="([^"]+)"/);
|
|
134
|
+
if (!match) return false;
|
|
135
|
+
|
|
136
|
+
return match[1] === "true";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Extract the `device_code_client_id` from a WWW-Authenticate Bearer challenge.
|
|
141
|
+
* Returns `null` if no device_code_client_id parameter is found.
|
|
142
|
+
*/
|
|
143
|
+
export function parseDeviceCodeClientId(wwwAuthenticate: string): string | null {
|
|
144
|
+
const bearerMatch = wwwAuthenticate.match(/^Bearer\s+(.*)/i);
|
|
145
|
+
if (!bearerMatch) return null;
|
|
146
|
+
|
|
147
|
+
const params = bearerMatch[1];
|
|
148
|
+
const match = params.match(/device_code_client_id="([^"]+)"/);
|
|
149
|
+
if (!match) return null;
|
|
150
|
+
|
|
151
|
+
return match[1];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Extract the `device_code_client_secret` from a WWW-Authenticate Bearer challenge.
|
|
156
|
+
* Returns `null` if no device_code_client_secret parameter is found.
|
|
157
|
+
*/
|
|
158
|
+
export function parseDeviceCodeClientSecret(wwwAuthenticate: string): string | null {
|
|
159
|
+
const bearerMatch = wwwAuthenticate.match(/^Bearer\s+(.*)/i);
|
|
160
|
+
if (!bearerMatch) return null;
|
|
161
|
+
|
|
162
|
+
const params = bearerMatch[1];
|
|
163
|
+
const match = params.match(/device_code_client_secret="([^"]+)"/);
|
|
164
|
+
if (!match) return null;
|
|
165
|
+
|
|
166
|
+
return match[1];
|
|
167
|
+
}
|
package/src/client/pipe.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "@query-farm/apache-arrow";
|
|
13
13
|
import { DESCRIBE_METHOD_NAME } from "../constants.js";
|
|
14
14
|
import { RpcError } from "../errors.js";
|
|
15
|
+
import { type ExternalLocationConfig, isExternalLocationBatch, resolveExternalLocation } from "../external.js";
|
|
15
16
|
import { serializeIpcStream } from "../http/common.js";
|
|
16
17
|
import { IpcStreamReader } from "../wire/reader.js";
|
|
17
18
|
import type { RpcClient } from "./connect.js";
|
|
@@ -86,6 +87,7 @@ export class PipeStreamSession implements StreamSession {
|
|
|
86
87
|
private _outputSchema: Schema;
|
|
87
88
|
private _releaseBusy: () => void;
|
|
88
89
|
private _setDrainPromise: (p: Promise<void>) => void;
|
|
90
|
+
private _externalConfig?: ExternalLocationConfig;
|
|
89
91
|
|
|
90
92
|
constructor(opts: {
|
|
91
93
|
reader: IpcStreamReader;
|
|
@@ -95,6 +97,7 @@ export class PipeStreamSession implements StreamSession {
|
|
|
95
97
|
outputSchema: Schema;
|
|
96
98
|
releaseBusy: () => void;
|
|
97
99
|
setDrainPromise: (p: Promise<void>) => void;
|
|
100
|
+
externalConfig?: ExternalLocationConfig;
|
|
98
101
|
}) {
|
|
99
102
|
this._reader = opts.reader;
|
|
100
103
|
this._writeFn = opts.writeFn;
|
|
@@ -103,6 +106,7 @@ export class PipeStreamSession implements StreamSession {
|
|
|
103
106
|
this._outputSchema = opts.outputSchema;
|
|
104
107
|
this._releaseBusy = opts.releaseBusy;
|
|
105
108
|
this._setDrainPromise = opts.setDrainPromise;
|
|
109
|
+
this._externalConfig = opts.externalConfig;
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
get header(): Record<string, any> | null {
|
|
@@ -120,6 +124,10 @@ export class PipeStreamSession implements StreamSession {
|
|
|
120
124
|
if (batch === null) return null; // Server closed output stream
|
|
121
125
|
|
|
122
126
|
if (batch.numRows === 0) {
|
|
127
|
+
// Check for external location pointer batch
|
|
128
|
+
if (isExternalLocationBatch(batch)) {
|
|
129
|
+
return await resolveExternalLocation(batch, this._externalConfig);
|
|
130
|
+
}
|
|
123
131
|
// Check if it's a log/error batch. If so, dispatch and continue.
|
|
124
132
|
// Otherwise it's a zero-row data batch — return it.
|
|
125
133
|
if (dispatchLogOrError(batch, this._onLog)) {
|
|
@@ -375,6 +383,7 @@ export function pipeConnect(
|
|
|
375
383
|
options?: PipeConnectOptions,
|
|
376
384
|
): RpcClient {
|
|
377
385
|
const onLog = options?.onLog;
|
|
386
|
+
const externalConfig = options?.externalLocation;
|
|
378
387
|
|
|
379
388
|
let reader: IpcStreamReader | null = null;
|
|
380
389
|
let readerPromise: Promise<IpcStreamReader> | null = null;
|
|
@@ -483,12 +492,16 @@ export function pipeConnect(
|
|
|
483
492
|
throw new Error("EOF reading response");
|
|
484
493
|
}
|
|
485
494
|
|
|
486
|
-
// Process batches: dispatch logs, find result
|
|
495
|
+
// Process batches: dispatch logs, resolve external pointers, find result
|
|
487
496
|
let resultBatch: RecordBatch | null = null;
|
|
488
|
-
for (
|
|
497
|
+
for (let batch of response.batches) {
|
|
489
498
|
if (batch.numRows === 0) {
|
|
490
|
-
|
|
491
|
-
|
|
499
|
+
if (isExternalLocationBatch(batch)) {
|
|
500
|
+
batch = await resolveExternalLocation(batch, externalConfig);
|
|
501
|
+
} else {
|
|
502
|
+
dispatchLogOrError(batch, onLog);
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
492
505
|
}
|
|
493
506
|
resultBatch = batch;
|
|
494
507
|
}
|
|
@@ -557,6 +570,7 @@ export function pipeConnect(
|
|
|
557
570
|
outputSchema,
|
|
558
571
|
releaseBusy,
|
|
559
572
|
setDrainPromise,
|
|
573
|
+
externalConfig,
|
|
560
574
|
});
|
|
561
575
|
} catch (e) {
|
|
562
576
|
// Init error (e.g., server raised exception during init).
|
|
@@ -624,6 +638,7 @@ export function subprocessConnect(cmd: string[], options?: SubprocessConnectOpti
|
|
|
624
638
|
|
|
625
639
|
const client = pipeConnect(stdout, writable, {
|
|
626
640
|
onLog: options?.onLog,
|
|
641
|
+
externalLocation: options?.externalLocation,
|
|
627
642
|
});
|
|
628
643
|
|
|
629
644
|
// Wrap close to also kill the subprocess
|
package/src/client/stream.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { Field, makeData, RecordBatch, Schema, Struct, vectorFromArray } from "@query-farm/apache-arrow";
|
|
5
5
|
import { STATE_KEY } from "../constants.js";
|
|
6
6
|
import { RpcError } from "../errors.js";
|
|
7
|
+
import { type ExternalLocationConfig, isExternalLocationBatch, resolveExternalLocation } from "../external.js";
|
|
7
8
|
import { ARROW_CONTENT_TYPE, serializeIpcStream } from "../http/common.js";
|
|
8
9
|
import { dispatchLogOrError, extractBatchRows, inferArrowType, readResponseBatches } from "./ipc.js";
|
|
9
10
|
import type { LogMessage, StreamSession } from "./types.js";
|
|
@@ -26,6 +27,7 @@ export class HttpStreamSession implements StreamSession {
|
|
|
26
27
|
private _compressFn?: CompressFn;
|
|
27
28
|
private _decompressFn?: DecompressFn;
|
|
28
29
|
private _authorization?: string;
|
|
30
|
+
private _externalConfig?: ExternalLocationConfig;
|
|
29
31
|
|
|
30
32
|
constructor(opts: {
|
|
31
33
|
baseUrl: string;
|
|
@@ -42,6 +44,7 @@ export class HttpStreamSession implements StreamSession {
|
|
|
42
44
|
compressFn?: CompressFn;
|
|
43
45
|
decompressFn?: DecompressFn;
|
|
44
46
|
authorization?: string;
|
|
47
|
+
externalConfig?: ExternalLocationConfig;
|
|
45
48
|
}) {
|
|
46
49
|
this._baseUrl = opts.baseUrl;
|
|
47
50
|
this._prefix = opts.prefix;
|
|
@@ -57,6 +60,7 @@ export class HttpStreamSession implements StreamSession {
|
|
|
57
60
|
this._compressFn = opts.compressFn;
|
|
58
61
|
this._decompressFn = opts.decompressFn;
|
|
59
62
|
this._authorization = opts.authorization;
|
|
63
|
+
this._externalConfig = opts.externalConfig;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
get header(): Record<string, any> | null {
|
|
@@ -211,10 +215,14 @@ export class HttpStreamSession implements StreamSession {
|
|
|
211
215
|
*/
|
|
212
216
|
async *[Symbol.asyncIterator](): AsyncIterableIterator<Record<string, any>[]> {
|
|
213
217
|
// Yield pre-loaded batches from init
|
|
214
|
-
for (
|
|
218
|
+
for (let batch of this._pendingBatches) {
|
|
215
219
|
if (batch.numRows === 0) {
|
|
216
|
-
|
|
217
|
-
|
|
220
|
+
if (isExternalLocationBatch(batch)) {
|
|
221
|
+
batch = await resolveExternalLocation(batch, this._externalConfig);
|
|
222
|
+
} else {
|
|
223
|
+
dispatchLogOrError(batch, this._onLog);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
218
226
|
}
|
|
219
227
|
yield extractBatchRows(batch);
|
|
220
228
|
}
|
|
@@ -229,7 +237,7 @@ export class HttpStreamSession implements StreamSession {
|
|
|
229
237
|
const { batches } = await readResponseBatches(responseBody);
|
|
230
238
|
|
|
231
239
|
let gotContinuation = false;
|
|
232
|
-
for (
|
|
240
|
+
for (let batch of batches) {
|
|
233
241
|
if (batch.numRows === 0) {
|
|
234
242
|
// Check for continuation token
|
|
235
243
|
const token = batch.metadata?.get(STATE_KEY);
|
|
@@ -238,9 +246,14 @@ export class HttpStreamSession implements StreamSession {
|
|
|
238
246
|
gotContinuation = true;
|
|
239
247
|
continue;
|
|
240
248
|
}
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
249
|
+
// Check for external location pointer
|
|
250
|
+
if (isExternalLocationBatch(batch)) {
|
|
251
|
+
batch = await resolveExternalLocation(batch, this._externalConfig);
|
|
252
|
+
} else {
|
|
253
|
+
// Log/error batch
|
|
254
|
+
dispatchLogOrError(batch, this._onLog);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
244
257
|
}
|
|
245
258
|
|
|
246
259
|
yield extractBatchRows(batch);
|
package/src/client/types.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface HttpConnectOptions {
|
|
|
7
7
|
compressionLevel?: number;
|
|
8
8
|
/** Authorization header value (e.g. "Bearer <token>"). Sent with every request. */
|
|
9
9
|
authorization?: string;
|
|
10
|
+
/** External storage config for resolving externalized batches. */
|
|
11
|
+
externalLocation?: import("../external.js").ExternalLocationConfig;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export interface LogMessage {
|
|
@@ -24,6 +26,8 @@ export interface StreamSession {
|
|
|
24
26
|
|
|
25
27
|
export interface PipeConnectOptions {
|
|
26
28
|
onLog?: (msg: LogMessage) => void;
|
|
29
|
+
/** External storage config for resolving externalized batches. */
|
|
30
|
+
externalLocation?: import("../external.js").ExternalLocationConfig;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
export interface SubprocessConnectOptions extends PipeConnectOptions {
|
package/src/constants.ts
CHANGED
|
@@ -15,8 +15,11 @@ export const REQUEST_ID_KEY = "vgi_rpc.request_id";
|
|
|
15
15
|
|
|
16
16
|
export const PROTOCOL_NAME_KEY = "vgi_rpc.protocol_name";
|
|
17
17
|
export const DESCRIBE_VERSION_KEY = "vgi_rpc.describe_version";
|
|
18
|
-
export const DESCRIBE_VERSION = "
|
|
18
|
+
export const DESCRIBE_VERSION = "3";
|
|
19
19
|
|
|
20
20
|
export const DESCRIBE_METHOD_NAME = "__describe__";
|
|
21
21
|
|
|
22
22
|
export const STATE_KEY = "vgi_rpc.stream_state#b64";
|
|
23
|
+
|
|
24
|
+
export const LOCATION_KEY = "vgi_rpc.location";
|
|
25
|
+
export const LOCATION_SHA256_KEY = "vgi_rpc.location.sha256";
|