@dbx-tools/cli 0.9.54 → 0.9.60

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.
Files changed (69) hide show
  1. package/README.md +548 -58
  2. package/bin/dbx-graphiti.ts +5 -0
  3. package/bin/dbx-lakebase-proxy.ts +4 -0
  4. package/bin/dbx-model-gateway.ts +5 -0
  5. package/index.ts +35 -1
  6. package/lib/bin/dbx-graphiti.d.ts +2 -0
  7. package/lib/bin/dbx-graphiti.js +4 -0
  8. package/lib/bin/dbx-lakebase-proxy.d.ts +2 -0
  9. package/lib/bin/dbx-lakebase-proxy.js +4 -0
  10. package/lib/bin/dbx-model-gateway.d.ts +2 -0
  11. package/lib/bin/dbx-model-gateway.js +4 -0
  12. package/lib/index.d.ts +35 -1
  13. package/lib/index.js +26 -2
  14. package/lib/src/appkit/cli.d.ts +24 -0
  15. package/lib/src/appkit/cli.js +54 -0
  16. package/lib/src/appkit/env-export.d.ts +40 -0
  17. package/lib/src/appkit/env-export.js +99 -0
  18. package/lib/src/auth/cli.d.ts +20 -0
  19. package/lib/src/auth/cli.js +118 -0
  20. package/lib/src/auth/options.d.ts +41 -0
  21. package/lib/src/auth/options.js +64 -0
  22. package/lib/src/cli.d.ts +2 -0
  23. package/lib/src/cli.js +13 -7
  24. package/lib/src/graphiti/cli.d.ts +18 -0
  25. package/lib/src/graphiti/cli.js +43 -0
  26. package/lib/src/graphiti/options.d.ts +10 -0
  27. package/lib/src/graphiti/options.js +10 -0
  28. package/lib/src/lakebase-proxy/cancellation.d.ts +22 -0
  29. package/lib/src/lakebase-proxy/cancellation.js +100 -0
  30. package/lib/src/lakebase-proxy/cli.d.ts +13 -0
  31. package/lib/src/lakebase-proxy/cli.js +54 -0
  32. package/lib/src/lakebase-proxy/options.d.ts +23 -0
  33. package/lib/src/lakebase-proxy/options.js +41 -0
  34. package/lib/src/lakebase-proxy/protocol.d.ts +37 -0
  35. package/lib/src/lakebase-proxy/protocol.js +124 -0
  36. package/lib/src/lakebase-proxy/proxy.d.ts +22 -0
  37. package/lib/src/lakebase-proxy/proxy.js +200 -0
  38. package/lib/src/model-gateway/cli.d.ts +19 -0
  39. package/lib/src/model-gateway/cli.js +63 -0
  40. package/lib/src/model-gateway/server.d.ts +13 -0
  41. package/lib/src/model-gateway/server.js +53 -0
  42. package/lib/src/tunnel/app.d.ts +20 -0
  43. package/lib/src/tunnel/app.js +52 -0
  44. package/lib/src/tunnel/cli.d.ts +27 -0
  45. package/lib/src/tunnel/cli.js +190 -0
  46. package/lib/src/tunnel/options.d.ts +72 -0
  47. package/lib/src/tunnel/options.js +138 -0
  48. package/lib/src/tunnel/proxy.d.ts +51 -0
  49. package/lib/src/tunnel/proxy.js +143 -0
  50. package/lib/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +124 -9
  52. package/src/appkit/cli.ts +72 -0
  53. package/src/appkit/env-export.ts +124 -0
  54. package/src/auth/cli.ts +165 -0
  55. package/src/auth/options.ts +79 -0
  56. package/src/cli.ts +22 -6
  57. package/src/graphiti/cli.ts +75 -0
  58. package/src/graphiti/options.ts +20 -0
  59. package/src/lakebase-proxy/cancellation.ts +116 -0
  60. package/src/lakebase-proxy/cli.ts +80 -0
  61. package/src/lakebase-proxy/options.ts +56 -0
  62. package/src/lakebase-proxy/protocol.ts +170 -0
  63. package/src/lakebase-proxy/proxy.ts +256 -0
  64. package/src/model-gateway/cli.ts +89 -0
  65. package/src/model-gateway/server.ts +62 -0
  66. package/src/tunnel/app.ts +58 -0
  67. package/src/tunnel/cli.ts +218 -0
  68. package/src/tunnel/options.ts +169 -0
  69. package/src/tunnel/proxy.ts +194 -0
