@channel.io/app-sdk-server 0.13.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/datasource-runners.test.d.ts +2 -0
- package/dist/__tests__/datasource-runners.test.d.ts.map +1 -0
- package/dist/__tests__/datasource-runners.test.js +244 -0
- package/dist/__tests__/datasource-runners.test.js.map +1 -0
- package/dist/__tests__/datasource.test.d.ts +2 -0
- package/dist/__tests__/datasource.test.d.ts.map +1 -0
- package/dist/__tests__/datasource.test.js +152 -0
- package/dist/__tests__/datasource.test.js.map +1 -0
- package/dist/__tests__/testing-utils.test.js +1 -1
- package/dist/__tests__/testing-utils.test.js.map +1 -1
- package/dist/datasource/arrow.d.ts +27 -0
- package/dist/datasource/arrow.d.ts.map +1 -0
- package/dist/datasource/arrow.js +261 -0
- package/dist/datasource/arrow.js.map +1 -0
- package/dist/datasource/bigquery.d.ts +97 -0
- package/dist/datasource/bigquery.d.ts.map +1 -0
- package/dist/datasource/bigquery.js +297 -0
- package/dist/datasource/bigquery.js.map +1 -0
- package/dist/datasource/grpc.d.ts +28 -0
- package/dist/datasource/grpc.d.ts.map +1 -0
- package/dist/datasource/grpc.js +292 -0
- package/dist/datasource/grpc.js.map +1 -0
- package/dist/datasource/index.d.ts +8 -0
- package/dist/datasource/index.d.ts.map +1 -0
- package/dist/datasource/index.js +8 -0
- package/dist/datasource/index.js.map +1 -0
- package/dist/datasource/policy.d.ts +16 -0
- package/dist/datasource/policy.d.ts.map +1 -0
- package/dist/datasource/policy.js +112 -0
- package/dist/datasource/policy.js.map +1 -0
- package/dist/datasource/postgres.d.ts +32 -0
- package/dist/datasource/postgres.d.ts.map +1 -0
- package/dist/datasource/postgres.js +234 -0
- package/dist/datasource/postgres.js.map +1 -0
- package/dist/datasource/query-handlers.d.ts +32 -0
- package/dist/datasource/query-handlers.d.ts.map +1 -0
- package/dist/datasource/query-handlers.js +58 -0
- package/dist/datasource/query-handlers.js.map +1 -0
- package/dist/datasource/types.d.ts +134 -0
- package/dist/datasource/types.d.ts.map +1 -0
- package/dist/datasource/types.js +34 -0
- package/dist/datasource/types.js.map +1 -0
- package/dist/decorators/extension-names.d.ts +1 -1
- package/dist/decorators/extension-names.d.ts.map +1 -1
- package/dist/decorators/extension-names.js +1 -0
- package/dist/decorators/extension-names.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/nestjs/channel-app.controller.d.ts +2 -2
- package/dist/nestjs/channel-app.controller.d.ts.map +1 -1
- package/dist/nestjs/channel-app.controller.js.map +1 -1
- package/package.json +30 -4
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { DataSourceErrorCode, DataSourceExecutionError } from "./types.js";
|
|
3
|
+
let cachedArrow;
|
|
4
|
+
export function encodeRowsToArrowIPC(columns, rows) {
|
|
5
|
+
if (columns.length === 0) {
|
|
6
|
+
throw new Error("columns are required");
|
|
7
|
+
}
|
|
8
|
+
return rowsToArrowIPC(columns, rows.map((row) => columns.map((column) => row[column.name])));
|
|
9
|
+
}
|
|
10
|
+
export function arrowRowsChunk(columns, rows) {
|
|
11
|
+
return {
|
|
12
|
+
arrow: {
|
|
13
|
+
dataBody: encodeRowsToArrowIPC(columns, rows),
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function resultChunk(rowCount, limitExceeded = false, executionMs = 0) {
|
|
18
|
+
return {
|
|
19
|
+
result: {
|
|
20
|
+
rowCount,
|
|
21
|
+
limitExceeded,
|
|
22
|
+
executionMs,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function writeRowsAsArrowIpcBatch(sink, fields, rows, options = {}) {
|
|
27
|
+
const bytes = rowsToArrowIPC(fields, rows);
|
|
28
|
+
let schemaSent = false;
|
|
29
|
+
let frameCount = 0;
|
|
30
|
+
for (const frame of splitArrowIpcStream(bytes)) {
|
|
31
|
+
if (frame.kind === "schema") {
|
|
32
|
+
if (options.sendSchema !== false) {
|
|
33
|
+
options.byteLimit?.reserve(frame.bytes.byteLength);
|
|
34
|
+
sink.send({ arrow: { dataHeader: frame.bytes } });
|
|
35
|
+
schemaSent = true;
|
|
36
|
+
frameCount++;
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
options.byteLimit?.reserve(frame.bytes.byteLength);
|
|
41
|
+
sink.send({ arrow: { dataBody: frame.bytes } });
|
|
42
|
+
frameCount++;
|
|
43
|
+
}
|
|
44
|
+
return { schemaSent, frameCount };
|
|
45
|
+
}
|
|
46
|
+
function rowsToArrowIPC(fields, rows) {
|
|
47
|
+
if (fields.length === 0) {
|
|
48
|
+
throw new Error("columns are required");
|
|
49
|
+
}
|
|
50
|
+
const arrow = loadApacheArrow();
|
|
51
|
+
const usedNames = new Map();
|
|
52
|
+
const arrays = {};
|
|
53
|
+
fields.forEach((field, index) => {
|
|
54
|
+
const name = uniqueColumnName(field.name || `column_${index + 1}`, usedNames);
|
|
55
|
+
const values = rows.map((row) => normalizeArrowValue(row[index], field));
|
|
56
|
+
const type = arrowTypeFromField(arrow, field);
|
|
57
|
+
arrays[name] = arrow.vectorFromArray ? arrow.vectorFromArray(values, type) : values;
|
|
58
|
+
});
|
|
59
|
+
const table = arrow.vectorFromArray
|
|
60
|
+
? new arrow.Table(arrays)
|
|
61
|
+
: arrow.tableFromArrays(arrays);
|
|
62
|
+
return arrow.tableToIPC(table, "stream");
|
|
63
|
+
}
|
|
64
|
+
function splitArrowIpcStream(bytes) {
|
|
65
|
+
const arrow = loadApacheArrow();
|
|
66
|
+
const frames = [];
|
|
67
|
+
let offset = 0;
|
|
68
|
+
while (offset < bytes.byteLength) {
|
|
69
|
+
const frameStart = offset;
|
|
70
|
+
let metadataLength = readInt32LE(bytes, offset);
|
|
71
|
+
offset += 4;
|
|
72
|
+
if (metadataLength === 0) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (metadataLength === -1) {
|
|
76
|
+
metadataLength = readInt32LE(bytes, offset);
|
|
77
|
+
offset += 4;
|
|
78
|
+
if (metadataLength === 0) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const metadataStart = offset;
|
|
83
|
+
const metadataEnd = metadataStart + metadataLength;
|
|
84
|
+
if (metadataEnd > bytes.byteLength) {
|
|
85
|
+
throw new Error("invalid Arrow IPC metadata length");
|
|
86
|
+
}
|
|
87
|
+
const message = arrow.Message.decode(bytes.slice(metadataStart, metadataEnd));
|
|
88
|
+
const bodyLength = Number(message.bodyLength ?? 0);
|
|
89
|
+
const frameEnd = metadataEnd + bodyLength;
|
|
90
|
+
if (frameEnd > bytes.byteLength) {
|
|
91
|
+
throw new Error("invalid Arrow IPC body length");
|
|
92
|
+
}
|
|
93
|
+
if (message.headerType === arrow.MessageHeader.Schema) {
|
|
94
|
+
frames.push({ kind: "schema", bytes: bytes.slice(frameStart, frameEnd) });
|
|
95
|
+
}
|
|
96
|
+
else if (message.headerType === arrow.MessageHeader.RecordBatch ||
|
|
97
|
+
message.headerType === arrow.MessageHeader.DictionaryBatch) {
|
|
98
|
+
frames.push({ kind: "body", bytes: bytes.slice(frameStart, frameEnd) });
|
|
99
|
+
}
|
|
100
|
+
offset = frameEnd;
|
|
101
|
+
}
|
|
102
|
+
return frames;
|
|
103
|
+
}
|
|
104
|
+
function arrowTypeFromField(arrow, field) {
|
|
105
|
+
switch (field.dataTypeID) {
|
|
106
|
+
case 16:
|
|
107
|
+
return new arrow.Bool();
|
|
108
|
+
case 21:
|
|
109
|
+
return new arrow.Int16();
|
|
110
|
+
case 23:
|
|
111
|
+
return new arrow.Int32();
|
|
112
|
+
case 20:
|
|
113
|
+
return new arrow.Int64();
|
|
114
|
+
case 700:
|
|
115
|
+
case 701:
|
|
116
|
+
return new arrow.Float64();
|
|
117
|
+
case 17:
|
|
118
|
+
return new arrow.Binary();
|
|
119
|
+
case 1082:
|
|
120
|
+
return new arrow.DateDay();
|
|
121
|
+
case 1114:
|
|
122
|
+
case 1184:
|
|
123
|
+
return new arrow.TimestampMillisecond("UTC");
|
|
124
|
+
default:
|
|
125
|
+
return arrowTypeFromDatabaseTypeName(arrow, field.databaseType ?? field.type);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function arrowTypeFromDatabaseTypeName(arrow, databaseType) {
|
|
129
|
+
switch (databaseType?.trim().toUpperCase()) {
|
|
130
|
+
case "BOOL":
|
|
131
|
+
case "BOOLEAN":
|
|
132
|
+
return new arrow.Bool();
|
|
133
|
+
case "INT2":
|
|
134
|
+
case "SMALLINT":
|
|
135
|
+
return new arrow.Int16();
|
|
136
|
+
case "INT4":
|
|
137
|
+
case "INTEGER":
|
|
138
|
+
case "SERIAL":
|
|
139
|
+
return new arrow.Int32();
|
|
140
|
+
case "INT8":
|
|
141
|
+
case "BIGINT":
|
|
142
|
+
case "BIGSERIAL":
|
|
143
|
+
return new arrow.Int64();
|
|
144
|
+
case "FLOAT4":
|
|
145
|
+
case "FLOAT8":
|
|
146
|
+
case "REAL":
|
|
147
|
+
case "DOUBLE":
|
|
148
|
+
case "DOUBLE PRECISION":
|
|
149
|
+
case "NUMERIC":
|
|
150
|
+
case "DECIMAL":
|
|
151
|
+
return new arrow.Float64();
|
|
152
|
+
case "BYTEA":
|
|
153
|
+
case "BINARY":
|
|
154
|
+
case "VARBINARY":
|
|
155
|
+
return new arrow.Binary();
|
|
156
|
+
case "DATE":
|
|
157
|
+
return new arrow.DateDay();
|
|
158
|
+
case "TIMESTAMP":
|
|
159
|
+
case "TIMESTAMPTZ":
|
|
160
|
+
case "TIMESTAMPZ":
|
|
161
|
+
case "DATETIME":
|
|
162
|
+
return new arrow.TimestampMillisecond("UTC");
|
|
163
|
+
default:
|
|
164
|
+
return new arrow.Utf8();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function normalizeArrowValue(value, field) {
|
|
168
|
+
if (value === null || value === undefined) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
switch (field.dataTypeID) {
|
|
172
|
+
case 20:
|
|
173
|
+
return typeof value === "bigint" ? value : BigInt(stringifyArrowValue(value));
|
|
174
|
+
case 21:
|
|
175
|
+
case 23:
|
|
176
|
+
case 700:
|
|
177
|
+
case 701:
|
|
178
|
+
return Number(value);
|
|
179
|
+
case 17:
|
|
180
|
+
return value instanceof Uint8Array ? value : Buffer.from(stringifyArrowValue(value));
|
|
181
|
+
case 1082:
|
|
182
|
+
case 1114:
|
|
183
|
+
case 1184:
|
|
184
|
+
return value instanceof Date ? value : new Date(stringifyArrowValue(value));
|
|
185
|
+
case 114:
|
|
186
|
+
case 3802:
|
|
187
|
+
case 1700:
|
|
188
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
189
|
+
default:
|
|
190
|
+
if (value instanceof Date || value instanceof Uint8Array) {
|
|
191
|
+
return value;
|
|
192
|
+
}
|
|
193
|
+
if (typeof value === "bigint") {
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
if (typeof value === "object") {
|
|
197
|
+
return JSON.stringify(value);
|
|
198
|
+
}
|
|
199
|
+
return value;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function stringifyArrowValue(value) {
|
|
203
|
+
switch (typeof value) {
|
|
204
|
+
case "string":
|
|
205
|
+
return value;
|
|
206
|
+
case "number":
|
|
207
|
+
case "boolean":
|
|
208
|
+
case "bigint":
|
|
209
|
+
return value.toString();
|
|
210
|
+
case "symbol":
|
|
211
|
+
return value.description ?? "";
|
|
212
|
+
case "undefined":
|
|
213
|
+
return "";
|
|
214
|
+
case "function":
|
|
215
|
+
return "";
|
|
216
|
+
case "object":
|
|
217
|
+
if (value === null) {
|
|
218
|
+
return "";
|
|
219
|
+
}
|
|
220
|
+
if (value instanceof Date) {
|
|
221
|
+
return value.toISOString();
|
|
222
|
+
}
|
|
223
|
+
if (value instanceof Uint8Array) {
|
|
224
|
+
return Buffer.from(value).toString();
|
|
225
|
+
}
|
|
226
|
+
return JSON.stringify(value);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function uniqueColumnName(name, usedNames) {
|
|
230
|
+
const previous = usedNames.get(name) ?? 0;
|
|
231
|
+
usedNames.set(name, previous + 1);
|
|
232
|
+
return previous === 0 ? name : `${name}_${previous + 1}`;
|
|
233
|
+
}
|
|
234
|
+
function readInt32LE(bytes, offset) {
|
|
235
|
+
if (offset + 4 > bytes.byteLength) {
|
|
236
|
+
throw new Error("invalid Arrow IPC frame");
|
|
237
|
+
}
|
|
238
|
+
return new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getInt32(0, true);
|
|
239
|
+
}
|
|
240
|
+
function loadApacheArrow() {
|
|
241
|
+
if (cachedArrow) {
|
|
242
|
+
return cachedArrow;
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
const require = createRequire(import.meta.url);
|
|
246
|
+
cachedArrow = require("apache-arrow");
|
|
247
|
+
return cachedArrow;
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
throw new DataSourceExecutionError({
|
|
251
|
+
code: DataSourceErrorCode.Unavailable,
|
|
252
|
+
message: `apache-arrow is required for datasource Arrow conversion: ${errorMessage(error)}`,
|
|
253
|
+
retryable: false,
|
|
254
|
+
cause: error,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function errorMessage(error) {
|
|
259
|
+
return error instanceof Error ? error.message : String(error);
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=arrow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arrow.js","sourceRoot":"","sources":["../../src/datasource/arrow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { DataSourceTableConfig } from "./policy.js";
|
|
2
|
+
import { type DataSourceQueryExecutor, type ExecuteQueryRequest, type QueryChunkSink } from "./types.js";
|
|
3
|
+
export interface BigQueryDataSourceConfig {
|
|
4
|
+
projectId: string;
|
|
5
|
+
credentialsJson?: string;
|
|
6
|
+
credentialsJsonEnv?: string;
|
|
7
|
+
credentialsEnvVars?: readonly string[];
|
|
8
|
+
keyFilename?: string;
|
|
9
|
+
clientOptions?: Record<string, unknown>;
|
|
10
|
+
bigQueryClient?: BigQueryClientLike;
|
|
11
|
+
readClient?: BigQueryReadClientLike;
|
|
12
|
+
sources: readonly BigQueryDataSourceSourceConfig[];
|
|
13
|
+
}
|
|
14
|
+
export interface BigQueryDataSourceSourceConfig {
|
|
15
|
+
sourceId: string;
|
|
16
|
+
projectId?: string;
|
|
17
|
+
datasetId: string;
|
|
18
|
+
location?: string;
|
|
19
|
+
tables?: readonly DataSourceTableConfig[];
|
|
20
|
+
maxStreamCount?: number;
|
|
21
|
+
maximumBytesBilled?: string | number | bigint;
|
|
22
|
+
}
|
|
23
|
+
export declare function createBigQueryDataSourceExecutor(config: BigQueryDataSourceConfig): BigQueryDataSourceExecutor;
|
|
24
|
+
export declare class BigQueryDataSourceExecutor implements DataSourceQueryExecutor {
|
|
25
|
+
private readonly config;
|
|
26
|
+
private readonly sources;
|
|
27
|
+
private bigQueryClient?;
|
|
28
|
+
private readClient?;
|
|
29
|
+
constructor(config: BigQueryDataSourceConfig);
|
|
30
|
+
executeQuery(request: ExecuteQueryRequest, sink: QueryChunkSink): Promise<void>;
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
private ensureClients;
|
|
33
|
+
}
|
|
34
|
+
export interface BigQueryClientLike {
|
|
35
|
+
createQueryJob(options: BigQueryQueryJobOptions): Promise<[BigQueryJobLike]>;
|
|
36
|
+
}
|
|
37
|
+
export interface BigQueryJobLike {
|
|
38
|
+
getQueryResults(options: Record<string, unknown>): Promise<unknown>;
|
|
39
|
+
getMetadata(): Promise<[BigQueryJobMetadata]>;
|
|
40
|
+
}
|
|
41
|
+
export interface BigQueryReadClientLike {
|
|
42
|
+
createReadSession(request: BigQueryCreateReadSessionRequest): Promise<[BigQueryReadSession]>;
|
|
43
|
+
readRows(request: {
|
|
44
|
+
readStream: string;
|
|
45
|
+
}): AsyncIterable<BigQueryReadRowsResponse>;
|
|
46
|
+
close?(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
export interface BigQueryQueryJobOptions {
|
|
49
|
+
query: string;
|
|
50
|
+
useLegacySql: boolean;
|
|
51
|
+
defaultDataset: {
|
|
52
|
+
projectId: string;
|
|
53
|
+
datasetId: string;
|
|
54
|
+
};
|
|
55
|
+
location?: string;
|
|
56
|
+
jobTimeoutMs?: number;
|
|
57
|
+
maximumBytesBilled?: string;
|
|
58
|
+
labels?: Record<string, string>;
|
|
59
|
+
}
|
|
60
|
+
export interface BigQueryJobMetadata {
|
|
61
|
+
configuration?: {
|
|
62
|
+
query?: {
|
|
63
|
+
destinationTable?: Partial<BigQueryTableRef>;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export interface BigQueryTableRef {
|
|
68
|
+
projectId: string;
|
|
69
|
+
datasetId: string;
|
|
70
|
+
tableId: string;
|
|
71
|
+
}
|
|
72
|
+
export interface BigQueryCreateReadSessionRequest {
|
|
73
|
+
parent: string;
|
|
74
|
+
readSession: {
|
|
75
|
+
table: string;
|
|
76
|
+
dataFormat: "ARROW";
|
|
77
|
+
};
|
|
78
|
+
maxStreamCount: number;
|
|
79
|
+
}
|
|
80
|
+
export interface BigQueryReadSession {
|
|
81
|
+
arrowSchema?: {
|
|
82
|
+
serializedSchema?: unknown;
|
|
83
|
+
} | null;
|
|
84
|
+
streams?: {
|
|
85
|
+
name?: string | null;
|
|
86
|
+
}[] | null;
|
|
87
|
+
}
|
|
88
|
+
export interface BigQueryReadRowsResponse {
|
|
89
|
+
arrowSchema?: {
|
|
90
|
+
serializedSchema?: unknown;
|
|
91
|
+
} | null;
|
|
92
|
+
arrowRecordBatch?: {
|
|
93
|
+
serializedRecordBatch?: unknown;
|
|
94
|
+
} | null;
|
|
95
|
+
rowCount?: unknown;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=bigquery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bigquery.d.ts","sourceRoot":"","sources":["../../src/datasource/bigquery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { DataSourceByteLimitTracker, queryWithRowLimit, validateReadOnlyQuery } from "./policy.js";
|
|
2
|
+
import { DataSourceErrorCode, DataSourceExecutionError, } from "./types.js";
|
|
3
|
+
export function createBigQueryDataSourceExecutor(config) {
|
|
4
|
+
return new BigQueryDataSourceExecutor(config);
|
|
5
|
+
}
|
|
6
|
+
export class BigQueryDataSourceExecutor {
|
|
7
|
+
config;
|
|
8
|
+
sources = new Map();
|
|
9
|
+
bigQueryClient;
|
|
10
|
+
readClient;
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
const projectId = config.projectId.trim();
|
|
14
|
+
if (!projectId) {
|
|
15
|
+
throw new Error("BigQuery project_id is required");
|
|
16
|
+
}
|
|
17
|
+
if (config.sources.length === 0) {
|
|
18
|
+
throw new Error("at least one BigQuery datasource source is required");
|
|
19
|
+
}
|
|
20
|
+
for (const source of config.sources) {
|
|
21
|
+
const normalized = normalizeSource(source, projectId);
|
|
22
|
+
if (this.sources.has(normalized.sourceId)) {
|
|
23
|
+
throw new Error(`duplicate datasource source_id: ${normalized.sourceId}`);
|
|
24
|
+
}
|
|
25
|
+
this.sources.set(normalized.sourceId, normalized);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async executeQuery(request, sink) {
|
|
29
|
+
const req = normalizeRequest(request);
|
|
30
|
+
const source = this.sources.get(req.sourceId);
|
|
31
|
+
if (!source) {
|
|
32
|
+
throw new DataSourceExecutionError({
|
|
33
|
+
code: DataSourceErrorCode.SourceNotFound,
|
|
34
|
+
message: `unknown datasource source_id: ${req.sourceId}`,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
validateReadOnlyQuery(req.query, [], source.tables ?? []);
|
|
38
|
+
const startedAt = Date.now();
|
|
39
|
+
const clients = await this.ensureClients();
|
|
40
|
+
const byteLimit = new DataSourceByteLimitTracker(req.byteLimit);
|
|
41
|
+
try {
|
|
42
|
+
const destination = await runQueryJob(clients.bigQueryClient, source, req);
|
|
43
|
+
const rowCount = await streamBigQueryResult(clients.readClient, source, destination, sink, byteLimit);
|
|
44
|
+
sink.send({
|
|
45
|
+
result: { rowCount, limitExceeded: false, executionMs: Date.now() - startedAt },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
throw toBigQueryDataSourceError(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async close() {
|
|
53
|
+
if (!this.config.readClient && this.readClient?.close) {
|
|
54
|
+
await this.readClient.close();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async ensureClients() {
|
|
58
|
+
if (this.bigQueryClient && this.readClient) {
|
|
59
|
+
return { bigQueryClient: this.bigQueryClient, readClient: this.readClient };
|
|
60
|
+
}
|
|
61
|
+
const options = clientOptions(this.config);
|
|
62
|
+
this.bigQueryClient = this.config.bigQueryClient ?? (await createBigQueryClient(options));
|
|
63
|
+
this.readClient = this.config.readClient ?? (await createBigQueryReadClient(options));
|
|
64
|
+
return { bigQueryClient: this.bigQueryClient, readClient: this.readClient };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function runQueryJob(client, source, req) {
|
|
68
|
+
const options = {
|
|
69
|
+
query: queryWithRowLimit(req.query, req.rowLimit),
|
|
70
|
+
useLegacySql: false,
|
|
71
|
+
defaultDataset: {
|
|
72
|
+
projectId: source.projectId,
|
|
73
|
+
datasetId: source.datasetId,
|
|
74
|
+
},
|
|
75
|
+
labels: { component: "datasource" },
|
|
76
|
+
};
|
|
77
|
+
if (source.location) {
|
|
78
|
+
options.location = source.location;
|
|
79
|
+
}
|
|
80
|
+
if (req.timeoutMs && req.timeoutMs > 0) {
|
|
81
|
+
options.jobTimeoutMs = Math.trunc(req.timeoutMs);
|
|
82
|
+
}
|
|
83
|
+
if (source.maximumBytesBilled !== undefined) {
|
|
84
|
+
options.maximumBytesBilled = String(source.maximumBytesBilled);
|
|
85
|
+
}
|
|
86
|
+
const [job] = await client.createQueryJob(options);
|
|
87
|
+
const queryResultsOptions = {
|
|
88
|
+
autoPaginate: false,
|
|
89
|
+
maxResults: 0,
|
|
90
|
+
};
|
|
91
|
+
if (source.location) {
|
|
92
|
+
queryResultsOptions["location"] = source.location;
|
|
93
|
+
}
|
|
94
|
+
await job.getQueryResults(queryResultsOptions);
|
|
95
|
+
const [metadata] = await job.getMetadata();
|
|
96
|
+
const table = metadata.configuration?.query?.destinationTable;
|
|
97
|
+
if (!table?.projectId || !table.datasetId || !table.tableId) {
|
|
98
|
+
throw new Error("BigQuery query job destination table is missing");
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
projectId: table.projectId,
|
|
102
|
+
datasetId: table.datasetId,
|
|
103
|
+
tableId: table.tableId,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function streamBigQueryResult(client, source, table, sink, byteLimit) {
|
|
107
|
+
const [session] = await client.createReadSession({
|
|
108
|
+
parent: `projects/${source.projectId}`,
|
|
109
|
+
readSession: {
|
|
110
|
+
table: `projects/${table.projectId}/datasets/${table.datasetId}/tables/${table.tableId}`,
|
|
111
|
+
dataFormat: "ARROW",
|
|
112
|
+
},
|
|
113
|
+
maxStreamCount: source.maxStreamCount,
|
|
114
|
+
});
|
|
115
|
+
let schemaSent = false;
|
|
116
|
+
const sessionSchema = bytesFromUnknown(session.arrowSchema?.serializedSchema);
|
|
117
|
+
if (sessionSchema) {
|
|
118
|
+
byteLimit.reserve(sessionSchema.byteLength);
|
|
119
|
+
sink.send({ arrow: { dataHeader: sessionSchema } });
|
|
120
|
+
schemaSent = true;
|
|
121
|
+
}
|
|
122
|
+
let rowCount = 0;
|
|
123
|
+
for (const stream of session.streams ?? []) {
|
|
124
|
+
if (!stream.name) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const rows = client.readRows({ readStream: stream.name });
|
|
128
|
+
for await (const response of rows) {
|
|
129
|
+
const responseSchema = bytesFromUnknown(response.arrowSchema?.serializedSchema);
|
|
130
|
+
if (responseSchema && !schemaSent) {
|
|
131
|
+
byteLimit.reserve(responseSchema.byteLength);
|
|
132
|
+
sink.send({ arrow: { dataHeader: responseSchema } });
|
|
133
|
+
schemaSent = true;
|
|
134
|
+
}
|
|
135
|
+
const batch = bytesFromUnknown(response.arrowRecordBatch?.serializedRecordBatch);
|
|
136
|
+
if (batch) {
|
|
137
|
+
byteLimit.reserve(batch.byteLength);
|
|
138
|
+
sink.send({ arrow: { dataBody: batch } });
|
|
139
|
+
}
|
|
140
|
+
rowCount += numberFromLong(response.rowCount);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return rowCount;
|
|
144
|
+
}
|
|
145
|
+
function normalizeSource(source, defaultProjectId) {
|
|
146
|
+
const sourceId = source.sourceId.trim();
|
|
147
|
+
if (!sourceId) {
|
|
148
|
+
throw new Error("source_id is required");
|
|
149
|
+
}
|
|
150
|
+
if (!source.datasetId.trim()) {
|
|
151
|
+
throw new Error(`BigQuery dataset_id is required for source_id ${sourceId}`);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
...source,
|
|
155
|
+
sourceId,
|
|
156
|
+
projectId: normalizedProjectId(source.projectId, defaultProjectId),
|
|
157
|
+
maxStreamCount: source.maxStreamCount && source.maxStreamCount > 0 ? Math.trunc(source.maxStreamCount) : 1,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function normalizedProjectId(projectId, defaultProjectId) {
|
|
161
|
+
const trimmed = projectId?.trim();
|
|
162
|
+
return trimmed && trimmed.length > 0 ? trimmed : defaultProjectId;
|
|
163
|
+
}
|
|
164
|
+
function normalizeRequest(request) {
|
|
165
|
+
return {
|
|
166
|
+
sourceId: request.sourceId?.trim() ?? "",
|
|
167
|
+
query: request.query?.trim() ?? "",
|
|
168
|
+
rowLimit: request.rowLimit,
|
|
169
|
+
byteLimit: request.byteLimit,
|
|
170
|
+
timeoutMs: request.timeoutMs,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function clientOptions(config) {
|
|
174
|
+
const options = {
|
|
175
|
+
...config.clientOptions,
|
|
176
|
+
projectId: config.projectId,
|
|
177
|
+
};
|
|
178
|
+
if (config.keyFilename) {
|
|
179
|
+
options["keyFilename"] = config.keyFilename;
|
|
180
|
+
}
|
|
181
|
+
const credentialsJson = credentialJson(config);
|
|
182
|
+
if (credentialsJson) {
|
|
183
|
+
options["credentials"] = JSON.parse(credentialsJson);
|
|
184
|
+
}
|
|
185
|
+
return options;
|
|
186
|
+
}
|
|
187
|
+
function credentialJson(config) {
|
|
188
|
+
if (config.credentialsJson?.trim()) {
|
|
189
|
+
return config.credentialsJson;
|
|
190
|
+
}
|
|
191
|
+
if (config.credentialsJsonEnv?.trim()) {
|
|
192
|
+
const value = process.env[config.credentialsJsonEnv];
|
|
193
|
+
if (value?.trim()) {
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
for (const envName of config.credentialsEnvVars ?? []) {
|
|
198
|
+
const value = process.env[envName];
|
|
199
|
+
if (value?.trim()) {
|
|
200
|
+
return value;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
async function createBigQueryClient(options) {
|
|
206
|
+
try {
|
|
207
|
+
const mod = (await importOptionalModule("@google-cloud/bigquery"));
|
|
208
|
+
return new mod.BigQuery(options);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
throw new DataSourceExecutionError({
|
|
212
|
+
code: DataSourceErrorCode.Unavailable,
|
|
213
|
+
message: `@google-cloud/bigquery is required for BigQuery datasource execution: ${errorMessage(error)}`,
|
|
214
|
+
cause: error,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async function createBigQueryReadClient(options) {
|
|
219
|
+
try {
|
|
220
|
+
const mod = (await importOptionalModule("@google-cloud/bigquery-storage"));
|
|
221
|
+
return new mod.BigQueryReadClient(options);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
throw new DataSourceExecutionError({
|
|
225
|
+
code: DataSourceErrorCode.Unavailable,
|
|
226
|
+
message: `@google-cloud/bigquery-storage is required for BigQuery Storage streaming: ${errorMessage(error)}`,
|
|
227
|
+
cause: error,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function bytesFromUnknown(value) {
|
|
232
|
+
if (value === null || value === undefined) {
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
if (value instanceof Uint8Array) {
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
if (typeof value === "string") {
|
|
239
|
+
return Buffer.from(value, "base64");
|
|
240
|
+
}
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
function numberFromLong(value) {
|
|
244
|
+
if (typeof value === "number") {
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
if (typeof value === "bigint") {
|
|
248
|
+
return Number(value);
|
|
249
|
+
}
|
|
250
|
+
if (typeof value === "string") {
|
|
251
|
+
const parsed = Number(value);
|
|
252
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
253
|
+
}
|
|
254
|
+
if (value && typeof value === "object" && "toString" in value) {
|
|
255
|
+
const objectValue = value;
|
|
256
|
+
if (objectValue.toString === Object.prototype.toString) {
|
|
257
|
+
return 0;
|
|
258
|
+
}
|
|
259
|
+
const parsed = Number(objectValue.toString());
|
|
260
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
261
|
+
}
|
|
262
|
+
return 0;
|
|
263
|
+
}
|
|
264
|
+
function toBigQueryDataSourceError(error) {
|
|
265
|
+
if (error instanceof DataSourceExecutionError) {
|
|
266
|
+
return error;
|
|
267
|
+
}
|
|
268
|
+
if (error instanceof Error) {
|
|
269
|
+
const upstream = {
|
|
270
|
+
engine: "bigquery",
|
|
271
|
+
message: error.message,
|
|
272
|
+
};
|
|
273
|
+
const code = errorCode(error);
|
|
274
|
+
if (code) {
|
|
275
|
+
upstream.code = code;
|
|
276
|
+
}
|
|
277
|
+
return new DataSourceExecutionError({
|
|
278
|
+
code: DataSourceErrorCode.ExternalError,
|
|
279
|
+
message: "BigQuery datasource query failed",
|
|
280
|
+
upstream,
|
|
281
|
+
cause: error,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
return error;
|
|
285
|
+
}
|
|
286
|
+
function errorCode(error) {
|
|
287
|
+
const code = error.code;
|
|
288
|
+
return typeof code === "string" ? code : undefined;
|
|
289
|
+
}
|
|
290
|
+
function errorMessage(error) {
|
|
291
|
+
return error instanceof Error ? error.message : String(error);
|
|
292
|
+
}
|
|
293
|
+
async function importOptionalModule(specifier) {
|
|
294
|
+
const mod = await import(specifier);
|
|
295
|
+
return mod;
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=bigquery.js.map
|