From 2bf0b1d3d9e1a07b49462f4224a1db1f1d563ca9 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Tue, 4 Feb 2025 08:08:36 +0700 Subject: [PATCH 1/3] move the transform function to sdk transform --- package-lock.json | 7 + package.json | 5 +- src/connections/index.ts | 12 +- src/connections/mysql.ts | 64 ++++----- src/connections/outerbase.bk.txt | 139 ------------------- src/connections/postgre/postgresql.ts | 27 ++-- src/connections/snowflake/snowflake.ts | 36 ++++- src/connections/sql-base.ts | 13 +- src/connections/sqlite/cloudflare.ts | 178 ++----------------------- src/connections/sqlite/starbase.ts | 10 +- src/connections/sqlite/turso.ts | 26 ++-- src/utils/transformer.ts | 132 +++++++++--------- 12 files changed, 173 insertions(+), 476 deletions(-) delete mode 100644 src/connections/outerbase.bk.txt diff --git a/package-lock.json b/package-lock.json index f66349d..f02067f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "2.0.0-rc.4", "license": "MIT", "dependencies": { + "@outerbase/sdk-transform": "^1.0.2", "handlebars": "^4.7.8" }, "bin": { @@ -2979,6 +2980,12 @@ "node": ">=8.0.0" } }, + "node_modules/@outerbase/sdk-transform": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@outerbase/sdk-transform/-/sdk-transform-1.0.2.tgz", + "integrity": "sha512-Kycs4PLowe7H/8eskLK9umkzTaOwrhd3SOjdN2kPTmTir5sqGSmcCOOYFCjbDHapcNU0GYw5h53cMBxiXA0YYw==", + "license": "MIT" + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", diff --git a/package.json b/package.json index fe07d00..3ad70a5 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "author": "Outerbase", "license": "MIT", "dependencies": { + "@outerbase/sdk-transform": "^1.0.2", "handlebars": "^4.7.8" }, "devDependencies": { @@ -53,11 +54,11 @@ "mysql2": "^3.11.3", "pg": "^8.13.0", "prettier": "^3.2.5", + "snowflake-sdk": "^1.15.0", "ts-jest": "^29.1.3", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "typescript": "^5.4.5", - "ws": "^8.17.1", - "snowflake-sdk": "^1.15.0" + "ws": "^8.17.1" } } diff --git a/src/connections/index.ts b/src/connections/index.ts index 4199a72..9325ad0 100644 --- a/src/connections/index.ts +++ b/src/connections/index.ts @@ -1,23 +1,17 @@ +import { ColumnHeader, ResultSet } from '@outerbase/sdk-transform'; import { Database, TableColumn, TableColumnDefinition, } from '../models/database'; -export interface QueryResultHeader { - name: string; - displayName: string; - type?: string; - tableName?: string; -} -export interface QueryResult> { +export interface QueryResult> + extends Omit { data: T[]; count?: number; - headers: QueryResultHeader[]; error: Error | null; query: string; } - export interface ConnectionSelectOptions { where?: { name: string; value: unknown; operator: string }[]; orderBy?: (string | [string, 'ASC' | 'DESC'])[]; diff --git a/src/connections/mysql.ts b/src/connections/mysql.ts index 0882de5..f7c47c0 100644 --- a/src/connections/mysql.ts +++ b/src/connections/mysql.ts @@ -7,20 +7,15 @@ import { import { SqlConnection } from './sql-base'; import { Query } from '../query'; import { QueryType } from '../query-params'; -import { - Constraint, - Database, - Table, - TableColumn, - TableColumnDefinition, -} from './../models/database'; +import { Constraint, Database, Table, TableColumn } from './../models/database'; import { MySQLDialect } from './../query-builder/dialects/mysql'; import { createErrorResult, - transformArrayBasedResult, + transformFromSdkTransform, } from './../utils/transformer'; import { QueryResult } from '.'; import { ColumnDataType } from '../query-builder'; +import { transformMySQLResult } from '@outerbase/sdk-transform'; interface MySQLSchemaResult { SCHEMA_NAME: string; @@ -127,10 +122,10 @@ export function buildMySQLDatabaseSchmea({ columnLookup[ column.TABLE_SCHEMA + - '.' + - column.TABLE_NAME + - '.' + - column.COLUMN_NAME + '.' + + column.TABLE_NAME + + '.' + + column.COLUMN_NAME ] = columnObject; table.columns.push(columnObject); @@ -156,10 +151,10 @@ export function buildMySQLDatabaseSchmea({ constraintLookup[ constraint.TABLE_SCHEMA + - '.' + - constraint.TABLE_NAME + - '.' + - constraint.CONSTRAINT_NAME + '.' + + constraint.TABLE_NAME + + '.' + + constraint.CONSTRAINT_NAME ] = constraintObject; table.constraints.push(constraintObject); @@ -169,22 +164,22 @@ export function buildMySQLDatabaseSchmea({ for (const constraintColumn of constraintColumnsList) { const constraint = constraintLookup[ - constraintColumn.TABLE_SCHEMA + - '.' + - constraintColumn.TABLE_NAME + - '.' + - constraintColumn.CONSTRAINT_NAME + constraintColumn.TABLE_SCHEMA + + '.' + + constraintColumn.TABLE_NAME + + '.' + + constraintColumn.CONSTRAINT_NAME ]; if (!constraint) continue; const currentColumn = columnLookup[ - constraintColumn.TABLE_SCHEMA + - '.' + - constraintColumn.TABLE_NAME + - '.' + - constraintColumn.COLUMN_NAME + constraintColumn.TABLE_SCHEMA + + '.' + + constraintColumn.TABLE_NAME + + '.' + + constraintColumn.COLUMN_NAME ]; if (currentColumn && constraintColumn.REFERENCED_COLUMN_NAME) { currentColumn.definition.references = { @@ -254,18 +249,11 @@ export class MySQLConnection extends SqlConnection { ); if (error) { - return createErrorResult(error.message) as QueryResult; + return createErrorResult(error.message); } else { - return transformArrayBasedResult( - fields, - (header) => { - return { - name: header.name, - tableName: header.table, - }; - }, - rows as unknown[][] - ) as QueryResult; + return transformFromSdkTransform( + transformMySQLResult([rows, fields]) + ); } } catch { return createErrorResult('Unknown error') as QueryResult; @@ -377,7 +365,7 @@ export class MySQLConnection extends SqlConnection { ); } - async connect(): Promise { } + async connect(): Promise {} async disconnect(): Promise { this.conn.destroy(); } diff --git a/src/connections/outerbase.bk.txt b/src/connections/outerbase.bk.txt deleted file mode 100644 index 80dd695..0000000 --- a/src/connections/outerbase.bk.txt +++ /dev/null @@ -1,139 +0,0 @@ -import { QueryType } from '../query-params' -import { Query, constructRawQuery } from '../query' -import { Connection } from './index' -import { DefaultDialect } from '../query-builder/dialects/default'; - -export const API_URL = 'https://app.outerbase.com' - -export type OuterbaseConnectionDetails = { - apiKey: string -}; - -export class OuterbaseConnection implements Connection { - // The API key used for Outerbase authentication - api_key: string | undefined - - // Default query type to named for Outerbase - queryType = QueryType.named - - // Default dialect for Cloudflare - dialect = new DefaultDialect() - - /** - * Creates a new OuterbaseConnection object with the provided API key. - * - * @param apiKey - The API key to be used for authentication. - */ - constructor(private _: { - apiKey: string - }) { - this.api_key = _.apiKey; - } - - /** - * Performs a connect action on the current Connection object. - * In this particular use case Outerbase is a REST API and - * requires an API key for authentication. - * - * @param details - Unused in the Outerbase scenario. - * @returns Promise - */ - async connect(): Promise { - return Promise.resolve(); - } - - /** - * Performs a disconnect action on the current Connection object. - * In this particular use case Outerbase is a REST API and does - * not require a disconnect action. - * - * @returns Promise - */ - async disconnect(): Promise { - return Promise.resolve() - } - - /** - * Triggers a query action on the current Connection object. The query - * is a SQL query that will be executed on a source inside of the users - * Outerbase account. The query is sent to the Outerbase API and the - * response is returned. - * - * The parameters object is sent along with the query to be used in the - * query. By default if the query has parameters the SQL statement will - * produce a string with `:property` values that the parameters object - * keys should map to, and will be replaced by. - * - * @param query - The SQL query to be executed. - * @param parameters - An object containing the parameters to be used in the query. - * @returns Promise<{ data: any, error: Error | null }> - */ - async query( - query: Query - ): Promise<{ data: any; error: Error | null; query: string }> { - if (!this.api_key) throw new Error('Outerbase API key is not set') - if (!query) throw new Error('Query was not provided') - - const response = await fetch(`${API_URL}/api/v1/ezql/raw`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-Source-Token': this.api_key, - }, - body: JSON.stringify({ - query: query.query, - params: query.parameters, - }), - }) - - let json = await response.json() - let error = null - let items = (await json.response?.results?.items) ?? [] - const rawSQL = constructRawQuery(query) - - return { - data: items, - error: error, - query: rawSQL, - } - } - - /** - * Runs a saved query from the Outerbase account associated with the - * `OuterbaseConnection` token provided. The query ID is used to - * identify the query to be run and the response is returned. - * - * You can find the query ID by navigating to the query in the Outerbase - * app and copying the ID from the URL. If the query is deleted this - * ID will no longer be valid and the query will not be able to be run. - * - * @param queryId - * @returns Promise<{ data: any, error: Error | null }> - */ - async runSavedQuery( - queryId: string - ): Promise<{ data: any; error: Error | null }> { - if (!this.api_key) throw new Error('Outerbase API key is not set') - if (!queryId) throw new Error('Query ID is not set') - - const response = await fetch( - `${API_URL}/api/v1/ezql/query/${queryId}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-Source-Token': this.api_key, - }, - } - ) - - let json = await response.json() - let error = null - let items = (await json.response?.results?.items) ?? [] - - return { - data: items, - error: error, - } - } -} diff --git a/src/connections/postgre/postgresql.ts b/src/connections/postgre/postgresql.ts index 8436c97..61d8407 100644 --- a/src/connections/postgre/postgresql.ts +++ b/src/connections/postgre/postgresql.ts @@ -1,13 +1,14 @@ -import { Client, types } from 'pg'; +import { Client } from 'pg'; import { QueryResult } from '..'; import { Query } from '../../query'; import { AbstractDialect } from './../../query-builder'; import { PostgresDialect } from './../../query-builder/dialects/postgres'; import { createErrorResult, - transformArrayBasedResult, + transformFromSdkTransform, } from './../../utils/transformer'; import { PostgreBaseConnection } from './base'; +import { setPgParser, transformPgResult } from '@outerbase/sdk-transform'; export class PostgreSQLConnection extends PostgreBaseConnection { client: Client; @@ -17,13 +18,7 @@ export class PostgreSQLConnection extends PostgreBaseConnection { constructor(pgClient: any) { super(); this.client = pgClient; - - this.client.setTypeParser(types.builtins.TIMESTAMP, str => str) - this.client.setTypeParser(types.builtins.DATE, str => str) - this.client.setTypeParser(types.builtins.TIMESTAMPTZ, str => str) - this.client.setTypeParser(types.builtins.TIME, str => str) - this.client.setTypeParser(types.builtins.TIMETZ, str => str) - this.client.setTypeParser(types.builtins.JSON, str => str); + setPgParser(this.client); } async connect() { @@ -38,24 +33,18 @@ export class PostgreSQLConnection extends PostgreBaseConnection { query: Query ): Promise> { try { - const { rows, fields } = await this.client.query({ + const result = await this.client.query({ text: query.query, rowMode: 'array', values: query.parameters as unknown[], }); - return transformArrayBasedResult( - fields, - (field) => ({ - name: field.name, - }), - rows - ) as QueryResult; + return transformFromSdkTransform(transformPgResult(result)); } catch (e) { if (e instanceof Error) { - return createErrorResult(e.message) as QueryResult; + return createErrorResult(e.message); } - return createErrorResult('Unknown error') as QueryResult; + return createErrorResult('Unknown error'); } } } diff --git a/src/connections/snowflake/snowflake.ts b/src/connections/snowflake/snowflake.ts index fbfd365..67298da 100644 --- a/src/connections/snowflake/snowflake.ts +++ b/src/connections/snowflake/snowflake.ts @@ -3,7 +3,7 @@ import { Query } from '../../query'; import { QueryResult } from '..'; import { createErrorResult, - transformArrayBasedResult, + transformFromSdkTransform, } from '../../utils/transformer'; import { Database, TableColumn } from '../../models/database'; import { PostgreBaseConnection } from './../postgre/base'; @@ -12,6 +12,8 @@ import { MySQLConstraintColumnResult, } from '../mysql'; +import { transformArrayBasedResult } from '@outerbase/sdk-transform'; + export class SnowflakeConnection extends PostgreBaseConnection { protected db: snowflake.Connection; @@ -199,15 +201,35 @@ export class SnowflakeConnection extends PostgreBaseConnection { }); if (err) return createErrorResult(err.message) as QueryResult; - return transformArrayBasedResult( - headers, - (header) => ({ - name: header, + return transformFromSdkTransform({ + ...transformArrayBasedResult({ + headers, + rows, + headersMapper: (header) => ({ + name: header, + displayName: header, + originalType: null, + }), }), - rows - ) as QueryResult; + stat: { + queryDurationMs: 0, + rowsAffected: 0, + rowsRead: 0, + rowsWritten: 0, + }, + }) as QueryResult; } catch (e) { return createErrorResult('Unknown error') as QueryResult; } } } + +/* + headers, + (header) => ({ + name: header, + displayName: header, + originalType: null, + }), + rows +*/ diff --git a/src/connections/sql-base.ts b/src/connections/sql-base.ts index 551c59b..bafbc5c 100644 --- a/src/connections/sql-base.ts +++ b/src/connections/sql-base.ts @@ -161,7 +161,18 @@ export abstract class SqlConnection extends Connection { ); } - return { data: [], error: null, query: '', headers: [] }; + return { + data: [], + error: null, + query: '', + headers: [], + stat: { + queryDurationMs: 0, + rowsAffected: 0, + rowsRead: 0, + rowsWritten: 0, + }, + }; } async update( diff --git a/src/connections/sqlite/cloudflare.ts b/src/connections/sqlite/cloudflare.ts index adf529a..4ec7a46 100644 --- a/src/connections/sqlite/cloudflare.ts +++ b/src/connections/sqlite/cloudflare.ts @@ -2,17 +2,13 @@ import { QueryType } from '../../query-params'; import { Query } from '../../query'; import { DefaultDialect } from '../../query-builder/dialects/default'; import { SqliteBaseConnection } from './base'; +import { Database } from './../../models/database'; import { - Constraint, - ConstraintColumn, - Database, - Table, - TableColumn, - TableIndex, - TableIndexType, -} from './../../models/database'; -import { transformArrayBasedResult } from './../../utils/transformer'; + createErrorResult, + transformFromSdkTransform, +} from './../../utils/transformer'; import { QueryResult } from '..'; +import { transformCloudflareD1 } from '@outerbase/sdk-transform'; interface CloudflareResult { results: { @@ -135,22 +131,16 @@ export class CloudflareD1Connection extends SqliteBaseConnection { const json: CloudflareResponse = await response.json(); if (json.success) { - const items = json.result[0].results; - return transformArrayBasedResult( - items.columns, - (column) => ({ name: column }), - items.rows - ) as QueryResult; + return transformFromSdkTransform( + transformCloudflareD1(json.result[0]) + ); } - return { - data: [], - error: new Error( - json.error ?? json.errors?.map((e) => e.message).join(', ') - ), - query: '', - headers: [], - }; + return createErrorResult( + json.error ?? + json.errors?.map((e) => e.message).join(', ') ?? + 'Unknown error' + ); } public async fetchDatabaseSchema(): Promise { @@ -158,146 +148,4 @@ export class CloudflareD1Connection extends SqliteBaseConnection { delete result.main['_cf_KV']; return result; } - - // For some reason, Cloudflare D1 does not support - // cross join with pragma_table_info, so we have to - // to expensive loops to get the same data - // public async fetchDatabaseSchema(): Promise { - // const exclude_tables = [ - // '_cf_kv', - // 'sqlite_schema', - // 'sqlite_temp_schema', - // ]; - - // const schemaMap: Record> = {}; - - // const { data } = await this.query({ - // query: `PRAGMA table_list`, - // }); - - // const allTables = ( - // data as { - // schema: string; - // name: string; - // type: string; - // }[] - // ).filter( - // (row) => - // !row.name.startsWith('_lite') && - // !row.name.startsWith('sqlite_') && - // !exclude_tables.includes(row.name?.toLowerCase()) - // ); - - // for (const table of allTables) { - // if (exclude_tables.includes(table.name?.toLowerCase())) continue; - - // const { data: pragmaData } = await this.query({ - // query: `PRAGMA table_info('${table.name}')`, - // }); - - // const tableData = pragmaData as { - // cid: number; - // name: string; - // type: string; - // notnull: 0 | 1; - // dflt_value: string | null; - // pk: 0 | 1; - // }[]; - - // const { data: fkConstraintResponse } = await this.query({ - // query: `PRAGMA foreign_key_list('${table.name}')`, - // }); - - // const fkConstraintData = ( - // fkConstraintResponse as { - // id: number; - // seq: number; - // table: string; - // from: string; - // to: string; - // on_update: 'NO ACTION' | unknown; - // on_delete: 'NO ACTION' | unknown; - // match: 'NONE' | unknown; - // }[] - // ).filter( - // (row) => - // !row.table.startsWith('_lite') && - // !row.table.startsWith('sqlite_') - // ); - - // const constraints: Constraint[] = []; - - // if (fkConstraintData.length > 0) { - // const fkConstraints: Constraint = { - // name: 'FOREIGN KEY', - // schema: table.schema, - // tableName: table.name, - // type: 'FOREIGN KEY', - // referenceSchema: table.schema, - // referenceTableName: fkConstraintData[0].table, - // columns: [], - // }; - - // fkConstraintData.forEach((fkConstraint) => { - // const currentConstraint: ConstraintColumn = { - // columnName: fkConstraint.from, - // referenceColumnName: fkConstraint.to, - // }; - // fkConstraints.columns.push(currentConstraint); - // }); - // constraints.push(fkConstraints); - // } - - // const indexes: TableIndex[] = []; - // const columns = tableData.map((column) => { - // // Primary keys are ALWAYS considered indexes - // if (column.pk === 1) { - // indexes.push({ - // name: column.name, - // type: TableIndexType.PRIMARY, - // columns: [column.name], - // }); - // } - - // const columnConstraint = fkConstraintData.find( - // (fk) => fk.from === column.name - // ); - - // const currentColumn: TableColumn = { - // name: column.name, - // position: column.cid, - // definition: { - // type: column.type, - // nullable: column.notnull === 0, - // default: column.dflt_value, - // primaryKey: column.pk === 1, - // unique: column.pk === 1, - // references: columnConstraint - // ? { - // column: [columnConstraint.to], - // table: columnConstraint.table, - // } - // : undefined, - // }, - // }; - - // return currentColumn; - // }); - - // const currentTable: Table = { - // name: table.name, - // columns: columns, - // indexes: indexes, - // constraints: constraints, - // }; - - // if (!schemaMap[table.schema]) { - // schemaMap[table.schema] = {}; - // } - - // schemaMap[table.schema][table.name] = currentTable; - // } - - // return schemaMap; - // } } diff --git a/src/connections/sqlite/starbase.ts b/src/connections/sqlite/starbase.ts index 98bba73..cad6199 100644 --- a/src/connections/sqlite/starbase.ts +++ b/src/connections/sqlite/starbase.ts @@ -5,9 +5,11 @@ import { SqliteBaseConnection } from './base'; import { QueryResult } from '..'; import { createErrorResult, - transformArrayBasedResult, + transformFromSdkTransform, } from '../../utils/transformer'; +import { transformStarbaseResult } from '@outerbase/sdk-transform'; + export type StarbaseConnectionDetails = { url: string; apiKey: string; @@ -120,11 +122,7 @@ export class StarbaseConnection extends SqliteBaseConnection { ? json.result[0] : json.result; - return transformArrayBasedResult( - items.columns, - (header) => ({ name: header }), - items.rows - ) as QueryResult; + return transformFromSdkTransform(transformStarbaseResult(items)); } return createErrorResult('ss') as QueryResult; diff --git a/src/connections/sqlite/turso.ts b/src/connections/sqlite/turso.ts index 4e03cd2..873ba33 100644 --- a/src/connections/sqlite/turso.ts +++ b/src/connections/sqlite/turso.ts @@ -5,7 +5,11 @@ import { QueryResult } from '..'; import { Query } from '../../query'; import { PostgresDialect } from './../../query-builder/dialects/postgres'; import { SqliteBaseConnection } from './base'; -import { transformArrayBasedResult } from './../../utils/transformer'; +import { + createErrorResult, + transformFromSdkTransform, +} from './../../utils/transformer'; +import { transformTursoResult } from '@outerbase/sdk-transform'; export class TursoConnection extends SqliteBaseConnection { client: Client; @@ -25,26 +29,12 @@ export class TursoConnection extends SqliteBaseConnection { args: (query.parameters ?? []) as InValue[], }); - return transformArrayBasedResult( - result.columns, - (header) => ({ name: header }), - result.rows as unknown as unknown[][] - ) as QueryResult; + return transformFromSdkTransform(transformTursoResult(result)); } catch (e) { if (e instanceof Error) { - return { - data: [], - error: { message: e.message, name: e.name }, - query: query.query, - headers: [], - }; + return createErrorResult(e.message) as QueryResult; } else { - return { - data: [], - error: { message: 'Unknown error', name: 'Unknown' }, - query: query.query, - headers: [], - }; + return createErrorResult('Unknown error') as QueryResult; } } } diff --git a/src/utils/transformer.ts b/src/utils/transformer.ts index 794d432..2580571 100644 --- a/src/utils/transformer.ts +++ b/src/utils/transformer.ts @@ -3,13 +3,44 @@ * database result format into our own query result formation */ -import { QueryResult, QueryResultHeader } from './../connections'; +import { ColumnHeader, ResultSet } from '@outerbase/sdk-transform'; +import { QueryResult } from './../connections'; + +export function transformFromSdkTransform( + result: ResultSet +): QueryResult { + const { rows, ...rest } = result; + + return { + data: rows as T[], + error: null, + query: '', + ...rest, + }; +} + +export function createErrorResult( + message: string +): QueryResult { + return { + data: [], + error: { message, name: 'Error' }, + query: '', + headers: [], + stat: { + queryDurationMs: 0, + rowsAffected: 0, + rowsRead: 0, + rowsWritten: 0, + }, + }; +} export function transformObjectBasedResult( arr: Record[] ): QueryResult { const usedColumnName = new Set(); - const columns: QueryResultHeader[] = []; + const columns: ColumnHeader[] = []; // Build the headers based on rows arr.forEach((row) => { @@ -19,6 +50,7 @@ export function transformObjectBasedResult( columns.push({ name: key, displayName: key, + originalType: null, }); } }); @@ -29,6 +61,12 @@ export function transformObjectBasedResult( headers: columns, error: null, query: '', + stat: { + queryDurationMs: 0, + rowsAffected: 0, + rowsRead: 0, + rowsWritten: 0, + }, }; } @@ -41,89 +79,33 @@ export function transformObjectBasedResultFirstRow( headers: [], error: null, query: '', + stat: { + queryDurationMs: 0, + rowsAffected: 0, + rowsRead: 0, + rowsWritten: 0, + }, }; } const row = arr[0]; - const columns: QueryResultHeader[] = []; + const columns: ColumnHeader[] = []; return { data: arr, headers: Object.keys(row).map((key) => ({ name: key, displayName: key, + originalType: null, })), error: null, query: '', - }; -} - -/** - * Transforms the array based result into our own query result format - */ -export function transformArrayBasedResult( - headers: HeaderType[], - headersMapper: (header: HeaderType) => { - name: string; - tableName?: string; - }, - arr: unknown[][] -): QueryResult { - // Building the headers - const usedColumnName = new Set(); - - const headerMap: QueryResultHeader[] = headers.map((header) => { - const { name, tableName } = headersMapper(header); - let finalColumnName = name; - - // We got the duplicated column name, let try to find it a new name - if (usedColumnName.has(finalColumnName)) { - // If there is table name, let use it as prefix - finalColumnName = tableName ? `${tableName}.${name}` : name; - - for (let i = 1; i < 100; i++) { - if (usedColumnName.has(finalColumnName)) { - finalColumnName = `${name}${i}`; - } else { - break; - } - } - } - - // Hope we don't run into this situation. - if (usedColumnName.has(finalColumnName)) { - throw new Error('Cannot find unique column name'); - } - - usedColumnName.add(finalColumnName); - return { name: finalColumnName, tableName, displayName: name }; - }); - - // Mapping the data - const data = arr.map((row) => { - return headerMap.reduce( - (acc, header, index) => { - acc[header.name] = row[index]; - return acc; - }, - {} as Record - ); - }); - - return { - data, - headers: headerMap, - error: null, - query: '', - }; -} - -export function createErrorResult(message: string): QueryResult { - return { - data: [], - error: { message, name: 'Error' }, - query: '', - headers: [], + stat: { + queryDurationMs: 0, + rowsAffected: 0, + rowsRead: 0, + rowsWritten: 0, + }, }; } @@ -133,5 +115,11 @@ export function createOkResult() { error: null, query: '', headers: [], + stat: { + queryDurationMs: 0, + rowsAffected: 0, + rowsRead: 0, + rowsWritten: 0, + }, }; } From c7b9f9c5ee54709590da126856d7e7e675df6363 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Tue, 4 Feb 2025 08:29:10 +0700 Subject: [PATCH 2/3] bump sdk transform version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f02067f..bff50fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.0.0-rc.4", "license": "MIT", "dependencies": { - "@outerbase/sdk-transform": "^1.0.2", + "@outerbase/sdk-transform": "^1.0.3", "handlebars": "^4.7.8" }, "bin": { @@ -2981,9 +2981,9 @@ } }, "node_modules/@outerbase/sdk-transform": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@outerbase/sdk-transform/-/sdk-transform-1.0.2.tgz", - "integrity": "sha512-Kycs4PLowe7H/8eskLK9umkzTaOwrhd3SOjdN2kPTmTir5sqGSmcCOOYFCjbDHapcNU0GYw5h53cMBxiXA0YYw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@outerbase/sdk-transform/-/sdk-transform-1.0.3.tgz", + "integrity": "sha512-YsiB9YdiDeJmhuVvXFHjIsOoZBCAEHPf+KRCWGGIPm9XOdFXARdA3CJnDDxBUJUUS6oeH0K41juq/pB8bUwSaA==", "license": "MIT" }, "node_modules/@pkgjs/parseargs": { diff --git a/package.json b/package.json index 3ad70a5..a1a068c 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "author": "Outerbase", "license": "MIT", "dependencies": { - "@outerbase/sdk-transform": "^1.0.2", + "@outerbase/sdk-transform": "^1.0.3", "handlebars": "^4.7.8" }, "devDependencies": { From b810ce1efe2a5016c7a1e6be441fe5391486cbf3 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Tue, 4 Feb 2025 08:42:43 +0700 Subject: [PATCH 3/3] bump version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index bff50fd..6216672 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@outerbase/sdk", - "version": "2.0.0-rc.4", + "version": "2.0.0-rc.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@outerbase/sdk", - "version": "2.0.0-rc.4", + "version": "2.0.0-rc.5", "license": "MIT", "dependencies": { "@outerbase/sdk-transform": "^1.0.3", diff --git a/package.json b/package.json index a1a068c..cc1d582 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@outerbase/sdk", - "version": "2.0.0-rc.4", + "version": "2.0.0-rc.5", "description": "", "main": "dist/index.js", "module": "dist/index.js",