@@ -0,0 +1,37 @@
1
+ /** Minimal PostgreSQL startup protocol helpers for the loopback proxy. */
2
+ import type { Socket } from "node:net";
3
+ /** PostgreSQL SSLRequest protocol code. */
4
+ export declare const SSL_REQUEST = 80877103;
5
+ /** PostgreSQL CancelRequest protocol code. */
6
+ export declare const CANCEL_REQUEST = 80877102;
7
+ /** PostgreSQL protocol version 3 code. */
8
+ export declare const PROTOCOL_3 = 196608;
9
+ /** Parsed PostgreSQL startup packet. */
10
+ export interface StartupMessage {
11
+ kind: "startup";
12
+ protocol: number;
13
+ parameters: Record<string, string>;
14
+ }
15
+ /** Parsed PostgreSQL cancellation packet. */
16
+ export interface CancelMessage {
17
+ kind: "cancel";
18
+ processId: number;
19
+ secretKey: number;
20
+ }
21
+ /** First supported packet received from a PostgreSQL client. */
22
+ export type InitialMessage = StartupMessage | CancelMessage;
23
+ /** Error caused by an invalid or unsupported PostgreSQL startup packet. */
24
+ export declare class PostgresProtocolError extends Error {
25
+ }
26
+ /** Read and classify the first PostgreSQL frontend message from a socket. */
27
+ export declare function readInitialMessage(socket: Socket, timeoutMs: number): Promise<InitialMessage>;
28
+ /** Build a PostgreSQL SSL negotiation request packet. */
29
+ export declare function sslRequest(): Buffer;
30
+ /** Build a PostgreSQL cancellation request packet. */
31
+ export declare function cancelRequest(processId: number, secretKey: number): Buffer;
32
+ /** Build the backend messages that complete PostgreSQL startup. */
33
+ export declare function startupComplete(parameters: ReadonlyMap<string, string>, processId: number, secretKey: number, transactionStatus?: string): Buffer;
34
+ /** Replace client startup identity with the resolved upstream identity. */
35
+ export declare function upstreamStartupParameters(parameters: Record<string, string>, user: string, database: string): Record<string, string>;
36
+ /** Build a fatal PostgreSQL error response. */
37
+ export declare function fatalError(message: string, sqlstate?: string): Buffer;
@@ -0,0 +1,124 @@
1
+ /** Minimal PostgreSQL startup protocol helpers for the loopback proxy. */
2
+ /** PostgreSQL SSLRequest protocol code. */
3
+ export const SSL_REQUEST = 80_877_103;
4
+ /** PostgreSQL CancelRequest protocol code. */
5
+ export const CANCEL_REQUEST = 80_877_102;
6
+ /** PostgreSQL protocol version 3 code. */
7
+ export const PROTOCOL_3 = 196_608;
8
+ /** Error caused by an invalid or unsupported PostgreSQL startup packet. */
9
+ export class PostgresProtocolError extends Error {
10
+ }
11
+ /** Read and classify the first PostgreSQL frontend message from a socket. */
12
+ export async function readInitialMessage(socket, timeoutMs) {
13
+ const deadline = Date.now() + timeoutMs;
14
+ for (;;) {
15
+ const packet = await readPacket(socket, deadline);
16
+ const code = packet.readInt32BE(4);
17
+ if (code === SSL_REQUEST) {
18
+ socket.write("N");
19
+ continue;
20
+ }
21
+ if (code === CANCEL_REQUEST) {
22
+ if (packet.length !== 16)
23
+ throw new PostgresProtocolError("Invalid CancelRequest packet");
24
+ return {
25
+ kind: "cancel",
26
+ processId: packet.readInt32BE(8),
27
+ secretKey: packet.readInt32BE(12),
28
+ };
29
+ }
30
+ if (code !== PROTOCOL_3) {
31
+ throw new PostgresProtocolError(`Unsupported PostgreSQL protocol version ${code}`);
32
+ }
33
+ return { kind: "startup", protocol: code, parameters: parseParameters(packet.subarray(8)) };
34
+ }
35
+ }
36
+ /** Build a PostgreSQL SSL negotiation request packet. */
37
+ export function sslRequest() {
38
+ return requestPacket(SSL_REQUEST);
39
+ }
40
+ /** Build a PostgreSQL cancellation request packet. */
41
+ export function cancelRequest(processId, secretKey) {
42
+ return requestPacket(CANCEL_REQUEST, processId, secretKey);
43
+ }
44
+ /** Build the backend messages that complete PostgreSQL startup. */
45
+ export function startupComplete(parameters, processId, secretKey, transactionStatus = "I") {
46
+ return Buffer.concat([
47
+ backendMessage("R", int32(0)),
48
+ ...[...parameters].map(([name, value]) => backendMessage("S", Buffer.from(`${name}\0${value}\0`))),
49
+ backendMessage("K", Buffer.concat([int32(processId), int32(secretKey)])),
50
+ backendMessage("Z", Buffer.from(transactionStatus.slice(0, 1) || "I")),
51
+ ]);
52
+ }
53
+ /** Replace client startup identity with the resolved upstream identity. */
54
+ export function upstreamStartupParameters(parameters, user, database) {
55
+ return { ...parameters, user, database };
56
+ }
57
+ /** Build a fatal PostgreSQL error response. */
58
+ export function fatalError(message, sqlstate = "08001") {
59
+ return backendMessage("E", Buffer.concat([Buffer.from(`SFATAL\0C${sqlstate}\0M${message}\0`), Buffer.from([0])]));
60
+ }
61
+ function requestPacket(code, processId, secretKey) {
62
+ const values = [code];
63
+ if (processId !== undefined && secretKey !== undefined)
64
+ values.push(processId, secretKey);
65
+ return Buffer.concat([int32(4 + values.length * 4), ...values.map(int32)]);
66
+ }
67
+ function backendMessage(code, body) {
68
+ return Buffer.concat([Buffer.from(code), int32(body.length + 4), body]);
69
+ }
70
+ function int32(value) {
71
+ const buffer = Buffer.allocUnsafe(4);
72
+ buffer.writeInt32BE(value);
73
+ return buffer;
74
+ }
75
+ async function readPacket(socket, deadline) {
76
+ let buffer = Buffer.alloc(0);
77
+ while (buffer.length < 4)
78
+ buffer = Buffer.concat([buffer, await readChunk(socket, deadline)]);
79
+ const length = buffer.readInt32BE(0);
80
+ if (length < 8 || length > 1024 * 1024) {
81
+ throw new PostgresProtocolError("Invalid PostgreSQL startup packet");
82
+ }
83
+ while (buffer.length < length) {
84
+ buffer = Buffer.concat([buffer, await readChunk(socket, deadline)]);
85
+ }
86
+ const remainder = buffer.subarray(length);
87
+ if (remainder.length)
88
+ socket.unshift(remainder);
89
+ return buffer.subarray(0, length);
90
+ }
91
+ function readChunk(socket, deadline) {
92
+ const remaining = deadline - Date.now();
93
+ if (remaining <= 0) {
94
+ return Promise.reject(new PostgresProtocolError("PostgreSQL startup timed out"));
95
+ }
96
+ return new Promise((resolve, reject) => {
97
+ const timer = setTimeout(() => finish(new PostgresProtocolError("PostgreSQL startup timed out")), remaining);
98
+ const onData = (chunk) => finish(undefined, chunk);
99
+ const onError = (error) => finish(error);
100
+ const onEnd = () => finish(new PostgresProtocolError("PostgreSQL client closed during startup"));
101
+ const finish = (error, chunk) => {
102
+ clearTimeout(timer);
103
+ socket.off("data", onData);
104
+ socket.off("error", onError);
105
+ socket.off("end", onEnd);
106
+ if (error)
107
+ reject(error);
108
+ else
109
+ resolve(chunk);
110
+ };
111
+ socket.once("data", onData);
112
+ socket.once("error", onError);
113
+ socket.once("end", onEnd);
114
+ });
115
+ }
116
+ function parseParameters(body) {
117
+ const values = body.toString("utf8").split("\0");
118
+ const parameters = {};
119
+ for (let index = 0; index + 1 < values.length && values[index]; index += 2) {
120
+ parameters[values[index]] = values[index + 1] ?? "";
121
+ }
122
+ return parameters;
123
+ }
124
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGFrZWJhc2UtcHJveHkvcHJvdG9jb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsMEVBQTBFO0FBSTFFLDJDQUEyQztBQUMzQyxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDO0FBQ3RDLDhDQUE4QztBQUM5QyxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsVUFBVSxDQUFDO0FBQ3pDLDBDQUEwQztBQUMxQyxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDO0FBbUJsQywyRUFBMkU7QUFDM0UsTUFBTSxPQUFPLHFCQUFzQixTQUFRLEtBQUs7Q0FBRztBQUVuRCw2RUFBNkU7QUFDN0UsTUFBTSxDQUFDLEtBQUssVUFBVSxrQkFBa0IsQ0FDdEMsTUFBYyxFQUNkLFNBQWlCO0lBRWpCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUM7SUFDeEMsU0FBUyxDQUFDO1FBQ1IsTUFBTSxNQUFNLEdBQUcsTUFBTSxVQUFVLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkMsSUFBSSxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7WUFDekIsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNsQixTQUFTO1FBQ1gsQ0FBQztRQUNELElBQUksSUFBSSxLQUFLLGNBQWMsRUFBRSxDQUFDO1lBQzVCLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxFQUFFO2dCQUFFLE1BQU0sSUFBSSxxQkFBcUIsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1lBQzFGLE9BQU87Z0JBQ0wsSUFBSSxFQUFFLFFBQVE7Z0JBQ2QsU0FBUyxFQUFFLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFD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bHBlcnMgZm9yIHRoZSBsb29wYmFjayBwcm94eS4gKi9cblxuaW1wb3J0IHR5cGUgeyBTb2NrZXQgfSBmcm9tIFwibm9kZTpuZXRcIjtcblxuLyoqIFBvc3RncmVTUUwgU1NMUmVxdWVzdCBwcm90b2NvbCBjb2RlLiAqL1xuZXhwb3J0IGNvbnN0IFNTTF9SRVFVRVNUID0gODBfODc3XzEwMztcbi8qKiBQb3N0Z3JlU1FMIENhbmNlbFJlcXVlc3QgcHJvdG9jb2wgY29kZS4gKi9cbmV4cG9ydCBjb25zdCBDQU5DRUxfUkVRVUVTVCA9IDgwXzg3N18xMDI7XG4vKiogUG9zdGdyZVNRTCBwcm90b2NvbCB2ZXJzaW9uIDMgY29kZS4gKi9cbmV4cG9ydCBjb25zdCBQUk9UT0NPTF8zID0gMTk2XzYwODtcblxuLyoqIFBhcnNlZCBQb3N0Z3JlU1FMIHN0YXJ0dXAgcGFja2V0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGFydHVwTWVzc2FnZSB7XG4gIGtpbmQ6IFwic3RhcnR1cFwiO1xuICBwcm90b2NvbDogbnVtYmVyO1xuICBwYXJhbWV0ZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufVxuXG4vKiogUGFyc2VkIFBvc3RncmVTUUwgY2FuY2VsbGF0aW9uIHBhY2tldC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2FuY2VsTWVzc2FnZSB7XG4gIGtpbmQ6IFwiY2FuY2VsXCI7XG4gIHByb2Nlc3NJZDogbnVtYmVyO1xuICBzZWNyZXRLZXk6IG51bWJlcjtcbn1cblxuLyoqIEZpcnN0IHN1cHBvcnRlZCBwYWNrZXQgcmVjZWl2ZWQgZnJvbSBhIFBvc3RncmVTUUwgY2xpZW50LiAqL1xuZXhwb3J0IHR5cGUgSW5pdGlhbE1lc3NhZ2UgPSBTdGFydHVwTWVzc2FnZSB8IENhbmNlbE1lc3NhZ2U7XG5cbi8qKiBFcnJvciBjYXVzZWQgYnkgYW4gaW52YWxpZCBvciB1bnN1cHBvcnRlZCBQb3N0Z3JlU1FMIHN0YXJ0dXAgcGFja2V0LiAqL1xuZXhwb3J0IGNsYXNzIFBvc3RncmVzUHJvdG9jb2xFcnJvciBleHRlbmRzIEVycm9yIHt9XG5cbi8qKiBSZWFkIGFuZCBjbGFzc2lmeSB0aGUgZmlyc3QgUG9zdGdyZVNRTCBmcm9udGVuZCBtZXNzYWdlIGZyb20gYSBzb2NrZXQuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEluaXRpYWxNZXNzYWdlKFxuICBzb2NrZXQ6IFNvY2tldCxcbiAgdGltZW91dE1zOiBudW1iZXIsXG4pOiBQcm9taXNlPEluaXRpYWxNZXNzYWdlPiB7XG4gIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIHRpbWVvdXRNcztcbiAgZm9yICg7Oykge1xuICAgIGNvbnN0IHBhY2tldCA9IGF3YWl0IHJlYWRQYWNrZXQoc29ja2V0LCBkZWFkbGluZSk7XG4gICAgY29uc3QgY29kZSA9IHBhY2tldC5yZWFkSW50MzJCRSg0KTtcbiAgICBpZiAoY29kZSA9PT0gU1NMX1JFUVVFU1QpIHtcbiAgICAgIHNvY2tldC53cml0ZShcIk5cIik7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKGNvZGUgPT09IENBTkNFTF9SRVFVRVNUKSB7XG4gICAgICBpZiAocGFja2V0Lmxlbmd0aCAhPT0gMTYpIHRocm93IG5ldyBQb3N0Z3Jlc1Byb3RvY29sRXJyb3IoXCJJbnZhbGlkIENhbmNlbFJlcXVlc3QgcGFja2V0XCIpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAga2luZDogXCJjYW5jZWxcIixcbiAgICAgICAgcHJvY2Vzc0lkOiBwYWNrZXQucmVhZEludDMyQkUoOCksXG4gICAgICAgIHNlY3JldEtleTogcGFja2V0LnJlYWRJbnQzMkJFKDEyKSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChjb2RlICE9PSBQUk9UT0NPTF8zKSB7XG4gICAgICB0aHJvdyBuZXcgUG9zdGdyZXNQcm90b2NvbEVycm9yKGBVbnN1cHBvcnRlZCBQb3N0Z3JlU1FMIHByb3RvY29sIHZlcnNpb24gJHtjb2RlfWApO1xuICAgIH1cbiAgICByZXR1cm4geyBraW5kOiBcInN0YXJ0dXBcIiwgcHJvdG9jb2w6IGNvZGUsIHBhcmFtZXRlcnM6IHBhcnNlUGFyYW1ldGVycyhwYWNrZXQuc3ViYXJyYXkoOCkpIH07XG4gIH1cbn1cblxuLyoqIEJ1aWxkIGEgUG9zdGdyZVNRTCBTU0wgbmVnb3RpYXRpb24gcmVxdWVzdCBwYWNrZXQuICovXG5leHBvcnQgZnVuY3Rpb24gc3NsUmVxdWVzdCgpOiBCdWZmZXIge1xuICByZXR1cm4gcmVxdWVzdFBhY2tldChTU0xfUkVRVUVTVCk7XG59XG5cbi8qKiBCdWlsZCBhIFBvc3RncmVTUUwgY2FuY2VsbGF0aW9uIHJlcXVlc3QgcGFja2V0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbmNlbFJlcXVlc3QocHJvY2Vzc0lkOiBudW1iZXIsIHNlY3JldEtleTogbnVtYmVyKTogQnVmZmVyIHtcbiAgcmV0dXJuIHJlcXVlc3RQYWNrZXQoQ0FOQ0VMX1JFUVVFU1QsIHByb2Nlc3NJZCwgc2VjcmV0S2V5KTtcbn1cblxuLyoqIEJ1aWxkIHRoZSBiYWNrZW5kIG1lc3NhZ2VzIHRoYXQgY29tcGxldGUgUG9zdGdyZVNRTCBzdGFydHVwLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0dXBDb21wbGV0ZShcbiAgcGFyYW1ldGVyczogUmVhZG9ubHlNYXA8c3RyaW5nLCBzdHJpbmc+LFxuICBwcm9jZXNzSWQ6IG51bWJlcixcbiAgc2VjcmV0S2V5OiBudW1iZXIsXG4gIHRyYW5zYWN0aW9uU3RhdHVzID0gXCJJXCIsXG4pOiBCdWZmZXIge1xuICByZXR1cm4gQnVmZmVyLmNvbmNhdChbXG4gICAgYmFja2VuZE1lc3NhZ2UoXCJSXCIsIGludDMyKDApKSxcbiAgICAuLi5bLi4ucGFyYW1ldGVyc10ubWFwKChbbmFtZSwgdmFsdWVdKSA9PlxuICAgICAgYmFja2VuZE1lc3NhZ2UoXCJTXCIsIEJ1ZmZlci5mcm9tKGAke25hbWV9XFwwJHt2YWx1ZX1cXDBgKSksXG4gICAgKSxcbiAgICBiYWNrZW5kTWVzc2FnZShcIktcIiwgQnVmZmVyLmNvbmNhdChbaW50MzIocHJvY2Vzc0lkKSwgaW50MzIoc2VjcmV0S2V5KV0pKSxcbiAgICBiYWNrZW5kTWVzc2FnZShcIlpcIiwgQnVmZmVyLmZyb20odHJhbnNhY3Rpb25TdGF0dXMuc2xpY2UoMCwgMSkgfHwgXCJJXCIpKSxcbiAgXSk7XG59XG5cbi8qKiBSZXBsYWNlIGNsaWVudCBzdGFydHVwIGlkZW50aXR5IHdpdGggdGhlIHJlc29sdmVkIHVwc3RyZWFtIGlkZW50aXR5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwc3RyZWFtU3RhcnR1cFBhcmFtZXRlcnMoXG4gIHBhcmFtZXRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gIHVzZXI6IHN0cmluZyxcbiAgZGF0YWJhc2U6IHN0cmluZyxcbik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICByZXR1cm4geyAuLi5wYXJhbWV0ZXJzLCB1c2VyLCBkYXRhYmFzZSB9O1xufVxuXG4vKiogQnVpbGQgYSBmYXRhbCBQb3N0Z3JlU1FMIGVycm9yIHJlc3BvbnNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZhdGFsRXJyb3IobWVzc2FnZTogc3RyaW5nLCBzcWxzdGF0ZSA9IFwiMDgwMDFcIik6IEJ1ZmZlciB7XG4gIHJldHVybiBiYWNrZW5kTWVzc2FnZShcbiAgICBcIkVcIixcbiAgICBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShgU0ZBVEFMXFwwQyR7c3Fsc3RhdGV9XFwwTSR7bWVzc2FnZX1cXDBgKSwgQnVmZmVyLmZyb20oWzBdKV0pLFxuICApO1xufVxuXG5mdW5jdGlvbiByZXF1ZXN0UGFja2V0KGNvZGU6IG51bWJlciwgcHJvY2Vzc0lkPzogbnVtYmVyLCBzZWNyZXRLZXk/OiBudW1iZXIpOiBCdWZmZXIge1xuICBjb25zdCB2YWx1ZXMgPSBbY29kZV07XG4gIGlmIChwcm9jZXNzSWQgIT09IHVuZGVmaW5lZCAmJiBzZWNyZXRLZXkgIT09IHVuZGVmaW5lZCkgdmFsdWVzLnB1c2gocHJvY2Vzc0lkLCBzZWNyZXRLZXkpO1xuICByZXR1cm4gQnVmZmVyLmNvbmNhdChbaW50MzIoNCArIHZhbHVlcy5sZW5ndGggKiA0KSwgLi4udmFsdWVzLm1hcChpbnQzMildKTtcbn1cblxuZnVuY3Rpb24gYmFja2VuZE1lc3NhZ2UoY29kZTogc3RyaW5nLCBib2R5OiBCdWZmZXIpOiBCdWZmZXIge1xuICByZXR1cm4gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oY29kZSksIGludDMyKGJvZHkubGVuZ3RoICsgNCksIGJvZHldKTtcbn1cblxuZnVuY3Rpb24gaW50MzIodmFsdWU6IG51bWJlcik6IEJ1ZmZlciB7XG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZSg0KTtcbiAgYnVmZmVyLndyaXRlSW50MzJCRSh2YWx1ZSk7XG4gIHJldHVybiBidWZmZXI7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRQYWNrZXQoc29ja2V0OiBTb2NrZXQsIGRlYWRsaW5lOiBudW1iZXIpOiBQcm9taXNlPEJ1ZmZlcj4ge1xuICBsZXQgYnVmZmVyID0gQnVmZmVyLmFsbG9jKDApO1xuICB3aGlsZSAoYnVmZmVyLmxlbmd0aCA8IDQpIGJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW2J1ZmZlciwgYXdhaXQgcmVhZENodW5rKHNvY2tldCwgZGVhZGxpbmUpXSk7XG4gIGNvbnN0IGxlbmd0aCA9IGJ1ZmZlci5yZWFkSW50MzJCRSgwKTtcbiAgaWYgKGxlbmd0aCA8IDggfHwgbGVuZ3RoID4gMTAyNCAqIDEwMjQpIHtcbiAgICB0aHJvdyBuZXcgUG9zdGdyZXNQcm90b2NvbEVycm9yKFwiSW52YWxpZCBQb3N0Z3JlU1FMIHN0YXJ0dXAgcGFja2V0XCIpO1xuICB9XG4gIHdoaWxlIChidWZmZXIubGVuZ3RoIDwgbGVuZ3RoKSB7XG4gICAgYnVmZmVyID0gQnVmZmVyLmNvbmNhdChbYnVmZmVyLCBhd2FpdCByZWFkQ2h1bmsoc29ja2V0LCBkZWFkbGluZSldKTtcbiAgfVxuICBjb25zdCByZW1haW5kZXIgPSBidWZmZXIuc3ViYXJyYXkobGVuZ3RoKTtcbiAgaWYgKHJlbWFpbmRlci5sZW5ndGgpIHNvY2tldC51bnNoaWZ0KHJlbWFpbmRlcik7XG4gIHJldHVybiBidWZmZXIuc3ViYXJyYXkoMCwgbGVuZ3RoKTtcbn1cblxuZnVuY3Rpb24gcmVhZENodW5rKHNvY2tldDogU29ja2V0LCBkZWFkbGluZTogbnVtYmVyKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgY29uc3QgcmVtYWluaW5nID0gZGVhZGxpbmUgLSBEYXRlLm5vdygpO1xuICBpZiAocmVtYWluaW5nIDw9IDApIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFBvc3RncmVzUHJvdG9jb2xFcnJvcihcIlBvc3RncmVTUUwgc3RhcnR1cCB0aW1lZCBvdXRcIikpO1xuICB9XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KFxuICAgICAgKCkgPT4gZmluaXNoKG5ldyBQb3N0Z3Jlc1Byb3RvY29sRXJyb3IoXCJQb3N0Z3JlU1FMIHN0YXJ0dXAgdGltZWQgb3V0XCIpKSxcbiAgICAgIHJlbWFpbmluZyxcbiAgICApO1xuICAgIGNvbnN0IG9uRGF0YSA9IChjaHVuazogQnVmZmVyKSA9PiBmaW5pc2godW5kZWZpbmVkLCBjaHVuayk7XG4gICAgY29uc3Qgb25FcnJvciA9IChlcnJvcjogRXJyb3IpID0+IGZpbmlzaChlcnJvcik7XG4gICAgY29uc3Qgb25FbmQgPSAoKSA9PlxuICAgICAgZmluaXNoKG5ldyBQb3N0Z3Jlc1Byb3RvY29sRXJyb3IoXCJQb3N0Z3JlU1FMIGNsaWVudCBjbG9zZWQgZHVyaW5nIHN0YXJ0dXBcIikpO1xuICAgIGNvbnN0IGZpbmlzaCA9IChlcnJvcj86IEVycm9yLCBjaHVuaz86IEJ1ZmZlcikgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHNvY2tldC5vZmYoXCJkYXRhXCIsIG9uRGF0YSk7XG4gICAgICBzb2NrZXQub2ZmKFwiZXJyb3JcIiwgb25FcnJvcik7XG4gICAgICBzb2NrZXQub2ZmKFwiZW5kXCIsIG9uRW5kKTtcbiAgICAgIGlmIChlcnJvcikgcmVqZWN0KGVycm9yKTtcbiAgICAgIGVsc2UgcmVzb2x2ZShjaHVuayEpO1xuICAgIH07XG4gICAgc29ja2V0Lm9uY2UoXCJkYXRhXCIsIG9uRGF0YSk7XG4gICAgc29ja2V0Lm9uY2UoXCJlcnJvclwiLCBvbkVycm9yKTtcbiAgICBzb2NrZXQub25jZShcImVuZFwiLCBvbkVuZCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwYXJzZVBhcmFtZXRlcnMoYm9keTogQnVmZmVyKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHZhbHVlcyA9IGJvZHkudG9TdHJpbmcoXCJ1dGY4XCIpLnNwbGl0KFwiXFwwXCIpO1xuICBjb25zdCBwYXJhbWV0ZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggKyAxIDwgdmFsdWVzLmxlbmd0aCAmJiB2YWx1ZXNbaW5kZXhdOyBpbmRleCArPSAyKSB7XG4gICAgcGFyYW1ldGVyc1t2YWx1ZXNbaW5kZXhdIV0gPSB2YWx1ZXNbaW5kZXggKyAxXSA/PyBcIlwiO1xuICB9XG4gIHJldHVybiBwYXJhbWV0ZXJzO1xufVxuIl19
@@ -0,0 +1,22 @@
1
+ /** Pure Node PostgreSQL wire proxy for Databricks Lakebase. */
2
+ import { type LakebaseProxyOptions } from "./options.ts";
3
+ /** Loopback PostgreSQL wire proxy backed by Databricks Lakebase credentials. */
4
+ export declare class LakebaseProxy {
5
+ private readonly client;
6
+ private readonly options;
7
+ private readonly cancellations;
8
+ private server?;
9
+ private statsTimer?;
10
+ private opened;
11
+ private closed;
12
+ private failed;
13
+ private active;
14
+ constructor(options?: LakebaseProxyOptions);
15
+ listen(): Promise<{
16
+ host: string;
17
+ port: number;
18
+ }>;
19
+ close(): Promise<void>;
20
+ private handle;
21
+ private reportStats;
22
+ }
@@ -0,0 +1,200 @@
1
+ /** Pure Node PostgreSQL wire proxy for Databricks Lakebase. */
2
+ import { createServer } from "node:net";
3
+ import { LakebaseClient, requireAddress } from "@dbx-tools/lakebase";
4
+ import { postgresConnectionOptions } from "@dbx-tools/postgres";
5
+ import { log, stringUtils } from "@dbx-tools/shared-core";
6
+ import { Client } from "pg";
7
+ import { CancellationRegistry } from "./cancellation.js";
8
+ import { resolveLakebaseProxyOptions, } from "./options.js";
9
+ import { fatalError, PostgresProtocolError, readInitialMessage, startupComplete, upstreamStartupParameters, } from "./protocol.js";
10
+ const logger = log.logger("lakebase-proxy");
11
+ /** Loopback PostgreSQL wire proxy backed by Databricks Lakebase credentials. */
12
+ export class LakebaseProxy {
13
+ client;
14
+ options;
15
+ cancellations = new CancellationRegistry();
16
+ server;
17
+ statsTimer;
18
+ opened = 0;
19
+ closed = 0;
20
+ failed = 0;
21
+ active = 0;
22
+ constructor(options = {}) {
23
+ this.options = resolveLakebaseProxyOptions(options);
24
+ this.client = new LakebaseClient({ profile: this.options.profile });
25
+ }
26
+ async listen() {
27
+ if (this.server)
28
+ throw new Error("Lakebase proxy is already listening");
29
+ const host = this.options.listen.host;
30
+ const server = createServer((socket) => void this.handle(socket));
31
+ this.server = server;
32
+ this.statsTimer = setInterval(() => this.reportStats(), 60_000);
33
+ this.statsTimer.unref();
34
+ await new Promise((resolve, reject) => {
35
+ server.once("error", reject);
36
+ server.listen(this.options.listen.port, host, () => {
37
+ server.off("error", reject);
38
+ resolve();
39
+ });
40
+ });
41
+ const address = server.address();
42
+ if (!address || typeof address === "string") {
43
+ throw new Error("Lakebase listener has no address");
44
+ }
45
+ logger.info("Lakebase proxy listening", { host: address.address, port: address.port });
46
+ return { host: address.address, port: address.port };
47
+ }
48
+ async close() {
49
+ const server = this.server;
50
+ this.server = undefined;
51
+ if (this.statsTimer)
52
+ clearInterval(this.statsTimer);
53
+ this.statsTimer = undefined;
54
+ if (!server)
55
+ return;
56
+ await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
57
+ }
58
+ async handle(local) {
59
+ const started = Date.now();
60
+ let upstream;
61
+ let cancellation;
62
+ this.opened += 1;
63
+ this.active += 1;
64
+ try {
65
+ local.setNoDelay(true);
66
+ const initial = await readInitialMessage(local, this.options.startupTimeoutSeconds * 1000);
67
+ if (initial.kind === "cancel") {
68
+ await this.cancellations.forward(initial);
69
+ local.end();
70
+ return;
71
+ }
72
+ const startup = initial;
73
+ const targetText = startup.parameters.database;
74
+ if (!targetText)
75
+ throw new ProxyFailure("startup database is required", "3D000");
76
+ let target;
77
+ try {
78
+ target = requireAddress(targetText);
79
+ }
80
+ catch (error) {
81
+ throw new ProxyFailure(message(error), "3D000");
82
+ }
83
+ const startupUser = stringUtils.trimToUndefined(startup.parameters.user);
84
+ let resolved;
85
+ try {
86
+ resolved = await this.client.resolve(target, startupUser);
87
+ }
88
+ catch (error) {
89
+ throw new ProxyFailure(message(error), "3D000");
90
+ }
91
+ let password;
92
+ try {
93
+ password = await this.client.generateDatabaseCredential(resolved.endpoint, startupUser);
94
+ }
95
+ catch (error) {
96
+ throw new ProxyFailure(message(error), "28000");
97
+ }
98
+ let connected;
99
+ try {
100
+ connected = await connectUpstream(resolved, password, postgresConnectionOptions(startup.parameters, this.options.postgresRole));
101
+ }
102
+ catch (error) {
103
+ throw new ProxyFailure(message(error), "08001");
104
+ }
105
+ upstream = connected.socket;
106
+ cancellation = this.cancellations.register({
107
+ host: resolved.host,
108
+ port: resolved.port,
109
+ processId: connected.processId,
110
+ secretKey: connected.secretKey,
111
+ });
112
+ local.write(startupComplete(connected.parameters, cancellation.processId, cancellation.secretKey, connected.transactionStatus));
113
+ local.pipe(upstream).pipe(local);
114
+ await Promise.race([closed(local), closed(upstream)]);
115
+ logger.debug("Lakebase connection closed", {
116
+ durationMs: Date.now() - started,
117
+ project: resolved.project,
118
+ branch: resolved.branch,
119
+ endpoint: resolved.endpoint,
120
+ });
121
+ }
122
+ catch (error) {
123
+ this.failed += 1;
124
+ const failure = error instanceof ProxyFailure
125
+ ? error
126
+ : error instanceof PostgresProtocolError
127
+ ? new ProxyFailure(error.message, "08P01")
128
+ : new ProxyFailure(message(error));
129
+ logger.warn("Lakebase connection failed", {
130
+ durationMs: Date.now() - started,
131
+ error: failure.message,
132
+ });
133
+ if (!local.destroyed)
134
+ local.end(fatalError(failure.message, failure.sqlstate));
135
+ }
136
+ finally {
137
+ if (cancellation)
138
+ this.cancellations.remove(cancellation);
139
+ upstream?.destroy();
140
+ local.destroy();
141
+ this.closed += 1;
142
+ this.active -= 1;
143
+ }
144
+ }
145
+ reportStats() {
146
+ logger.info("Lakebase proxy connections", {
147
+ opened: this.opened,
148
+ closed: this.closed,
149
+ failed: this.failed,
150
+ active: this.active,
151
+ });
152
+ }
153
+ }
154
+ async function connectUpstream(resolved, password, startup) {
155
+ const client = new Client({
156
+ host: resolved.host,
157
+ port: resolved.port,
158
+ database: resolved.database,
159
+ user: resolved.user,
160
+ password,
161
+ ssl: { rejectUnauthorized: true, servername: resolved.host },
162
+ application_name: startup.application_name,
163
+ connectionTimeoutMillis: 30_000,
164
+ });
165
+ const parameters = new Map();
166
+ client.getStartupConf = () => upstreamStartupParameters(startup, resolved.user, resolved.database);
167
+ client.on("error", (error) => {
168
+ logger.debug("Lakebase upstream client closed", { error: error.message });
169
+ });
170
+ client.connection.on("parameterStatus", (message) => {
171
+ parameters.set(message.parameterName, message.parameterValue);
172
+ });
173
+ await client.connect();
174
+ const socket = client.connection.stream;
175
+ socket.removeAllListeners("data");
176
+ return {
177
+ socket,
178
+ parameters,
179
+ processId: client.processID,
180
+ secretKey: client.secretKey,
181
+ transactionStatus: client._txStatus ?? "I",
182
+ };
183
+ }
184
+ function closed(socket) {
185
+ return new Promise((resolve, reject) => {
186
+ socket.once("close", () => resolve());
187
+ socket.once("error", reject);
188
+ });
189
+ }
190
+ function message(error) {
191
+ return error instanceof Error ? error.message : String(error);
192
+ }
193
+ class ProxyFailure extends Error {
194
+ sqlstate;
195
+ constructor(message, sqlstate = "08001") {
196
+ super(message);
197
+ this.sqlstate = sqlstate;
198
+ }
199
+ }
200
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGFrZWJhc2UtcHJveHkvcHJveHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0RBQStEO0FBRS9ELE9BQU8sRUFBRSxZQUFZLEVBQTRCLE1BQU0sVUFBVSxDQUFDO0FBRWxFLE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDckUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDaEUsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBRTVCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3pELE9BQU8sRUFDTCwyQkFBMkIsR0FHNUIsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUNMLFVBQVUsRUFDVixxQkFBcUIsRUFDckIsa0JBQWtCLEVBQ2xCLGVBQWUsRUFDZix5QkFBeUIsR0FFMUIsTUFBTSxlQUFlLENBQUM7QUFFdkIsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBb0I1QyxnRkFBZ0Y7QUFDaEYsTUFBTSxPQUFPLGFBQWE7SUFDUCxNQUFNLENBQWlCO0lBQ3ZCLE9BQU8sQ0FBK0I7SUFDdEMsYUFBYSxHQUFHLElBQUksb0JBQW9CLEVBQUUsQ0FBQztJQUNwRCxNQUFNLENBQVU7SUFDaEIsVUFBVSxDQUFrQztJQUM1QyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ1gsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNYLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDWCxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBRW5CLFlBQVksVUFBZ0MsRUFBRTtRQUM1QyxJQUFJLENBQUMsT0FBTyxHQUFHLDJCQUEyQixD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QUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDL0IsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsS0FBYztJQUM3QixPQUFPLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRSxDQUFDO0FBRUQsTUFBTSxZQUFhLFNBQVEsS0FBSztJQUduQjtJQUZYLFlBQ0UsT0FBZSxFQUNOLFdBQVcsT0FBTztRQUUzQixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFGTixhQUFRLEdBQVIsUUFBUSxDQUFVO0lBRzdCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBQdXJlIE5vZGUgUG9zdGdyZVNRTCB3aXJlIHByb3h5IGZvciBEYXRhYnJpY2tzIExha2ViYXNlLiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIsIHR5cGUgU2VydmVyLCB0eXBlIFNvY2tldCB9IGZyb20gXCJub2RlOm5ldFwiO1xuaW1wb3J0IHR5cGUgeyBEdXBsZXggfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcbmltcG9ydCB7IExha2ViYXNlQ2xpZW50LCByZXF1aXJlQWRkcmVzcyB9IGZyb20gXCJAZGJ4LXRvb2xzL2xha2ViYXNlXCI7XG5pbXBvcnQgeyBwb3N0Z3Jlc0Nvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSBcIkBkYngtdG9vbHMvcG9zdGdyZXNcIjtcbmltcG9ydCB7IGxvZywgc3RyaW5nVXRpbHMgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgQ2xpZW50IH0gZnJvbSBcInBnXCI7XG5cbmltcG9ydCB7IENhbmNlbGxhdGlvblJlZ2lzdHJ5IH0gZnJvbSBcIi4vY2FuY2VsbGF0aW9uLnRzXCI7XG5pbXBvcnQge1xuICByZXNvbHZlTGFrZWJhc2VQcm94eU9wdGlvbnMsXG4gIHR5cGUgTGFrZWJhc2VQcm94eU9wdGlvbnMsXG4gIHR5cGUgUmVzb2x2ZWRMYWtlYmFzZVByb3h5T3B0aW9ucyxcbn0gZnJvbSBcIi4vb3B0aW9ucy50c1wiO1xuaW1wb3J0IHtcbiAgZmF0YWxFcnJvcixcbiAgUG9zdGdyZXNQcm90b2NvbEVycm9yLFxuICByZWFkSW5pdGlhbE1lc3NhZ2UsXG4gIHN0YXJ0dXBDb21wbGV0ZSxcbiAgdXBzdHJlYW1TdGFydHVwUGFyYW1ldGVycyxcbiAgdHlwZSBDYW5jZWxNZXNzYWdlLFxufSBmcm9tIFwiLi9wcm90b2NvbC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwibGFrZWJhc2UtcHJveHlcIik7XG5cbmludGVyZmFjZSBQZ0Nvbm5lY3Rpb25JbnRlcm5hbHMge1xuICBzdHJlYW06IER1cGxleDtcbiAgb24oZXZlbnQ6IFwicGFyYW1ldGVyU3RhdHVzXCIsIGxpc3RlbmVyOiAobWVzc2FnZTogUGFyYW1ldGVyU3RhdHVzKSA9PiB2b2lkKTogdm9pZDtcbn1cblxudHlwZSBQZ0NsaWVudEludGVybmFscyA9IENsaWVudCAmIHtcbiAgY29ubmVjdGlvbjogQ2xpZW50W1wiY29ubmVjdGlvblwiXSAmIFBnQ29ubmVjdGlvbkludGVybmFscztcbiAgcHJvY2Vzc0lEOiBudW1iZXI7XG4gIHNlY3JldEtleTogbnVtYmVyO1xuICBfdHhTdGF0dXM/OiBzdHJpbmc7XG4gIGdldFN0YXJ0dXBDb25mKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59O1xuXG5pbnRlcmZhY2UgUGFyYW1ldGVyU3RhdHVzIHtcbiAgcGFyYW1ldGVyTmFtZTogc3RyaW5nO1xuICBwYXJhbWV0ZXJWYWx1ZTogc3RyaW5nO1xufVxuXG4vKiogTG9vcGJhY2sgUG9zdGdyZVNRTCB3aXJlIHByb3h5IGJhY2tlZCBieSBEYXRhYnJpY2tzIExha2ViYXNlIGNyZWRlbnRpYWxzLiAqL1xuZXhwb3J0IGNsYXNzIExha2ViYXNlUHJveHkge1xuICBwcml2YXRlIHJlYWRvbmx5IGNsaWVudDogTGFrZWJhc2VDbGllbnQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogUmVzb2x2ZWRMYWtlYmFzZVByb3h5T3B0aW9ucztcbiAgcHJpdmF0ZSByZWFkb25seSBjYW5jZWxsYXRpb25zID0gbmV3IENhbmNlbGxhdGlvblJlZ2lzdHJ5KCk7XG4gIHByaXZhdGUgc2VydmVyPzogU2VydmVyO1xuICBwcml2YXRlIHN0YXRzVGltZXI/OiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRJbnRlcnZhbD47XG4gIHByaXZhdGUgb3BlbmVkID0gMDtcbiAgcHJpdmF0ZSBjbG9zZWQgPSAwO1xuICBwcml2YXRlIGZhaWxlZCA9IDA7XG4gIHByaXZhdGUgYWN0aXZlID0gMDtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBMYWtlYmFzZVByb3h5T3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5vcHRpb25zID0gcmVzb2x2ZUxha2ViYXNlUHJveHlPcHRpb25zKG9wdGlvbnMpO1xuICAgIHRoaXMuY2xpZW50ID0gbmV3IExha2ViYXNlQ2xpZW50KHsgcHJvZmlsZTogdGhpcy5vcHRpb25zLnByb2ZpbGUgfSk7XG4gIH1cblxuICBhc3luYyBsaXN0ZW4oKTogUHJvbWlzZTx7IGhvc3Q6IHN0cmluZzsgcG9ydDogbnVtYmVyIH0+IHtcbiAgICBpZiAodGhpcy5zZXJ2ZXIpIHRocm93IG5ldyBFcnJvcihcIkxha2ViYXNlIHByb3h5IGlzIGFscmVhZHkgbGlzdGVuaW5nXCIpO1xuICAgIGNvbnN0IGhvc3QgPSB0aGlzLm9wdGlvbnMubGlzdGVuLmhvc3Q7XG4gICAgY29uc3Qgc2VydmVyID0gY3JlYXRlU2VydmVyKChzb2NrZXQpID0+IHZvaWQgdGhpcy5oYW5kbGUoc29ja2V0KSk7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgdGhpcy5zdGF0c1RpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4gdGhpcy5yZXBvcnRTdGF0cygpLCA2MF8wMDApO1xuICAgIHRoaXMuc3RhdHNUaW1lci51bnJlZigpO1xuICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHNlcnZlci5vbmNlKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICAgIHNlcnZlci5saXN0ZW4odGhpcy5vcHRpb25zLmxpc3Rlbi5wb3J0LCBob3N0LCAoKSA9PiB7XG4gICAgICAgIHNlcnZlci5vZmYoXCJlcnJvclwiLCByZWplY3QpO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBjb25zdCBhZGRyZXNzID0gc2VydmVyLmFkZHJlc3MoKTtcbiAgICBpZiAoIWFkZHJlc3MgfHwgdHlwZW9mIGFkZHJlc3MgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkxha2ViYXNlIGxpc3RlbmVyIGhhcyBubyBhZGRyZXNzXCIpO1xuICAgIH1cbiAgICBsb2dnZXIuaW5mbyhcIkxha2ViYXNlIHByb3h5IGxpc3RlbmluZ1wiLCB7IGhvc3Q6IGFkZHJlc3MuYWRkcmVzcywgcG9ydDogYWRkcmVzcy5wb3J0IH0pO1xuICAgIHJldHVybiB7IGhvc3Q6IGFkZHJlc3MuYWRkcmVzcywgcG9ydDogYWRkcmVzcy5wb3J0IH07XG4gIH1cblxuICBhc3luYyBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcjtcbiAgICB0aGlzLnNlcnZlciA9IHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5zdGF0c1RpbWVyKSBjbGVhckludGVydmFsKHRoaXMuc3RhdHNUaW1lcik7XG4gICAgdGhpcy5zdGF0c1RpbWVyID0gdW5kZWZpbmVkO1xuICAgIGlmICghc2VydmVyKSByZXR1cm47XG4gICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT5cbiAgICAgIHNlcnZlci5jbG9zZSgoZXJyb3IpID0+IChlcnJvciA/IHJlamVjdChlcnJvcikgOiByZXNvbHZlKCkpKSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGUobG9jYWw6IFNvY2tldCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHN0YXJ0ZWQgPSBEYXRlLm5vdygpO1xuICAgIGxldCB1cHN0cmVhbTogRHVwbGV4IHwgdW5kZWZpbmVkO1xuICAgIGxldCBjYW5jZWxsYXRpb246IENhbmNlbE1lc3NhZ2UgfCB1bmRlZmluZWQ7XG4gICAgdGhpcy5vcGVuZWQgKz0gMTtcbiAgICB0aGlzLmFjdGl2ZSArPSAxO1xuICAgIHRyeSB7XG4gICAgICBsb2NhbC5zZXROb0RlbGF5KHRydWUpO1xuICAgICAgY29uc3QgaW5pdGlhbCA9IGF3YWl0IHJlYWRJbml0aWFsTWVzc2FnZShsb2NhbCwgdGhpcy5vcHRpb25zLnN0YXJ0dXBUaW1lb3V0U2Vjb25kcyAqIDEwMDApO1xuICAgICAgaWYgKGluaXRpYWwua2luZCA9PT0gXCJjYW5jZWxcIikge1xuICAgICAgICBhd2FpdCB0aGlzLmNhbmNlbGxhdGlvbnMuZm9yd2FyZChpbml0aWFsKTtcbiAgICAgICAgbG9jYWwuZW5kKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHN0YXJ0dXAgPSBpbml0aWFsO1xuICAgICAgY29uc3QgdGFyZ2V0VGV4dCA9IHN0YXJ0dXAucGFyYW1ldGVycy5kYXRhYmFzZTtcbiAgICAgIGlmICghdGFyZ2V0VGV4dCkgdGhyb3cgbmV3IFByb3h5RmFpbHVyZShcInN0YXJ0dXAgZGF0YWJhc2UgaXMgcmVxdWlyZWRcIiwgXCIzRDAwMFwiKTtcbiAgICAgIGxldCB0YXJnZXQ7XG4gICAgICB0cnkge1xuICAgICAgICB0YXJnZXQgPSByZXF1aXJlQWRkcmVzcyh0YXJnZXRUZXh0KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBQcm94eUZhaWx1cmUobWVzc2FnZShlcnJvciksIFwiM0QwMDBcIik7XG4gICAgICB9XG4gICAgICBjb25zdCBzdGFydHVwVXNlciA9IHN0cmluZ1V0aWxzLnRyaW1Ub1VuZGVmaW5lZChzdGFydHVwLnBhcmFtZXRlcnMudXNlcik7XG4gICAgICBsZXQgcmVzb2x2ZWQ7XG4gICAgICB0cnkge1xuICAgICAgICByZXNvbHZlZCA9IGF3YWl0IHRoaXMuY2xpZW50LnJlc29sdmUodGFyZ2V0LCBzdGFydHVwVXNlcik7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgUHJveHlGYWlsdXJlKG1lc3NhZ2UoZXJyb3IpLCBcIjNEMDAwXCIpO1xuICAgICAgfVxuICAgICAgbGV0IHBhc3N3b3JkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcGFzc3dvcmQgPSBhd2FpdCB0aGlzLmNsaWVudC5nZW5lcmF0ZURhdGFiYXNlQ3JlZGVudGlhbChyZXNvbHZlZC5lbmRwb2ludCwgc3RhcnR1cFVzZXIpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IFByb3h5RmFpbHVyZShtZXNzYWdlKGVycm9yKSwgXCIyODAwMFwiKTtcbiAgICAgIH1cbiAgICAgIGxldCBjb25uZWN0ZWQ7XG4gICAgICB0cnkge1xuICAgICAgICBjb25uZWN0ZWQgPSBhd2FpdCBjb25uZWN0VXBzdHJlYW0oXG4gICAgICAgICAgcmVzb2x2ZWQsXG4gICAgICAgICAgcGFzc3dvcmQsXG4gICAgICAgICAgcG9zdGdyZXNDb25uZWN0aW9uT3B0aW9ucyhzdGFydHVwLnBhcmFtZXRlcnMsIHRoaXMub3B0aW9ucy5wb3N0Z3Jlc1JvbGUpLFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IFByb3h5RmFpbHVyZShtZXNzYWdlKGVycm9yKSwgXCIwODAwMVwiKTtcbiAgICAgIH1cbiAgICAgIHVwc3RyZWFtID0gY29ubmVjdGVkLnNvY2tldDtcbiAgICAgIGNhbmNlbGxhdGlvbiA9IHRoaXMuY2FuY2VsbGF0aW9ucy5yZWdpc3Rlcih7XG4gICAgICAgIGhvc3Q6IHJlc29sdmVkLmhvc3QsXG4gICAgICAgIHBvcnQ6IHJlc29sdmVkLnBvcnQsXG4gICAgICAgIHByb2Nlc3NJZDogY29ubmVjdGVkLnByb2Nlc3NJZCxcbiAgICAgICAgc2VjcmV0S2V5OiBjb25uZWN0ZWQuc2VjcmV0S2V5LFxuICAgICAgfSk7XG4gICAgICBsb2NhbC53cml0ZShcbiAgICAgICAgc3RhcnR1cENvbXBsZXRlKFxuICAgICAgICAgIGNvbm5lY3RlZC5wYXJhbWV0ZXJzLFxuICAgICAgICAgIGNhbmNlbGxhdGlvbi5wcm9jZXNzSWQsXG4gICAgICAgICAgY2FuY2VsbGF0aW9uLnNlY3JldEtleSxcbiAgICAgICAgICBjb25uZWN0ZWQudHJhbnNhY3Rpb25TdGF0dXMsXG4gICAgICAgICksXG4gICAgICApO1xuICAgICAgbG9jYWwucGlwZSh1cHN0cmVhbSkucGlwZShsb2NhbCk7XG4gICAgICBhd2FpdCBQcm9taXNlLnJhY2UoW2Nsb3NlZChsb2NhbCksIGNsb3NlZCh1cHN0cmVhbSldKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcIkxha2ViYXNlIGNvbm5lY3Rpb24gY2xvc2VkXCIsIHtcbiAgICAgICAgZHVyYXRpb25NczogRGF0ZS5ub3coKSAtIHN0YXJ0ZWQsXG4gICAgICAgIHByb2plY3Q6IHJlc29sdmVkLnByb2plY3QsXG4gICAgICAgIGJyYW5jaDogcmVzb2x2ZWQuYnJhbmNoLFxuICAgICAgICBlbmRwb2ludDogcmVzb2x2ZWQuZW5kcG9pbnQsXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5mYWlsZWQgKz0gMTtcbiAgICAgIGNvbnN0IGZhaWx1cmUgPVxuICAgICAgICBlcnJvciBpbnN0YW5jZW9mIFByb3h5RmFpbHVyZVxuICAgICAgICAgID8gZXJyb3JcbiAgICAgICAgICA6IGVycm9yIGluc3RhbmNlb2YgUG9zdGdyZXNQcm90b2NvbEVycm9yXG4gICAgICAgICAgICA/IG5ldyBQcm94eUZhaWx1cmUoZXJyb3IubWVzc2FnZSwgXCIwOFAwMVwiKVxuICAgICAgICAgICAgOiBuZXcgUHJveHlGYWlsdXJlKG1lc3NhZ2UoZXJyb3IpKTtcbiAgICAgIGxvZ2dlci53YXJuKFwiTGFrZWJhc2UgY29ubmVjdGlvbiBmYWlsZWRcIiwge1xuICAgICAgICBkdXJhdGlvbk1zOiBEYXRlLm5vdygpIC0gc3RhcnRlZCxcbiAgICAgICAgZXJyb3I6IGZhaWx1cmUubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgaWYgKCFsb2NhbC5kZXN0cm95ZWQpIGxvY2FsLmVuZChmYXRhbEVycm9yKGZhaWx1cmUubWVzc2FnZSwgZmFpbHVyZS5zcWxzdGF0ZSkpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoY2FuY2VsbGF0aW9uKSB0aGlzLmNhbmNlbGxhdGlvbnMucmVtb3ZlKGNhbmNlbGxhdGlvbik7XG4gICAgICB1cHN0cmVhbT8uZGVzdHJveSgpO1xuICAgICAgbG9jYWwuZGVzdHJveSgpO1xuICAgICAgdGhpcy5jbG9zZWQgKz0gMTtcbiAgICAgIHRoaXMuYWN0aXZlIC09IDE7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXBvcnRTdGF0cygpOiB2b2lkIHtcbiAgICBsb2dnZXIuaW5mbyhcIkxha2ViYXNlIHByb3h5IGNvbm5lY3Rpb25zXCIsIHtcbiAgICAgIG9wZW5lZDogdGhpcy5vcGVuZWQsXG4gICAgICBjbG9zZWQ6IHRoaXMuY2xvc2VkLFxuICAgICAgZmFpbGVkOiB0aGlzLmZhaWxlZCxcbiAgICAgIGFjdGl2ZTogdGhpcy5hY3RpdmUsXG4gICAgfSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY29ubmVjdFVwc3RyZWFtKFxuICByZXNvbHZlZDogQXdhaXRlZDxSZXR1cm5UeXBlPExha2ViYXNlQ2xpZW50W1wicmVzb2x2ZVwiXT4+LFxuICBwYXNzd29yZDogc3RyaW5nLFxuICBzdGFydHVwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuKTogUHJvbWlzZTx7XG4gIHNvY2tldDogRHVwbGV4O1xuICBwYXJhbWV0ZXJzOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xuICBwcm9jZXNzSWQ6IG51bWJlcjtcbiAgc2VjcmV0S2V5OiBudW1iZXI7XG4gIHRyYW5zYWN0aW9uU3RhdHVzOiBzdHJpbmc7XG59PiB7XG4gIGNvbnN0IGNsaWVudCA9IG5ldyBDbGllbnQoe1xuICAgIGhvc3Q6IHJlc29sdmVkLmhvc3QsXG4gICAgcG9ydDogcmVzb2x2ZWQucG9ydCxcbiAgICBkYXRhYmFzZTogcmVzb2x2ZWQuZGF0YWJhc2UsXG4gICAgdXNlcjogcmVzb2x2ZWQudXNlcixcbiAgICBwYXNzd29yZCxcbiAgICBzc2w6IHsgcmVqZWN0VW5hdXRob3JpemVkOiB0cnVlLCBzZXJ2ZXJuYW1lOiByZXNvbHZlZC5ob3N0IH0sXG4gICAgYXBwbGljYXRpb25fbmFtZTogc3RhcnR1cC5hcHBsaWNhdGlvbl9uYW1lLFxuICAgIGNvbm5lY3Rpb25UaW1lb3V0TWlsbGlzOiAzMF8wMDAsXG4gIH0pIGFzIHVua25vd24gYXMgUGdDbGllbnRJbnRlcm5hbHM7XG4gIGNvbnN0IHBhcmFtZXRlcnMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICBjbGllbnQuZ2V0U3RhcnR1cENvbmYgPSAoKSA9PlxuICAgIHVwc3RyZWFtU3RhcnR1cFBhcmFtZXRlcnMoc3RhcnR1cCwgcmVzb2x2ZWQudXNlciwgcmVzb2x2ZWQuZGF0YWJhc2UpO1xuICBjbGllbnQub24oXCJlcnJvclwiLCAoZXJyb3IpID0+IHtcbiAgICBsb2dnZXIuZGVidWcoXCJMYWtlYmFzZSB1cHN0cmVhbSBjbGllbnQgY2xvc2VkXCIsIHsgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfSk7XG4gIH0pO1xuICBjbGllbnQuY29ubmVjdGlvbi5vbihcInBhcmFtZXRlclN0YXR1c1wiLCAobWVzc2FnZSkgPT4ge1xuICAgIHBhcmFtZXRlcnMuc2V0KG1lc3NhZ2UucGFyYW1ldGVyTmFtZSwgbWVzc2FnZS5wYXJhbWV0ZXJWYWx1ZSk7XG4gIH0pO1xuICBhd2FpdCBjbGllbnQuY29ubmVjdCgpO1xuICBjb25zdCBzb2NrZXQgPSBjbGllbnQuY29ubmVjdGlvbi5zdHJlYW07XG4gIHNvY2tldC5yZW1vdmVBbGxMaXN0ZW5lcnMoXCJkYXRhXCIpO1xuICByZXR1cm4ge1xuICAgIHNvY2tldCxcbiAgICBwYXJhbWV0ZXJzLFxuICAgIHByb2Nlc3NJZDogY2xpZW50LnByb2Nlc3NJRCxcbiAgICBzZWNyZXRLZXk6IGNsaWVudC5zZWNyZXRLZXksXG4gICAgdHJhbnNhY3Rpb25TdGF0dXM6IGNsaWVudC5fdHhTdGF0dXMgPz8gXCJJXCIsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGNsb3NlZChzb2NrZXQ6IER1cGxleCk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHNvY2tldC5vbmNlKFwiY2xvc2VcIiwgKCkgPT4gcmVzb2x2ZSgpKTtcbiAgICBzb2NrZXQub25jZShcImVycm9yXCIsIHJlamVjdCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBtZXNzYWdlKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcbiAgcmV0dXJuIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKTtcbn1cblxuY2xhc3MgUHJveHlGYWlsdXJlIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihcbiAgICBtZXNzYWdlOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgc3Fsc3RhdGUgPSBcIjA4MDAxXCIsXG4gICkge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Foreground `dbx model-gateway` command.
3
+ *
4
+ * @module
5
+ */
6
+ import { type CliServiceCliDependencies } from "@dbx-tools/cli-service/cli";
7
+ import { type CliServiceDefinition } from "@dbx-tools/cli-service/definition";
8
+ import { type ModelGatewayOptions } from "@dbx-tools/shared-model-gateway/options";
9
+ import { Command } from "commander";
10
+ /** Injectable foreground gateway boundary for CLI tests. */
11
+ export interface ModelGatewayCliDependencies {
12
+ start(options: ModelGatewayOptions): Promise<void>;
13
+ /** Optional service CLI boundary for tests and embedding. */
14
+ readonly service?: CliServiceCliDependencies;
15
+ }
16
+ /** Build the tray-only model-gateway service definition. */
17
+ export declare function modelGatewayServiceDefinition(options?: ModelGatewayOptions): CliServiceDefinition;
18
+ /** Build foreground and service model-gateway commands without starting a server. */
19
+ export declare function buildProgram(name?: string, dependencies?: ModelGatewayCliDependencies): Command;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Foreground `dbx model-gateway` command.
3
+ *
4
+ * @module
5
+ */
6
+ import { addArgs, parseArgs, serializeArgs } from "@dbx-tools/cli-args";
7
+ import { buildServiceCommand } from "@dbx-tools/cli-service/cli";
8
+ import { defineService } from "@dbx-tools/cli-service/definition";
9
+ import { ModelGatewayCliOptionsSchema, resolveModelGatewayCliOptions, } from "@dbx-tools/shared-model-gateway/options";
10
+ import { Command } from "commander";
11
+ import { PACKAGE_VERSION } from "../../index.js";
12
+ import { startModelGateway } from "./server.js";
13
+ const DEFAULT_DEPENDENCIES = {
14
+ start: startModelGateway,
15
+ };
16
+ /** Build the tray-only model-gateway service definition. */
17
+ export function modelGatewayServiceDefinition(options = {}) {
18
+ const { runtimeInfo: _, ...resolved } = resolveModelGatewayCliOptions(options);
19
+ const host = urlHost(resolved.listen.host);
20
+ return defineService(import.meta.url, {
21
+ id: "dbx-tools.cli-model-gateway",
22
+ name: "dbx model gateway",
23
+ command: {
24
+ binName: "dbx-model-gateway",
25
+ arguments: serializeArgs(resolved),
26
+ },
27
+ menu: [
28
+ {
29
+ type: "url",
30
+ label: "Models",
31
+ url: `http://${host}:${resolved.listen.port}/v1/models`,
32
+ },
33
+ ],
34
+ });
35
+ }
36
+ /** Build foreground and service model-gateway commands without starting a server. */
37
+ export function buildProgram(name = "dbx model-gateway", dependencies = DEFAULT_DEPENDENCIES) {
38
+ const version = PACKAGE_VERSION;
39
+ const program = addArgs(new Command()
40
+ .name(name)
41
+ .description("Run or manage the AppKit Databricks model gateway")
42
+ .version(version, "-v, --version"), ModelGatewayCliOptionsSchema).action(async () => {
43
+ const options = modelGatewayOptions(program);
44
+ if (options.runtimeInfo) {
45
+ process.stdout.write(`${JSON.stringify({ implementation: "typescript-appkit", version })}\n`);
46
+ return;
47
+ }
48
+ const { runtimeInfo: _, ...serverOptions } = options;
49
+ await dependencies.start(serverOptions);
50
+ });
51
+ const serviceCommand = buildServiceCommand(() => {
52
+ return modelGatewayServiceDefinition(modelGatewayOptions(program));
53
+ }, dependencies.service);
54
+ program.addCommand(serviceCommand);
55
+ return program;
56
+ }
57
+ function modelGatewayOptions(command) {
58
+ return parseArgs(command, ModelGatewayCliOptionsSchema);
59
+ }
60
+ function urlHost(host) {
61
+ return host.includes(":") ? `[${host}]` : host;
62
+ }
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vZGVsLWdhdGV3YXkvY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsbUJBQW1CLEVBQWtDLE1BQU0sNEJBQTRCLENBQUM7QUFDakcsT0FBTyxFQUFFLGFBQWEsRUFBNkIsTUFBTSxtQ0FBbUMsQ0FBQztBQUM3RixPQUFPLEVBQ0wsNEJBQTRCLEVBQzVCLDZCQUE2QixHQUc5QixNQUFNLHlDQUF5QyxDQUFDO0FBQ2pELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFcEMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQVNoRCxNQUFNLG9CQUFvQixHQUFnQztJQUN4RCxLQUFLLEVBQUUsaUJBQWlCO0NBQ3pCLENBQUM7QUFFRiw0REFBNEQ7QUFDNUQsTUFBTSxVQUFVLDZCQUE2QixDQUMzQyxVQUErQixFQUFFO0lBRWpDLE1BQU0sRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLEdBQUcsNkJBQTZCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDL0UsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsT0FBTyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7UUFDcEMsRUFBRSxFQUFFLDZCQUE2QjtRQUNqQyxJQUFJLEVBQUUsbUJBQW1CO1FBQ3pCLE9BQU8sRUFBRTtZQUNQLE9BQU8sRUFBRSxtQkFBbUI7WUFDNUIsU0FBUyxFQUFFLGFBQWEsQ0FBQyxRQUFRLENBQUM7U0FDbkM7UUFDRCxJQUFJLEVBQUU7WUFDSjtnQkFDRSxJQUFJLEVBQUUsS0FBSztnQkFDWCxLQUFLLEVBQUUsUUFBUTtnQkFDZixHQUFHLEVBQUUsVUFBVSxJQUFJLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLFlBQVk7YUFDeEQ7U0FDRjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxxRkFBcUY7QUFDckYsTUFBTSxVQUFVLFlBQVksQ0FDMUIsSUFBSSxHQUFHLG1CQUFtQixFQUMxQixlQUE0QyxvQkFBb0I7SUFFaEUsTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDO0lBQ2hDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FDckIsSUFBSSxPQUFPLEVBQUU7U0FDVixJQUFJLENBQUMsSUFBSSxDQUFDO1NBQ1YsV0FBVyxDQUFDLG1EQUFtRCxDQUFDO1NBQ2hFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLEVBQ3BDLDRCQUE0QixDQUM3QixDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksRUFBRTtRQUNsQixNQUFNLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM3QyxJQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QixPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxjQUFjLEVBQUUsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUYsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxHQUFHLGFBQWEsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUNyRCxNQUFNLFlBQVksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLGNBQWMsR0FBRyxtQkFBbUIsQ0FBQyxHQUFHLEVBQUU7UUFDOUMsT0FBTyw2QkFBNkIsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLENBQUMsRUFBRSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekIsT0FBTyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUNuQyxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxPQUFnQjtJQUMzQyxPQUFPLFNBQVMsQ0FBQyxPQUFPLEVBQUUsNEJBQTRCLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsSUFBWTtJQUMzQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGb3JlZ3JvdW5kIGBkYnggbW9kZWwtZ2F0ZXdheWAgY29tbWFuZC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgYWRkQXJncywgcGFyc2VBcmdzLCBzZXJpYWxpemVBcmdzIH0gZnJvbSBcIkBkYngtdG9vbHMvY2xpLWFyZ3NcIjtcbmltcG9ydCB7IGJ1aWxkU2VydmljZUNvbW1hbmQsIHR5cGUgQ2xpU2VydmljZUNsaURlcGVuZGVuY2llcyB9IGZyb20gXCJAZGJ4LXRvb2xzL2NsaS1zZXJ2aWNlL2NsaVwiO1xuaW1wb3J0IHsgZGVmaW5lU2VydmljZSwgdHlwZSBDbGlTZXJ2aWNlRGVmaW5pdGlvbiB9IGZyb20gXCJAZGJ4LXRvb2xzL2NsaS1zZXJ2aWNlL2RlZmluaXRpb25cIjtcbmltcG9ydCB7XG4gIE1vZGVsR2F0ZXdheUNsaU9wdGlvbnNTY2hlbWEsXG4gIHJlc29sdmVNb2RlbEdhdGV3YXlDbGlPcHRpb25zLFxuICB0eXBlIE1vZGVsR2F0ZXdheUNsaU9wdGlvbnMsXG4gIHR5cGUgTW9kZWxHYXRld2F5T3B0aW9ucyxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsLWdhdGV3YXkvb3B0aW9uc1wiO1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gXCJjb21tYW5kZXJcIjtcblxuaW1wb3J0IHsgUEFDS0FHRV9WRVJTSU9OIH0gZnJvbSBcIi4uLy4uL2luZGV4LnRzXCI7XG5pbXBvcnQgeyBzdGFydE1vZGVsR2F0ZXdheSB9IGZyb20gXCIuL3NlcnZlci50c1wiO1xuXG4vKiogSW5qZWN0YWJsZSBmb3JlZ3JvdW5kIGdhdGV3YXkgYm91bmRhcnkgZm9yIENMSSB0ZXN0cy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxHYXRld2F5Q2xpRGVwZW5kZW5jaWVzIHtcbiAgc3RhcnQob3B0aW9uczogTW9kZWxHYXRld2F5T3B0aW9ucyk6IFByb21pc2U8dm9pZD47XG4gIC8qKiBPcHRpb25hbCBzZXJ2aWNlIENMSSBib3VuZGFyeSBmb3IgdGVzdHMgYW5kIGVtYmVkZGluZy4gKi9cbiAgcmVhZG9ubHkgc2VydmljZT86IENsaVNlcnZpY2VDbGlEZXBlbmRlbmNpZXM7XG59XG5cbmNvbnN0IERFRkFVTFRfREVQRU5ERU5DSUVTOiBNb2RlbEdhdGV3YXlDbGlEZXBlbmRlbmNpZXMgPSB7XG4gIHN0YXJ0OiBzdGFydE1vZGVsR2F0ZXdheSxcbn07XG5cbi8qKiBCdWlsZCB0aGUgdHJheS1vbmx5IG1vZGVsLWdhdGV3YXkgc2VydmljZSBkZWZpbml0aW9uLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vZGVsR2F0ZXdheVNlcnZpY2VEZWZpbml0aW9uKFxuICBvcHRpb25zOiBNb2RlbEdhdGV3YXlPcHRpb25zID0ge30sXG4pOiBDbGlTZXJ2aWNlRGVmaW5pdGlvbiB7XG4gIGNvbnN0IHsgcnVudGltZUluZm86IF8sIC4uLnJlc29sdmVkIH0gPSByZXNvbHZlTW9kZWxHYXRld2F5Q2xpT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3QgaG9zdCA9IHVybEhvc3QocmVzb2x2ZWQubGlzdGVuLmhvc3QpO1xuICByZXR1cm4gZGVmaW5lU2VydmljZShpbXBvcnQubWV0YS51cmwsIHtcbiAgICBpZDogXCJkYngtdG9vbHMuY2xpLW1vZGVsLWdhdGV3YXlcIixcbiAgICBuYW1lOiBcImRieCBtb2RlbCBnYXRld2F5XCIsXG4gICAgY29tbWFuZDoge1xuICAgICAgYmluTmFtZTogXCJkYngtbW9kZWwtZ2F0ZXdheVwiLFxuICAgICAgYXJndW1lbnRzOiBzZXJpYWxpemVBcmdzKHJlc29sdmVkKSxcbiAgICB9LFxuICAgIG1lbnU6IFtcbiAgICAgIHtcbiAgICAgICAgdHlwZTogXCJ1cmxcIixcbiAgICAgICAgbGFiZWw6IFwiTW9kZWxzXCIsXG4gICAgICAgIHVybDogYGh0dHA6Ly8ke2hvc3R9OiR7cmVzb2x2ZWQubGlzdGVuLnBvcnR9L3YxL21vZGVsc2AsXG4gICAgICB9LFxuICAgIF0sXG4gIH0pO1xufVxuXG4vKiogQnVpbGQgZm9yZWdyb3VuZCBhbmQgc2VydmljZSBtb2RlbC1nYXRld2F5IGNvbW1hbmRzIHdpdGhvdXQgc3RhcnRpbmcgYSBzZXJ2ZXIuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRQcm9ncmFtKFxuICBuYW1lID0gXCJkYnggbW9kZWwtZ2F0ZXdheVwiLFxuICBkZXBlbmRlbmNpZXM6IE1vZGVsR2F0ZXdheUNsaURlcGVuZGVuY2llcyA9IERFRkFVTFRfREVQRU5ERU5DSUVTLFxuKTogQ29tbWFuZCB7XG4gIGNvbnN0IHZlcnNpb24gPSBQQUNLQUdFX1ZFUlNJT047XG4gIGNvbnN0IHByb2dyYW0gPSBhZGRBcmdzKFxuICAgIG5ldyBDb21tYW5kKClcbiAgICAgIC5uYW1lKG5hbWUpXG4gICAgICAuZGVzY3JpcHRpb24oXCJSdW4gb3IgbWFuYWdlIHRoZSBBcHBLaXQgRGF0YWJyaWNrcyBtb2RlbCBnYXRld2F5XCIpXG4gICAgICAudmVyc2lvbih2ZXJzaW9uLCBcIi12LCAtLXZlcnNpb25cIiksXG4gICAgTW9kZWxHYXRld2F5Q2xpT3B0aW9uc1NjaGVtYSxcbiAgKS5hY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtb2RlbEdhdGV3YXlPcHRpb25zKHByb2dyYW0pO1xuICAgIGlmIChvcHRpb25zLnJ1bnRpbWVJbmZvKSB7XG4gICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgJHtKU09OLnN0cmluZ2lmeSh7IGltcGxlbWVudGF0aW9uOiBcInR5cGVzY3JpcHQtYXBwa2l0XCIsIHZlcnNpb24gfSl9XFxuYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgcnVudGltZUluZm86IF8sIC4uLnNlcnZlck9wdGlvbnMgfSA9IG9wdGlvbnM7XG4gICAgYXdhaXQgZGVwZW5kZW5jaWVzLnN0YXJ0KHNlcnZlck9wdGlvbnMpO1xuICB9KTtcbiAgY29uc3Qgc2VydmljZUNvbW1hbmQgPSBidWlsZFNlcnZpY2VDb21tYW5kKCgpID0+IHtcbiAgICByZXR1cm4gbW9kZWxHYXRld2F5U2VydmljZURlZmluaXRpb24obW9kZWxHYXRld2F5T3B0aW9ucyhwcm9ncmFtKSk7XG4gIH0sIGRlcGVuZGVuY2llcy5zZXJ2aWNlKTtcbiAgcHJvZ3JhbS5hZGRDb21tYW5kKHNlcnZpY2VDb21tYW5kKTtcbiAgcmV0dXJuIHByb2dyYW07XG59XG5cbmZ1bmN0aW9uIG1vZGVsR2F0ZXdheU9wdGlvbnMoY29tbWFuZDogQ29tbWFuZCk6IE1vZGVsR2F0ZXdheUNsaU9wdGlvbnMge1xuICByZXR1cm4gcGFyc2VBcmdzKGNvbW1hbmQsIE1vZGVsR2F0ZXdheUNsaU9wdGlvbnNTY2hlbWEpO1xufVxuXG5mdW5jdGlvbiB1cmxIb3N0KGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBob3N0LmluY2x1ZGVzKFwiOlwiKSA/IGBbJHtob3N0fV1gIDogaG9zdDtcbn1cbiJdfQ==
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Foreground model-gateway server owned by the CLI package.
3
+ *
4
+ * @module
5
+ */
6
+ import { server } from "@databricks/appkit";
7
+ import { type ModelGatewayOptions } from "@dbx-tools/shared-model-gateway/options";
8
+ type AppKitServerOptions = NonNullable<Parameters<typeof server>[0]>;
9
+ /** Resolve AppKit server settings for the loopback model gateway. */
10
+ export declare function modelGatewayServerOptions(options?: ModelGatewayOptions): AppKitServerOptions;
11
+ /** Start the foreground model gateway and keep its AppKit server active. */
12
+ export declare function startModelGateway(options?: ModelGatewayOptions): Promise<void>;
13
+ export {};
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Foreground model-gateway server owned by the CLI package.
3
+ *
4
+ * @module
5
+ */
6
+ import { createApp, server } from "@databricks/appkit";
7
+ import { modelGateway } from "@dbx-tools/appkit-model-gateway/plugin";
8
+ import { sendHealth } from "@dbx-tools/appkit-model-gateway/routes";
9
+ import { workspaceClient } from "@dbx-tools/databricks";
10
+ import { resolveModelGatewayOptions, } from "@dbx-tools/shared-model-gateway/options";
11
+ /** Resolve AppKit server settings for the loopback model gateway. */
12
+ export function modelGatewayServerOptions(options = {}) {
13
+ return appKitServerOptions(resolveModelGatewayOptions(options));
14
+ }
15
+ function appKitServerOptions(options) {
16
+ return {
17
+ bodyLimit: options.bodyLimit,
18
+ host: options.listen.host,
19
+ port: options.listen.port,
20
+ };
21
+ }
22
+ /** Start the foreground model gateway and keep its AppKit server active. */
23
+ export async function startModelGateway(options = {}) {
24
+ const resolved = resolveModelGatewayOptions(options);
25
+ const client = await workspaceClient.createWorkspaceClient({
26
+ ...(resolved.profile ? { profile: resolved.profile } : {}),
27
+ });
28
+ await createApp({
29
+ client,
30
+ plugins: [modelGateway(), server(appKitServerOptions(resolved))],
31
+ onPluginsReady(appkit) {
32
+ appkit.server.extend((application) => {
33
+ application.get("/api/healthz", (_request, response) => {
34
+ sendHealth(response);
35
+ });
36
+ application.get("/v1/models", (request, response) => {
37
+ void appkit.modelGateway.models(request, response);
38
+ });
39
+ for (const [path, protocol] of [
40
+ ["/v1/chat/completions", "openai-chat"],
41
+ ["/v1/responses", "openai-responses"],
42
+ ["/v1/messages", "anthropic-messages"],
43
+ ["/v1/embeddings", "openai-embeddings"],
44
+ ]) {
45
+ application.post(path, (request, response) => {
46
+ void appkit.modelGateway.inference(protocol, request, response);
47
+ });
48
+ }
49
+ });
50
+ },
51
+ });
52
+ }
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vZGVsLWdhdGV3YXkvc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUN0RSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDcEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3hELE9BQU8sRUFDTCwwQkFBMEIsR0FHM0IsTUFBTSx5Q0FBeUMsQ0FBQztBQUlqRCxxRUFBcUU7QUFDckUsTUFBTSxVQUFVLHlCQUF5QixDQUFDLFVBQStCLEVBQUU7SUFDekUsT0FBTyxtQkFBbUIsQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ2xFLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUFDLE9BQW9DO0lBQy9ELE9BQU87UUFDTCxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7UUFDNUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSTtRQUN6QixJQUFJLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJO0tBQzFCLENBQUM7QUFDSixDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLE1BQU0sQ0FBQyxLQUFLLFVBQVUsaUJBQWlCLENBQUMsVUFBK0IsRUFBRTtJQUN2RSxNQUFNLFFBQVEsR0FBRywwQkFBMEIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRCxNQUFNLE1BQU0sR0FBRyxNQUFNLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQztRQUN6RCxHQUFHLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDM0QsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxTQUFTLENBQUM7UUFDZCxNQUFNO1FBQ04sT0FBTyxFQUFFLENBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDaEUsY0FBYyxDQUFDLE1BQU07WUFDbkIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRTtnQkFDbkMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLEVBQUU7b0JBQ3JELFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDdkIsQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsV0FBVyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7b0JBQ2xELEtBQUssTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUNyRCxDQUFDLENBQUMsQ0FBQztnQkFDSCxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUk7b0JBQzdCLENBQUMsc0JBQXNCLEVBQUUsYUFBYSxDQUFDO29CQUN2QyxDQUFDLGVBQWUsRUFBRSxrQkFBa0IsQ0FBQztvQkFDckMsQ0FBQyxjQUFjLEVBQUUsb0JBQW9CLENBQUM7b0JBQ3RDLENBQUMsZ0JBQWdCLEVBQUUsbUJBQW1CLENBQUM7aUJBQy9CLEVBQUUsQ0FBQztvQkFDWCxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsRUFBRTt3QkFDM0MsS0FBSyxNQUFNLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO29CQUNsRSxDQUFDLENBQUMsQ0FBQztnQkFDTCxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRm9yZWdyb3VuZCBtb2RlbC1nYXRld2F5IHNlcnZlciBvd25lZCBieSB0aGUgQ0xJIHBhY2thZ2UuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUFwcCwgc2VydmVyIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgbW9kZWxHYXRld2F5IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0LW1vZGVsLWdhdGV3YXkvcGx1Z2luXCI7XG5pbXBvcnQgeyBzZW5kSGVhbHRoIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0LW1vZGVsLWdhdGV3YXkvcm91dGVzXCI7XG5pbXBvcnQgeyB3b3Jrc3BhY2VDbGllbnQgfSBmcm9tIFwiQGRieC10b29scy9kYXRhYnJpY2tzXCI7XG5pbXBvcnQge1xuICByZXNvbHZlTW9kZWxHYXRld2F5T3B0aW9ucyxcbiAgdHlwZSBNb2RlbEdhdGV3YXlPcHRpb25zLFxuICB0eXBlIFJlc29sdmVkTW9kZWxHYXRld2F5T3B0aW9ucyxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsLWdhdGV3YXkvb3B0aW9uc1wiO1xuXG50eXBlIEFwcEtpdFNlcnZlck9wdGlvbnMgPSBOb25OdWxsYWJsZTxQYXJhbWV0ZXJzPHR5cGVvZiBzZXJ2ZXI+WzBdPjtcblxuLyoqIFJlc29sdmUgQXBwS2l0IHNlcnZlciBzZXR0aW5ncyBmb3IgdGhlIGxvb3BiYWNrIG1vZGVsIGdhdGV3YXkuICovXG5leHBvcnQgZnVuY3Rpb24gbW9kZWxHYXRld2F5U2VydmVyT3B0aW9ucyhvcHRpb25zOiBNb2RlbEdhdGV3YXlPcHRpb25zID0ge30pOiBBcHBLaXRTZXJ2ZXJPcHRpb25zIHtcbiAgcmV0dXJuIGFwcEtpdFNlcnZlck9wdGlvbnMocmVzb2x2ZU1vZGVsR2F0ZXdheU9wdGlvbnMob3B0aW9ucykpO1xufVxuXG5mdW5jdGlvbiBhcHBLaXRTZXJ2ZXJPcHRpb25zKG9wdGlvbnM6IFJlc29sdmVkTW9kZWxHYXRld2F5T3B0aW9ucyk6IEFwcEtpdFNlcnZlck9wdGlvbnMge1xuICByZXR1cm4ge1xuICAgIGJvZHlMaW1pdDogb3B0aW9ucy5ib2R5TGltaXQsXG4gICAgaG9zdDogb3B0aW9ucy5saXN0ZW4uaG9zdCxcbiAgICBwb3J0OiBvcHRpb25zLmxpc3Rlbi5wb3J0LFxuICB9O1xufVxuXG4vKiogU3RhcnQgdGhlIGZvcmVncm91bmQgbW9kZWwgZ2F0ZXdheSBhbmQga2VlcCBpdHMgQXBwS2l0IHNlcnZlciBhY3RpdmUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnRNb2RlbEdhdGV3YXkob3B0aW9uczogTW9kZWxHYXRld2F5T3B0aW9ucyA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZU1vZGVsR2F0ZXdheU9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IGNsaWVudCA9IGF3YWl0IHdvcmtzcGFjZUNsaWVudC5jcmVhdGVXb3Jrc3BhY2VDbGllbnQoe1xuICAgIC4uLihyZXNvbHZlZC5wcm9maWxlID8geyBwcm9maWxlOiByZXNvbHZlZC5wcm9maWxlIH0gOiB7fSksXG4gIH0pO1xuICBhd2FpdCBjcmVhdGVBcHAoe1xuICAgIGNsaWVudCxcbiAgICBwbHVnaW5zOiBbbW9kZWxHYXRld2F5KCksIHNlcnZlcihhcHBLaXRTZXJ2ZXJPcHRpb25zKHJlc29sdmVkKSldLFxuICAgIG9uUGx1Z2luc1JlYWR5KGFwcGtpdCkge1xuICAgICAgYXBwa2l0LnNlcnZlci5leHRlbmQoKGFwcGxpY2F0aW9uKSA9PiB7XG4gICAgICAgIGFwcGxpY2F0aW9uLmdldChcIi9hcGkvaGVhbHRoelwiLCAoX3JlcXVlc3QsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgc2VuZEhlYWx0aChyZXNwb25zZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBhcHBsaWNhdGlvbi5nZXQoXCIvdjEvbW9kZWxzXCIsIChyZXF1ZXN0LCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIHZvaWQgYXBwa2l0Lm1vZGVsR2F0ZXdheS5tb2RlbHMocmVxdWVzdCwgcmVzcG9uc2UpO1xuICAgICAgICB9KTtcbiAgICAgICAgZm9yIChjb25zdCBbcGF0aCwgcHJvdG9jb2xdIG9mIFtcbiAgICAgICAgICBbXCIvdjEvY2hhdC9jb21wbGV0aW9uc1wiLCBcIm9wZW5haS1jaGF0XCJdLFxuICAgICAgICAgIFtcIi92MS9yZXNwb25zZXNcIiwgXCJvcGVuYWktcmVzcG9uc2VzXCJdLFxuICAgICAgICAgIFtcIi92MS9tZXNzYWdlc1wiLCBcImFudGhyb3BpYy1tZXNzYWdlc1wiXSxcbiAgICAgICAgICBbXCIvdjEvZW1iZWRkaW5nc1wiLCBcIm9wZW5haS1lbWJlZGRpbmdzXCJdLFxuICAgICAgICBdIGFzIGNvbnN0KSB7XG4gICAgICAgICAgYXBwbGljYXRpb24ucG9zdChwYXRoLCAocmVxdWVzdCwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIHZvaWQgYXBwa2l0Lm1vZGVsR2F0ZXdheS5pbmZlcmVuY2UocHJvdG9jb2wsIHJlcXVlc3QsIHJlc3BvbnNlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfSk7XG59XG4iXX0=