UNPKG

@vulcan-sql/extension-driver-ksqldb

Version:

ksqlDB driver for VulcanSQL

105 lines 4.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.KSQLDBDataSource = void 0; const tslib_1 = require("tslib"); const core_1 = require("@vulcan-sql/core"); const stream_1 = require("stream"); const sqlBuilder_1 = require("./sqlBuilder"); const typeMapper_1 = require("./typeMapper"); const restfulClient_1 = require("./restfulClient"); let KSQLDBDataSource = class KSQLDBDataSource extends core_1.DataSource { constructor() { super(...arguments); this.logger = this.getLogger(); this.clientMapping = new Map(); } onActivate() { return tslib_1.__awaiter(this, void 0, void 0, function* () { const profiles = this.getProfiles().values(); for (const profile of profiles) { this.logger.debug(`Initializing profile: ${profile.name} using ksqldb driver`); const options = Object.assign({}, profile.connection); const client = new restfulClient_1.RestfulClient(options); this.clientMapping.set(profile.name, { client, options }); // Testing connection const isRunning = yield client.checkConnectionRunning(); if (!isRunning) { throw new Error('KsqlDb server is not running'); } this.logger.debug(`Profile ${profile.name} initialized`); } }); } prepare({ parameterIndex }) { return tslib_1.__awaiter(this, void 0, void 0, function* () { return `$${parameterIndex}`; }); } execute({ statement: sql, bindParams, profileName, operations, }) { return tslib_1.__awaiter(this, void 0, void 0, function* () { this.checkProfileExist(profileName); const { client } = this.clientMapping.get(profileName); const params = Object.fromEntries(bindParams); try { const builtSQL = (0, sqlBuilder_1.buildSQL)(sql, operations); const data = yield client.query({ query: builtSQL, query_params: params, }); return yield this.getResultFromRestfulResponse(data); } catch (e) { this.logger.debug(`Errors occurred, release connection from ${profileName}`); throw e; } }); } getResultFromRestfulResponse(data) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const dataRowStream = new stream_1.Stream.Readable({ objectMode: true, read: () => null, // automatically destroy() the stream when it emits 'finish' or errors. Node > 10.16 autoDestroy: true, }); const headerData = data[0].header; const columns = (0, sqlBuilder_1.convertSchemaToColumns)(headerData.schema); // add the data row to the stream for (const innerData of data) { // format the ksqldb table response to VulcanSQL Data API // https://docs.ksqldb.io/en/latest/developer-guide/ksqldb-rest-api/query-endpoint/#example-table-response if (innerData.row) { const rowColumns = innerData.row.columns; const outputData = rowColumns.reduce((result, value, index) => { return Object.assign(Object.assign({}, result), { [columns[index].name]: value }); }, {}); dataRowStream.push(outputData); } // the end of query result if (innerData.finalMessage) { dataRowStream.push(null); } } return { getColumns: () => { return columns.map((column) => ({ name: column.name || '', // Convert KsqlDb type to FieldDataType supported by VulcanSQL for generating the response schema in the specification, see: https://github.com/Canner/vulcan-sql/pull/78#issuecomment-1621532674 type: (0, typeMapper_1.mapFromKsqlDbType)(column.type || ''), })); }, getData: () => dataRowStream, }; }); } checkProfileExist(profileName) { if (!this.clientMapping.has(profileName)) { throw new core_1.InternalError(`Profile instance ${profileName} not found`); } } }; KSQLDBDataSource = tslib_1.__decorate([ (0, core_1.VulcanExtensionId)('ksqldb') ], KSQLDBDataSource); exports.KSQLDBDataSource = KSQLDBDataSource; //# sourceMappingURL=ksqldbDataSource.js.map