@gftdcojp/gftd-orm
Version:
Enterprise-grade real-time data platform with ksqlDB, inspired by Supabase architecture
259 lines • 8.64 kB
JavaScript
;
/**
* クライアントサイド用HTTPクライアント(ブラウザ環境)
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.KsqlDbClientBrowser = exports.HttpClient = void 0;
exports.createKsqlDbClientBrowser = createKsqlDbClientBrowser;
const env_1 = require("./utils/env");
const ksqldb_client_1 = require("./ksqldb-client");
/**
* ブラウザ環境用HTTPクライアント
*/
class HttpClient {
constructor(config) {
if (!(0, env_1.isBrowser)()) {
throw new Error('HttpClient can only be used in browser environment');
}
this.config = config;
this.defaultHeaders = {
'Content-Type': 'application/json',
...config.headers,
};
// 認証情報がある場合は Authorization ヘッダーを追加
if (config.apiKey && config.apiSecret) {
const credentials = btoa(`${config.apiKey}:${config.apiSecret}`);
this.defaultHeaders['Authorization'] = `Basic ${credentials}`;
}
}
/**
* GET リクエストを送信
*/
async get(path, params) {
const url = new URL(path, this.config.url);
if (params) {
Object.keys(params).forEach(key => {
url.searchParams.append(key, params[key]);
});
}
const response = await this.fetch(url.toString(), {
method: 'GET',
headers: this.defaultHeaders,
});
return this.handleResponse(response);
}
/**
* POST リクエストを送信
*/
async post(path, data) {
const url = new URL(path, this.config.url);
const response = await this.fetch(url.toString(), {
method: 'POST',
headers: this.defaultHeaders,
body: data ? JSON.stringify(data) : undefined,
});
return this.handleResponse(response);
}
/**
* PUT リクエストを送信
*/
async put(path, data) {
const url = new URL(path, this.config.url);
const response = await this.fetch(url.toString(), {
method: 'PUT',
headers: this.defaultHeaders,
body: data ? JSON.stringify(data) : undefined,
});
return this.handleResponse(response);
}
/**
* DELETE リクエストを送信
*/
async delete(path) {
const url = new URL(path, this.config.url);
const response = await this.fetch(url.toString(), {
method: 'DELETE',
headers: this.defaultHeaders,
});
return this.handleResponse(response);
}
/**
* ksqlDB クエリを実行
*/
async executeQuery(sql) {
const response = await this.post('/ksql', {
ksql: sql,
streamsProperties: {},
});
return response;
}
/**
* Pull Query を実行(ブラウザ用)
* @param sql - 実行するSQL文
* @param options - Pull Queryのオプション
*/
async executePullQuery(sql, options = {}) {
const { format = 'object' } = options;
const response = await this.post('/query-stream', {
sql,
properties: {},
});
// ブラウザ環境では、レスポンスの形式が異なる可能性があるため、
// 基本的な変換処理を実装
if (format === 'object' && response && Array.isArray(response.data) && response.columnNames) {
const transformedData = (0, ksqldb_client_1.transformArrayRowsToObjects)(response.data, response.columnNames);
return {
...response,
data: transformedData
};
}
return response;
}
async fetch(url, options) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout || 30000);
try {
const response = await fetch(url, {
...options,
signal: controller.signal,
});
clearTimeout(timeoutId);
return response;
}
catch (error) {
clearTimeout(timeoutId);
if (error instanceof Error && error.name === 'AbortError') {
throw new Error('Request timeout');
}
throw error;
}
}
async handleResponse(response) {
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return response.json();
}
return response.text();
}
}
exports.HttpClient = HttpClient;
/**
* ブラウザ環境用ksqlDBクライアント
*/
class KsqlDbClientBrowser {
constructor(config) {
this.config = config;
this.httpClient = new HttpClient({
url: config.url,
apiKey: config.apiKey,
apiSecret: config.apiSecret,
headers: config.headers,
timeout: 30000,
});
}
/**
* クエリを実行
*/
async executeQuery(sql) {
try {
const response = await this.httpClient.executeQuery(sql);
return response;
}
catch (error) {
throw new Error(`ksqlDB query failed: ${error.message}`);
}
}
/**
* Pull Query を実行
* @param sql - 実行するSQL文
* @param options - Pull Queryのオプション(デフォルトでオブジェクト形式を返す)
*/
async executePullQuery(sql, options = {}) {
console.log(`[DEBUG] KsqlDbClientBrowser.executePullQuery - SQL: ${sql}`);
console.log(`[DEBUG] KsqlDbClientBrowser.executePullQuery - Options:`, options);
console.log(`[DEBUG] KsqlDbClientBrowser.executePullQuery - Config:`, this.config);
try {
const response = await this.httpClient.executePullQuery(sql, options);
console.log(`[DEBUG] KsqlDbClientBrowser.executePullQuery - Response:`, response);
return response;
}
catch (error) {
console.error(`[ERROR] KsqlDbClientBrowser.executePullQuery failed:`, error);
// ストリーム vs テーブルの問題を特定しやすくする
if (error.message && (error.message.includes('stream') || error.message.includes('table'))) {
console.error(`[ERROR] KsqlDbClientBrowser.executePullQuery - Possible stream/table issue. SQL: ${sql}`);
console.error(`[ERROR] KsqlDbClientBrowser.executePullQuery - Remember: Pull queries work only on TABLES, not STREAMS`);
}
throw new Error(`ksqlDB pull query failed: ${error.message || 'Unknown error'}`);
}
}
/**
* DDL文を実行
*/
async executeDDL(ddl) {
try {
const response = await this.httpClient.executeQuery(ddl);
if (response && response[0] && response[0].errorMessage) {
throw new Error(`DDL execution failed: ${response[0].errorMessage.message}`);
}
return response;
}
catch (error) {
throw new Error(`ksqlDB DDL failed: ${error.message}`);
}
}
/**
* ストリーム/テーブル一覧を取得
*/
async listStreams() {
return this.executeQuery('LIST STREAMS;');
}
async listTables() {
return this.executeQuery('LIST TABLES;');
}
/**
* トピック一覧を取得
*/
async listTopics() {
return this.executeQuery('LIST TOPICS;');
}
/**
* スキーマ情報を取得
*/
async describeStream(streamName) {
return this.executeQuery(`DESCRIBE ${streamName};`);
}
async describeTable(tableName) {
return this.executeQuery(`DESCRIBE ${tableName};`);
}
/**
* 接続状態を確認
*/
async isConnected() {
try {
await this.executeQuery('SHOW QUERIES;');
return true;
}
catch {
return false;
}
}
/**
* クライアント設定を取得
*/
getConfig() {
return this.config;
}
}
exports.KsqlDbClientBrowser = KsqlDbClientBrowser;
/**
* ブラウザ環境用ksqlDBクライアントを作成
*/
function createKsqlDbClientBrowser(config) {
return new KsqlDbClientBrowser(config);
}
//# sourceMappingURL=http-client.js.map