UNPKG

@gftdcojp/gftd-orm

Version:

Enterprise-grade real-time data platform with ksqlDB, inspired by Supabase architecture

194 lines 6.32 kB
/** * Supabase風クライアント - 匿名キーベースの統合クライアント */ import { rls, executePullQuery, executePushQuery, AuditLogManager, AuditEventType, AuditLogLevel } from './types'; import { RealtimeClient } from './realtime-client'; import { log } from './utils/logger'; /** * キーの種類 */ export var KeyType; (function (KeyType) { KeyType["ANON"] = "anon"; KeyType["SERVICE_ROLE"] = "service_role"; })(KeyType || (KeyType = {})); /** * 最小限のキー認証システム(内部実装) * @deprecated anon-key-systemから移行 */ class SimpleKeyAuth { constructor() { this.validKeys = new Set(); // デフォルトキーを設定(開発用) this.validKeys.add('gftd_anon_mock_key'); this.validKeys.add('gftd_service_mock_key'); } static getInstance() { if (!SimpleKeyAuth.instance) { SimpleKeyAuth.instance = new SimpleKeyAuth(); } return SimpleKeyAuth.instance; } authenticateWithKey(key, userId) { if (!this.validKeys.has(key)) { return { success: false, error: 'Invalid key' }; } const isServiceKey = key.includes('service'); const user = { sub: userId || `mock-${Date.now()}`, role: isServiceKey ? 'service_role' : 'anon', tenant_id: 'default', metadata: { keyType: isServiceKey ? KeyType.SERVICE_ROLE : KeyType.ANON, }, app_metadata: { provider: 'key', keyId: key, }, user_metadata: {}, }; return { success: true, user, token: 'mock-token' }; } } /** * 最小限のキーシステムヘルパー */ const simpleKeySystem = { manager: () => SimpleKeyAuth.getInstance(), }; /** * Supabase風クライアント */ export class GftdClient { constructor(config) { this.config = config; this.authState = { user: null, session: null, isAuthenticated: false, isAnonymous: false, }; this.initializeClient(); } /** * クライアントを初期化 */ async initializeClient() { // キーベース認証を実行 const authResult = simpleKeySystem.manager().authenticateWithKey(this.config.key); if (authResult.success && authResult.user) { this.authState = { user: authResult.user, session: { accessToken: authResult.token || '', user: authResult.user, expiresAt: Math.floor(Date.now() / 1000) + 3600, // 1時間 expiresIn: 3600, // 1時間(秒) tokenType: 'Bearer', }, isAuthenticated: true, isAnonymous: authResult.user.role === 'anon', }; log.info(`GFTD Client initialized with ${authResult.user.role} key`); // リアルタイムクライアントを初期化 if (this.config.options?.realtime) { this.realtimeClient = new RealtimeClient({ url: this.config.options.realtime.url || this.config.url.replace('http', 'ws'), autoReconnect: this.config.options.realtime.autoReconnect, }); } } else { throw new Error(`Authentication failed: ${authResult.error}`); } } /** * 認証状態を取得 */ get auth() { return this.authState; } /** * 直接SQLクエリを実行 */ async query(sql, options) { try { if (!this.authState.user) { throw new Error('Not authenticated'); } // RLSを適用 const modifiedSQL = rls.applyToQuery(sql, this.authState.user); // クエリを実行 const result = await executePullQuery(modifiedSQL, options); AuditLogManager.log({ level: AuditLogLevel.INFO, eventType: AuditEventType.DATA_READ, userId: this.authState.user.sub, tenantId: this.authState.user.tenant_id, result: 'SUCCESS', message: `Query executed successfully`, details: { sql: modifiedSQL }, }); return { data: result.data, error: null, }; } catch (error) { log.error(`Query execution failed: ${error}`); if (this.authState.user) { AuditLogManager.log({ level: AuditLogLevel.ERROR, eventType: AuditEventType.DATA_READ, userId: this.authState.user.sub, tenantId: this.authState.user.tenant_id, result: 'FAILURE', message: `Query execution failed: ${error}`, details: { sql, error: String(error) }, }); } return { data: [], error: error, }; } } /** * プッシュクエリを実行(ストリーミング) */ async stream(sql, onData, onError) { if (!this.authState.user) { throw new Error('Not authenticated'); } // RLSを適用 const modifiedSQL = rls.applyToQuery(sql, this.authState.user); return executePushQuery(modifiedSQL, onData, onError); } /** * 接続をクリーンアップ */ dispose() { if (this.tokenRefreshInterval) { clearInterval(this.tokenRefreshInterval); } if (this.realtimeClient) { this.realtimeClient.disconnect(); } } /** * 公開キーを取得(互換性のため) */ getKeys() { return { anonKey: 'gftd_anon_mock_key', serviceRoleKey: null, // サービスロールキーは公開しない }; } } /** * Supabase風クライアント作成関数 */ export function createClient(url, key, options) { return new GftdClient({ url, key, options }); } //# sourceMappingURL=supabase-like-client.js.map