@scriptdb/browser-client 1.1.1 → 1.1.2

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/README.md CHANGED
@@ -228,7 +228,7 @@ scriptdb shell
228
228
 
229
229
  ## Changelog
230
230
 
231
- ### 1.1.1 (2025-01-16)
231
+ ### 1.1.2 (2025-01-16)
232
232
 
233
233
  **Added**
234
234
  - Native `scriptdb logs` command to view real-time logs
package/dist/index.d.mts CHANGED
@@ -4,6 +4,7 @@
4
4
  * This is a lightweight WebSocket client that connects to the ScriptDB WebSocket proxy.
5
5
  * The proxy handles all communication with the ScriptDB server using @scriptdb/client.
6
6
  */
7
+ type Action = 'script-code' | 'save-db' | 'remove-db' | 'rename-db' | 'login' | 'logout' | 'get-info' | 'list-dbs' | 'create-db' | 'update-db' | 'get-db' | 'shell-command';
7
8
  interface Logger {
8
9
  debug?: (...args: any[]) => void;
9
10
  info?: (...args: any[]) => void;
@@ -19,6 +20,12 @@ interface ClientOptions {
19
20
  requestTimeout?: number;
20
21
  secure?: boolean;
21
22
  }
23
+ interface Message {
24
+ id?: number;
25
+ action?: Action;
26
+ message?: string;
27
+ data?: any;
28
+ }
22
29
  declare class BrowserClient {
23
30
  private logger;
24
31
  private host;
@@ -49,9 +56,9 @@ declare class BrowserClient {
49
56
  */
50
57
  private _handleMessage;
51
58
  /**
52
- * Send request to proxy
59
+ * Send request to proxy (internal helper)
53
60
  */
54
- private sendRequest;
61
+ private _sendRequest;
55
62
  /**
56
63
  * Cleanup on disconnect
57
64
  */
@@ -64,6 +71,15 @@ declare class BrowserClient {
64
71
  * Disconnect (alias for close)
65
72
  */
66
73
  disconnect(): Promise<void>;
74
+ /**
75
+ * Send request helper (for public API methods)
76
+ */
77
+ sendRequest(action: Action, data?: any): Promise<any>;
78
+ /**
79
+ * Execute a command. Supports concurrent requests via request id mapping.
80
+ * Returns a Promise resolved with response.data or rejected on ERROR/timeout.
81
+ */
82
+ execute(message: Message): Promise<any>;
67
83
  /**
68
84
  * Login with username and password
69
85
  */
@@ -91,7 +107,7 @@ declare class BrowserClient {
91
107
  /**
92
108
  * Execute code in a database
93
109
  */
94
- run(code: string, databaseName: string): Promise<any>;
110
+ run(code: string | Function, databaseName: string): Promise<any>;
95
111
  /**
96
112
  * Save a database to disk
97
113
  */
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * This is a lightweight WebSocket client that connects to the ScriptDB WebSocket proxy.
5
5
  * The proxy handles all communication with the ScriptDB server using @scriptdb/client.
6
6
  */
7
+ type Action = 'script-code' | 'save-db' | 'remove-db' | 'rename-db' | 'login' | 'logout' | 'get-info' | 'list-dbs' | 'create-db' | 'update-db' | 'get-db' | 'shell-command';
7
8
  interface Logger {
8
9
  debug?: (...args: any[]) => void;
9
10
  info?: (...args: any[]) => void;
@@ -19,6 +20,12 @@ interface ClientOptions {
19
20
  requestTimeout?: number;
20
21
  secure?: boolean;
21
22
  }
23
+ interface Message {
24
+ id?: number;
25
+ action?: Action;
26
+ message?: string;
27
+ data?: any;
28
+ }
22
29
  declare class BrowserClient {
23
30
  private logger;
24
31
  private host;
@@ -49,9 +56,9 @@ declare class BrowserClient {
49
56
  */
50
57
  private _handleMessage;
51
58
  /**
52
- * Send request to proxy
59
+ * Send request to proxy (internal helper)
53
60
  */
54
- private sendRequest;
61
+ private _sendRequest;
55
62
  /**
56
63
  * Cleanup on disconnect
57
64
  */
@@ -64,6 +71,15 @@ declare class BrowserClient {
64
71
  * Disconnect (alias for close)
65
72
  */
66
73
  disconnect(): Promise<void>;
74
+ /**
75
+ * Send request helper (for public API methods)
76
+ */
77
+ sendRequest(action: Action, data?: any): Promise<any>;
78
+ /**
79
+ * Execute a command. Supports concurrent requests via request id mapping.
80
+ * Returns a Promise resolved with response.data or rejected on ERROR/timeout.
81
+ */
82
+ execute(message: Message): Promise<any>;
67
83
  /**
68
84
  * Login with username and password
69
85
  */
@@ -91,7 +107,7 @@ declare class BrowserClient {
91
107
  /**
92
108
  * Execute code in a database
93
109
  */
94
- run(code: string, databaseName: string): Promise<any>;
110
+ run(code: string | Function, databaseName: string): Promise<any>;
95
111
  /**
96
112
  * Save a database to disk
97
113
  */
package/dist/index.js CHANGED
@@ -155,9 +155,9 @@ var BrowserClient = class {
155
155
  console.log("Message has no id, ignoring");
156
156
  }
157
157
  /**
158
- * Send request to proxy
158
+ * Send request to proxy (internal helper)
159
159
  */
160
- async sendRequest(action, data = {}) {
160
+ async _sendRequest(action, data = {}) {
161
161
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
162
162
  throw new Error("Not connected");
163
163
  }
@@ -215,6 +215,22 @@ var BrowserClient = class {
215
215
  async disconnect() {
216
216
  this.close();
217
217
  }
218
+ /**
219
+ * Send request helper (for public API methods)
220
+ */
221
+ async sendRequest(action, data = {}) {
222
+ return this.execute({ action, data });
223
+ }
224
+ /**
225
+ * Execute a command. Supports concurrent requests via request id mapping.
226
+ * Returns a Promise resolved with response.data or rejected on ERROR/timeout.
227
+ */
228
+ async execute(message) {
229
+ if (!message.action) {
230
+ throw new Error("Action is required");
231
+ }
232
+ return this._sendRequest(message.action, message.data);
233
+ }
218
234
  // ========== Public API Methods ==========
219
235
  /**
220
236
  * Login with username and password
@@ -256,7 +272,33 @@ var BrowserClient = class {
256
272
  * Execute code in a database
257
273
  */
258
274
  async run(code, databaseName) {
259
- return this.sendRequest("script-code", { code, databaseName });
275
+ let stringCode;
276
+ if (typeof code === "function") {
277
+ const funcStr = code.toString();
278
+ const arrowMatch = funcStr.match(/^[\s]*\(?\s*\)?\s*=>\s*{?/);
279
+ const functionMatch = funcStr.match(/^[\s]*function\s*\(?[\w\s]*\)?\s*{/);
280
+ const match = arrowMatch || functionMatch;
281
+ const start = match ? match[0].length : 0;
282
+ const end = funcStr.lastIndexOf("}");
283
+ stringCode = funcStr.substring(start, end);
284
+ stringCode = stringCode.replace(/^[\s\r\n]+/, "").replace(/[\s\r\n]+$/, "");
285
+ stringCode = stringCode.replace(
286
+ /import\s*\(\s*([^)]+?)\s*\)\s*\.from\s*\(\s*(['"])([^'"]+)\2\s*\)/g,
287
+ (_, importArg, quote, modulePath) => {
288
+ const trimmed = importArg.trim();
289
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
290
+ const inner = trimmed.slice(1, -1).trim();
291
+ return `import { ${inner} } from ${quote}${modulePath}${quote}`;
292
+ } else {
293
+ return `import ${trimmed} from ${quote}${modulePath}${quote}`;
294
+ }
295
+ }
296
+ );
297
+ stringCode = stringCode.split("\n").map((line) => line.trim()).join("\n").trim();
298
+ } else {
299
+ stringCode = code;
300
+ }
301
+ return this.sendRequest("script-code", { code: stringCode, databaseName });
260
302
  }
261
303
  /**
262
304
  * Save a database to disk
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Browser-compatible ScriptDB Client\n * \n * This is a lightweight WebSocket client that connects to the ScriptDB WebSocket proxy.\n * The proxy handles all communication with the ScriptDB server using @scriptdb/client.\n */\n\ntype Action = 'script-code' | 'save-db' | 'remove-db' | 'rename-db' | 'login' | 'logout' | 'get-info' | 'list-dbs' | 'create-db' | 'update-db' | 'get-db' | 'shell-command';\n\ninterface Logger {\n debug?: (...args: any[]) => void;\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n}\n\ninterface ClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n logger?: Logger;\n requestTimeout?: number;\n secure?: boolean;\n}\n\ninterface PendingRequest {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timer: number | null;\n}\n\ninterface Message {\n id?: number;\n action?: Action;\n message?: string;\n data?: any;\n}\n\nconst noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nexport class BrowserClient {\n private logger: Logger;\n private host: string;\n private port: number;\n private username: string | null;\n private password: string | null;\n private requestTimeout: number;\n private secure: boolean;\n\n private ws: WebSocket | null = null;\n private _connected: boolean = false;\n private _nextId: number = 1;\n private _pending: Map<number, PendingRequest> = new Map();\n\n constructor(options: ClientOptions) {\n this.logger = options.logger || noopLogger;\n this.host = options.host || 'localhost';\n this.port = options.port || 1234;\n this.username = options.username || null;\n this.password = options.password || null;\n this.requestTimeout = Number.isFinite(options.requestTimeout) ? options.requestTimeout! : 120000; // 2 minutes default\n this.secure = options.secure !== undefined ? options.secure : false;\n }\n\n /**\n * Check if connected\n */\n get connected(): boolean {\n return this._connected;\n }\n\n /**\n * Connect to WebSocket proxy and authenticate\n */\n async connect(): Promise<BrowserClient> {\n return new Promise((resolve, reject) => {\n const wsPort = this.port + 1;\n const wsUrl = `ws://${this.host}:${wsPort}`;\n this.logger.info?.('Connecting to', wsUrl);\n\n try {\n this.ws = new WebSocket(wsUrl);\n } catch (e) {\n const error = e as Error;\n this.logger.error?.(\"Connection failed\", error.message);\n return reject(error);\n }\n\n this.ws.onopen = async () => {\n console.log('WebSocket onopen - browserClient.ts');\n this.logger.info?.('WebSocket connected');\n this._connected = true;\n this._setupListeners();\n\n // Always send login request (even with empty credentials for anonymous access)\n try {\n console.log('Sending login request with credentials:', { username: this.username || '', hasPassword: !!this.password, secure: this.secure });\n await this.sendRequest('login', { \n username: this.username || '', \n password: this.password || '',\n secure: this.secure\n });\n console.log('Authenticated successfully');\n this.logger.info?.('Authenticated successfully');\n resolve(this);\n } catch (err) {\n console.error('Login failed:', err);\n reject(err);\n }\n };\n\n this.ws.onerror = (error) => {\n console.error('WebSocket onerror:', error);\n this.logger.error?.('WebSocket error:', error);\n reject(new Error('WebSocket connection failed'));\n };\n\n this.ws.onclose = () => {\n console.log('WebSocket onclose');\n this.logger.info?.('WebSocket disconnected');\n this._connected = false;\n this._cleanup();\n };\n });\n }\n\n /**\n * Setup message listeners\n */\n private _setupListeners() {\n if (!this.ws) return;\n\n this.ws.onmessage = (event) => {\n console.log('WebSocket onmessage fired - browserClient.ts', event.data);\n try {\n const msg = JSON.parse(event.data) as Message;\n console.log('Parsed message:', msg);\n this._handleMessage(msg);\n } catch (error) {\n console.error('Failed to parse message:', error, event.data);\n this.logger.error?.('Failed to parse message:', error);\n }\n };\n }\n\n /**\n * Handle incoming message\n */\n private _handleMessage(msg: Message) {\n console.log('_handleMessage called with:', msg);\n if (!msg || typeof msg !== \"object\") {\n console.log('Invalid message - not an object');\n return;\n }\n\n this.logger.debug?.('Received message:', msg);\n\n // Handle response with id\n if (typeof msg.id !== \"undefined\") {\n console.log('Message has id:', msg.id);\n const pending = this._pending.get(msg.id);\n console.log('Pending request found:', !!pending, 'total pending:', this._pending.size);\n if (!pending) {\n this.logger.debug?.(\"No pending request for id\", msg.id);\n console.log(\"No pending request for id\", msg.id);\n return;\n }\n\n const { resolve, reject, timer } = pending;\n if (timer) clearTimeout(timer);\n this._pending.delete(msg.id);\n\n console.log('Resolving request with message:', msg.message, 'data:', msg.data);\n\n // Check for errors\n if (msg.message === \"ERROR\" || msg.message === \"AUTH FAILED\" || msg.message === \"AUTH FAIL\") {\n return reject(new Error(typeof msg.data === 'string' ? msg.data : \"Request failed\"));\n }\n\n // Success - AUTH OK, OK, or SUCCESS\n if (msg.message === \"AUTH OK\" || msg.message === \"OK\" || msg.message === \"SUCCESS\") {\n console.log('Calling resolve with data:', msg.data);\n return resolve(msg.data);\n }\n\n // Default to resolve with data\n console.log('Default resolve with data:', msg.data);\n return resolve(msg.data);\n }\n console.log('Message has no id, ignoring');\n }\n\n /**\n * Send request to proxy\n */\n private async sendRequest(action: Action, data: any = {}): Promise<any> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error('Not connected');\n }\n\n const id = this._nextId++;\n const request = { id, action, data };\n\n return new Promise((resolve, reject) => {\n let timer: number | null = null;\n if (this.requestTimeout > 0) {\n timer = window.setTimeout(() => {\n if (this._pending.has(id)) {\n this._pending.delete(id);\n reject(new Error(\"Request timeout\"));\n }\n }, this.requestTimeout);\n }\n\n this._pending.set(id, { resolve, reject, timer });\n\n try {\n this.ws?.send(JSON.stringify(request));\n } catch (e) {\n if (timer) clearTimeout(timer);\n this._pending.delete(id);\n reject(e);\n }\n });\n }\n\n /**\n * Cleanup on disconnect\n */\n private _cleanup() {\n this._pending.forEach((pending) => {\n if (pending.timer) clearTimeout(pending.timer);\n try {\n pending.reject(new Error(\"Disconnected\"));\n } catch (e) {}\n });\n this._pending.clear();\n }\n\n /**\n * Close connection\n */\n close() {\n if (this.ws) {\n try {\n this.ws.close();\n } catch (e) {}\n this.ws = null;\n }\n this._cleanup();\n }\n\n /**\n * Disconnect (alias for close)\n */\n async disconnect(): Promise<void> {\n this.close();\n }\n\n // ========== Public API Methods ==========\n\n /**\n * Login with username and password\n */\n async login(username: string, password: string): Promise<any> {\n return this.sendRequest('login', { username, password });\n }\n\n /**\n * Logout from server\n */\n async logout(): Promise<any> {\n return this.sendRequest('logout', {});\n }\n\n /**\n * List all databases\n */\n async listDatabases(): Promise<any> {\n return this.sendRequest('list-dbs', {});\n }\n\n /**\n * Create a new database\n */\n async createDatabase(name: string): Promise<any> {\n return this.sendRequest('create-db', { databaseName: name });\n }\n\n /**\n * Remove a database\n */\n async removeDatabase(name: string): Promise<any> {\n return this.sendRequest('remove-db', { databaseName: name });\n }\n\n /**\n * Rename a database\n */\n async renameDatabase(oldName: string, newName: string): Promise<any> {\n return this.sendRequest('rename-db', { databaseName: oldName, newName });\n }\n\n /**\n * Execute code in a database\n */\n async run(code: string, databaseName: string): Promise<any> {\n return this.sendRequest('script-code', { code, databaseName });\n }\n\n /**\n * Save a database to disk\n */\n async saveDatabase(databaseName: string): Promise<any> {\n return this.sendRequest('save-db', { databaseName });\n }\n\n /**\n * Update database metadata\n */\n async updateDatabase(databaseName: string, data: any): Promise<any> {\n return this.sendRequest('update-db', { databaseName, ...data });\n }\n\n /**\n * Get database content\n */\n async getDatabase(name: string): Promise<{ success: boolean; databaseName: string; content: string; path?: string }> {\n return this.sendRequest('get-db', { databaseName: name });\n }\n\n /**\n * Get server information\n */\n async getInfo(): Promise<any> {\n return this.sendRequest('get-info', {});\n }\n\n /**\n * Execute shell command on server\n */\n async executeShell(command: string): Promise<{ stdout: string; stderr: string }> {\n return this.sendRequest('shell-command', { command });\n }\n}\n\nexport default BrowserClient;\n\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Browser-compatible ScriptDB Client\n * \n * This is a lightweight WebSocket client that connects to the ScriptDB WebSocket proxy.\n * The proxy handles all communication with the ScriptDB server using @scriptdb/client.\n */\n\ntype Action = 'script-code' | 'save-db' | 'remove-db' | 'rename-db' | 'login' | 'logout' | 'get-info' | 'list-dbs' | 'create-db' | 'update-db' | 'get-db' | 'shell-command';\n\ninterface Logger {\n debug?: (...args: any[]) => void;\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n}\n\ninterface ClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n logger?: Logger;\n requestTimeout?: number;\n secure?: boolean;\n}\n\ninterface PendingRequest {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timer: number | null;\n}\n\ninterface Message {\n id?: number;\n action?: Action;\n message?: string;\n data?: any;\n}\n\nconst noopLogger: Logger = {\n debug: () => { },\n info: () => { },\n warn: () => { },\n error: () => { },\n};\n\nexport class BrowserClient {\n private logger: Logger;\n private host: string;\n private port: number;\n private username: string | null;\n private password: string | null;\n private requestTimeout: number;\n private secure: boolean;\n\n private ws: WebSocket | null = null;\n private _connected: boolean = false;\n private _nextId: number = 1;\n private _pending: Map<number, PendingRequest> = new Map();\n\n constructor(options: ClientOptions) {\n this.logger = options.logger || noopLogger;\n this.host = options.host || 'localhost';\n this.port = options.port || 1234;\n this.username = options.username || null;\n this.password = options.password || null;\n this.requestTimeout = Number.isFinite(options.requestTimeout) ? options.requestTimeout! : 120000; // 2 minutes default\n this.secure = options.secure !== undefined ? options.secure : false;\n }\n\n /**\n * Check if connected\n */\n get connected(): boolean {\n return this._connected;\n }\n\n /**\n * Connect to WebSocket proxy and authenticate\n */\n async connect(): Promise<BrowserClient> {\n return new Promise((resolve, reject) => {\n const wsPort = this.port + 1;\n const wsUrl = `ws://${this.host}:${wsPort}`;\n this.logger.info?.('Connecting to', wsUrl);\n\n try {\n this.ws = new WebSocket(wsUrl);\n } catch (e) {\n const error = e as Error;\n this.logger.error?.(\"Connection failed\", error.message);\n return reject(error);\n }\n\n this.ws.onopen = async () => {\n console.log('WebSocket onopen - browserClient.ts');\n this.logger.info?.('WebSocket connected');\n this._connected = true;\n this._setupListeners();\n\n // Always send login request (even with empty credentials for anonymous access)\n try {\n console.log('Sending login request with credentials:', { username: this.username || '', hasPassword: !!this.password, secure: this.secure });\n await this.sendRequest('login', {\n username: this.username || '',\n password: this.password || '',\n secure: this.secure\n });\n console.log('Authenticated successfully');\n this.logger.info?.('Authenticated successfully');\n resolve(this);\n } catch (err) {\n console.error('Login failed:', err);\n reject(err);\n }\n };\n\n this.ws.onerror = (error) => {\n console.error('WebSocket onerror:', error);\n this.logger.error?.('WebSocket error:', error);\n reject(new Error('WebSocket connection failed'));\n };\n\n this.ws.onclose = () => {\n console.log('WebSocket onclose');\n this.logger.info?.('WebSocket disconnected');\n this._connected = false;\n this._cleanup();\n };\n });\n }\n\n /**\n * Setup message listeners\n */\n private _setupListeners() {\n if (!this.ws) return;\n\n this.ws.onmessage = (event) => {\n console.log('WebSocket onmessage fired - browserClient.ts', event.data);\n try {\n const msg = JSON.parse(event.data) as Message;\n console.log('Parsed message:', msg);\n this._handleMessage(msg);\n } catch (error) {\n console.error('Failed to parse message:', error, event.data);\n this.logger.error?.('Failed to parse message:', error);\n }\n };\n }\n\n /**\n * Handle incoming message\n */\n private _handleMessage(msg: Message) {\n console.log('_handleMessage called with:', msg);\n if (!msg || typeof msg !== \"object\") {\n console.log('Invalid message - not an object');\n return;\n }\n\n this.logger.debug?.('Received message:', msg);\n\n // Handle response with id\n if (typeof msg.id !== \"undefined\") {\n console.log('Message has id:', msg.id);\n const pending = this._pending.get(msg.id);\n console.log('Pending request found:', !!pending, 'total pending:', this._pending.size);\n if (!pending) {\n this.logger.debug?.(\"No pending request for id\", msg.id);\n console.log(\"No pending request for id\", msg.id);\n return;\n }\n\n const { resolve, reject, timer } = pending;\n if (timer) clearTimeout(timer);\n this._pending.delete(msg.id);\n\n console.log('Resolving request with message:', msg.message, 'data:', msg.data);\n\n // Check for errors\n if (msg.message === \"ERROR\" || msg.message === \"AUTH FAILED\" || msg.message === \"AUTH FAIL\") {\n return reject(new Error(typeof msg.data === 'string' ? msg.data : \"Request failed\"));\n }\n\n // Success - AUTH OK, OK, or SUCCESS\n if (msg.message === \"AUTH OK\" || msg.message === \"OK\" || msg.message === \"SUCCESS\") {\n console.log('Calling resolve with data:', msg.data);\n return resolve(msg.data);\n }\n\n // Default to resolve with data\n console.log('Default resolve with data:', msg.data);\n return resolve(msg.data);\n }\n console.log('Message has no id, ignoring');\n }\n\n /**\n * Send request to proxy (internal helper)\n */\n private async _sendRequest(action: Action, data: any = {}): Promise<any> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error('Not connected');\n }\n\n const id = this._nextId++;\n const request = { id, action, data };\n\n return new Promise((resolve, reject) => {\n let timer: number | null = null;\n if (this.requestTimeout > 0) {\n timer = window.setTimeout(() => {\n if (this._pending.has(id)) {\n this._pending.delete(id);\n reject(new Error(\"Request timeout\"));\n }\n }, this.requestTimeout);\n }\n\n this._pending.set(id, { resolve, reject, timer });\n\n try {\n this.ws?.send(JSON.stringify(request));\n } catch (e) {\n if (timer) clearTimeout(timer);\n this._pending.delete(id);\n reject(e);\n }\n });\n }\n\n /**\n * Cleanup on disconnect\n */\n private _cleanup() {\n this._pending.forEach((pending) => {\n if (pending.timer) clearTimeout(pending.timer);\n try {\n pending.reject(new Error(\"Disconnected\"));\n } catch (e) { }\n });\n this._pending.clear();\n }\n\n /**\n * Close connection\n */\n close() {\n if (this.ws) {\n try {\n this.ws.close();\n } catch (e) { }\n this.ws = null;\n }\n this._cleanup();\n }\n\n /**\n * Disconnect (alias for close)\n */\n async disconnect(): Promise<void> {\n this.close();\n }\n\n /**\n * Send request helper (for public API methods)\n */\n async sendRequest(action: Action, data: any = {}): Promise<any> {\n return this.execute({ action, data });\n }\n\n /**\n * Execute a command. Supports concurrent requests via request id mapping.\n * Returns a Promise resolved with response.data or rejected on ERROR/timeout.\n */\n async execute(message: Message): Promise<any> {\n if (!message.action) {\n throw new Error('Action is required');\n }\n return this._sendRequest(message.action, message.data);\n }\n\n // ========== Public API Methods ==========\n\n /**\n * Login with username and password\n */\n async login(username: string, password: string): Promise<any> {\n return this.sendRequest('login', { username, password });\n }\n\n /**\n * Logout from server\n */\n async logout(): Promise<any> {\n return this.sendRequest('logout', {});\n }\n\n /**\n * List all databases\n */\n async listDatabases(): Promise<any> {\n return this.sendRequest('list-dbs', {});\n }\n\n /**\n * Create a new database\n */\n async createDatabase(name: string): Promise<any> {\n return this.sendRequest('create-db', { databaseName: name });\n }\n\n /**\n * Remove a database\n */\n async removeDatabase(name: string): Promise<any> {\n return this.sendRequest('remove-db', { databaseName: name });\n }\n\n /**\n * Rename a database\n */\n async renameDatabase(oldName: string, newName: string): Promise<any> {\n return this.sendRequest('rename-db', { databaseName: oldName, newName });\n }\n\n /**\n * Execute code in a database\n */\n async run(code: string | Function, databaseName: string): Promise<any> {\n let stringCode: string;\n if (typeof code === 'function') {\n const funcStr = code.toString();\n // ตัด arrow function หรือ function keyword และ opening brace ออก\n const arrowMatch = funcStr.match(/^[\\s]*\\(?\\s*\\)?\\s*=>\\s*{?/);\n const functionMatch = funcStr.match(/^[\\s]*function\\s*\\(?[\\w\\s]*\\)?\\s*{/);\n const match = arrowMatch || functionMatch;\n const start = match ? match[0].length : 0;\n const end = funcStr.lastIndexOf('}');\n stringCode = funcStr.substring(start, end);\n // Trim leading newline, spaces, and trailing\n stringCode = stringCode.replace(/^[\\s\\r\\n]+/, '').replace(/[\\s\\r\\n]+$/, '');\n\n // Transform import(aa).from(\"module\") to import aa from \"module\"\n stringCode = stringCode.replace(\n /import\\s*\\(\\s*([^)]+?)\\s*\\)\\s*\\.from\\s*\\(\\s*(['\"])([^'\"]+)\\2\\s*\\)/g,\n (_, importArg, quote, modulePath) => {\n // Check if importArg is wrapped in braces (destructuring)\n const trimmed = importArg.trim();\n if (trimmed.startsWith('{') && trimmed.endsWith('}')) {\n // Destructuring: import({bb}) -> import { bb }\n const inner = trimmed.slice(1, -1).trim();\n return `import { ${inner} } from ${quote}${modulePath}${quote}`;\n } else {\n // Default: import(aa) -> import aa\n return `import ${trimmed} from ${quote}${modulePath}${quote}`;\n }\n }\n );\n\n // Trim leading whitespace from each line\n stringCode = stringCode.split('\\n').map(line => line.trim()).join('\\n').trim();\n } else {\n stringCode = code;\n }\n\n return this.sendRequest('script-code', { code: stringCode, databaseName });\n }\n\n /**\n * Save a database to disk\n */\n async saveDatabase(databaseName: string): Promise<any> {\n return this.sendRequest('save-db', { databaseName });\n }\n\n /**\n * Update database metadata\n */\n async updateDatabase(databaseName: string, data: any): Promise<any> {\n return this.sendRequest('update-db', { databaseName, ...data });\n }\n\n /**\n * Get database content\n */\n async getDatabase(name: string): Promise<{ success: boolean; databaseName: string; content: string; path?: string }> {\n return this.sendRequest('get-db', { databaseName: name });\n }\n\n /**\n * Get server information\n */\n async getInfo(): Promise<any> {\n return this.sendRequest('get-info', {});\n }\n\n /**\n * Execute shell command on server\n */\n async executeShell(command: string): Promise<{ stdout: string; stderr: string }> {\n return this.sendRequest('shell-command', { command });\n }\n}\n\nexport default BrowserClient;\n\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -130,9 +130,9 @@ var BrowserClient = class {
130
130
  console.log("Message has no id, ignoring");
131
131
  }
132
132
  /**
133
- * Send request to proxy
133
+ * Send request to proxy (internal helper)
134
134
  */
135
- async sendRequest(action, data = {}) {
135
+ async _sendRequest(action, data = {}) {
136
136
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
137
137
  throw new Error("Not connected");
138
138
  }
@@ -190,6 +190,22 @@ var BrowserClient = class {
190
190
  async disconnect() {
191
191
  this.close();
192
192
  }
193
+ /**
194
+ * Send request helper (for public API methods)
195
+ */
196
+ async sendRequest(action, data = {}) {
197
+ return this.execute({ action, data });
198
+ }
199
+ /**
200
+ * Execute a command. Supports concurrent requests via request id mapping.
201
+ * Returns a Promise resolved with response.data or rejected on ERROR/timeout.
202
+ */
203
+ async execute(message) {
204
+ if (!message.action) {
205
+ throw new Error("Action is required");
206
+ }
207
+ return this._sendRequest(message.action, message.data);
208
+ }
193
209
  // ========== Public API Methods ==========
194
210
  /**
195
211
  * Login with username and password
@@ -231,7 +247,33 @@ var BrowserClient = class {
231
247
  * Execute code in a database
232
248
  */
233
249
  async run(code, databaseName) {
234
- return this.sendRequest("script-code", { code, databaseName });
250
+ let stringCode;
251
+ if (typeof code === "function") {
252
+ const funcStr = code.toString();
253
+ const arrowMatch = funcStr.match(/^[\s]*\(?\s*\)?\s*=>\s*{?/);
254
+ const functionMatch = funcStr.match(/^[\s]*function\s*\(?[\w\s]*\)?\s*{/);
255
+ const match = arrowMatch || functionMatch;
256
+ const start = match ? match[0].length : 0;
257
+ const end = funcStr.lastIndexOf("}");
258
+ stringCode = funcStr.substring(start, end);
259
+ stringCode = stringCode.replace(/^[\s\r\n]+/, "").replace(/[\s\r\n]+$/, "");
260
+ stringCode = stringCode.replace(
261
+ /import\s*\(\s*([^)]+?)\s*\)\s*\.from\s*\(\s*(['"])([^'"]+)\2\s*\)/g,
262
+ (_, importArg, quote, modulePath) => {
263
+ const trimmed = importArg.trim();
264
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
265
+ const inner = trimmed.slice(1, -1).trim();
266
+ return `import { ${inner} } from ${quote}${modulePath}${quote}`;
267
+ } else {
268
+ return `import ${trimmed} from ${quote}${modulePath}${quote}`;
269
+ }
270
+ }
271
+ );
272
+ stringCode = stringCode.split("\n").map((line) => line.trim()).join("\n").trim();
273
+ } else {
274
+ stringCode = code;
275
+ }
276
+ return this.sendRequest("script-code", { code: stringCode, databaseName });
235
277
  }
236
278
  /**
237
279
  * Save a database to disk
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Browser-compatible ScriptDB Client\n * \n * This is a lightweight WebSocket client that connects to the ScriptDB WebSocket proxy.\n * The proxy handles all communication with the ScriptDB server using @scriptdb/client.\n */\n\ntype Action = 'script-code' | 'save-db' | 'remove-db' | 'rename-db' | 'login' | 'logout' | 'get-info' | 'list-dbs' | 'create-db' | 'update-db' | 'get-db' | 'shell-command';\n\ninterface Logger {\n debug?: (...args: any[]) => void;\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n}\n\ninterface ClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n logger?: Logger;\n requestTimeout?: number;\n secure?: boolean;\n}\n\ninterface PendingRequest {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timer: number | null;\n}\n\ninterface Message {\n id?: number;\n action?: Action;\n message?: string;\n data?: any;\n}\n\nconst noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nexport class BrowserClient {\n private logger: Logger;\n private host: string;\n private port: number;\n private username: string | null;\n private password: string | null;\n private requestTimeout: number;\n private secure: boolean;\n\n private ws: WebSocket | null = null;\n private _connected: boolean = false;\n private _nextId: number = 1;\n private _pending: Map<number, PendingRequest> = new Map();\n\n constructor(options: ClientOptions) {\n this.logger = options.logger || noopLogger;\n this.host = options.host || 'localhost';\n this.port = options.port || 1234;\n this.username = options.username || null;\n this.password = options.password || null;\n this.requestTimeout = Number.isFinite(options.requestTimeout) ? options.requestTimeout! : 120000; // 2 minutes default\n this.secure = options.secure !== undefined ? options.secure : false;\n }\n\n /**\n * Check if connected\n */\n get connected(): boolean {\n return this._connected;\n }\n\n /**\n * Connect to WebSocket proxy and authenticate\n */\n async connect(): Promise<BrowserClient> {\n return new Promise((resolve, reject) => {\n const wsPort = this.port + 1;\n const wsUrl = `ws://${this.host}:${wsPort}`;\n this.logger.info?.('Connecting to', wsUrl);\n\n try {\n this.ws = new WebSocket(wsUrl);\n } catch (e) {\n const error = e as Error;\n this.logger.error?.(\"Connection failed\", error.message);\n return reject(error);\n }\n\n this.ws.onopen = async () => {\n console.log('WebSocket onopen - browserClient.ts');\n this.logger.info?.('WebSocket connected');\n this._connected = true;\n this._setupListeners();\n\n // Always send login request (even with empty credentials for anonymous access)\n try {\n console.log('Sending login request with credentials:', { username: this.username || '', hasPassword: !!this.password, secure: this.secure });\n await this.sendRequest('login', { \n username: this.username || '', \n password: this.password || '',\n secure: this.secure\n });\n console.log('Authenticated successfully');\n this.logger.info?.('Authenticated successfully');\n resolve(this);\n } catch (err) {\n console.error('Login failed:', err);\n reject(err);\n }\n };\n\n this.ws.onerror = (error) => {\n console.error('WebSocket onerror:', error);\n this.logger.error?.('WebSocket error:', error);\n reject(new Error('WebSocket connection failed'));\n };\n\n this.ws.onclose = () => {\n console.log('WebSocket onclose');\n this.logger.info?.('WebSocket disconnected');\n this._connected = false;\n this._cleanup();\n };\n });\n }\n\n /**\n * Setup message listeners\n */\n private _setupListeners() {\n if (!this.ws) return;\n\n this.ws.onmessage = (event) => {\n console.log('WebSocket onmessage fired - browserClient.ts', event.data);\n try {\n const msg = JSON.parse(event.data) as Message;\n console.log('Parsed message:', msg);\n this._handleMessage(msg);\n } catch (error) {\n console.error('Failed to parse message:', error, event.data);\n this.logger.error?.('Failed to parse message:', error);\n }\n };\n }\n\n /**\n * Handle incoming message\n */\n private _handleMessage(msg: Message) {\n console.log('_handleMessage called with:', msg);\n if (!msg || typeof msg !== \"object\") {\n console.log('Invalid message - not an object');\n return;\n }\n\n this.logger.debug?.('Received message:', msg);\n\n // Handle response with id\n if (typeof msg.id !== \"undefined\") {\n console.log('Message has id:', msg.id);\n const pending = this._pending.get(msg.id);\n console.log('Pending request found:', !!pending, 'total pending:', this._pending.size);\n if (!pending) {\n this.logger.debug?.(\"No pending request for id\", msg.id);\n console.log(\"No pending request for id\", msg.id);\n return;\n }\n\n const { resolve, reject, timer } = pending;\n if (timer) clearTimeout(timer);\n this._pending.delete(msg.id);\n\n console.log('Resolving request with message:', msg.message, 'data:', msg.data);\n\n // Check for errors\n if (msg.message === \"ERROR\" || msg.message === \"AUTH FAILED\" || msg.message === \"AUTH FAIL\") {\n return reject(new Error(typeof msg.data === 'string' ? msg.data : \"Request failed\"));\n }\n\n // Success - AUTH OK, OK, or SUCCESS\n if (msg.message === \"AUTH OK\" || msg.message === \"OK\" || msg.message === \"SUCCESS\") {\n console.log('Calling resolve with data:', msg.data);\n return resolve(msg.data);\n }\n\n // Default to resolve with data\n console.log('Default resolve with data:', msg.data);\n return resolve(msg.data);\n }\n console.log('Message has no id, ignoring');\n }\n\n /**\n * Send request to proxy\n */\n private async sendRequest(action: Action, data: any = {}): Promise<any> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error('Not connected');\n }\n\n const id = this._nextId++;\n const request = { id, action, data };\n\n return new Promise((resolve, reject) => {\n let timer: number | null = null;\n if (this.requestTimeout > 0) {\n timer = window.setTimeout(() => {\n if (this._pending.has(id)) {\n this._pending.delete(id);\n reject(new Error(\"Request timeout\"));\n }\n }, this.requestTimeout);\n }\n\n this._pending.set(id, { resolve, reject, timer });\n\n try {\n this.ws?.send(JSON.stringify(request));\n } catch (e) {\n if (timer) clearTimeout(timer);\n this._pending.delete(id);\n reject(e);\n }\n });\n }\n\n /**\n * Cleanup on disconnect\n */\n private _cleanup() {\n this._pending.forEach((pending) => {\n if (pending.timer) clearTimeout(pending.timer);\n try {\n pending.reject(new Error(\"Disconnected\"));\n } catch (e) {}\n });\n this._pending.clear();\n }\n\n /**\n * Close connection\n */\n close() {\n if (this.ws) {\n try {\n this.ws.close();\n } catch (e) {}\n this.ws = null;\n }\n this._cleanup();\n }\n\n /**\n * Disconnect (alias for close)\n */\n async disconnect(): Promise<void> {\n this.close();\n }\n\n // ========== Public API Methods ==========\n\n /**\n * Login with username and password\n */\n async login(username: string, password: string): Promise<any> {\n return this.sendRequest('login', { username, password });\n }\n\n /**\n * Logout from server\n */\n async logout(): Promise<any> {\n return this.sendRequest('logout', {});\n }\n\n /**\n * List all databases\n */\n async listDatabases(): Promise<any> {\n return this.sendRequest('list-dbs', {});\n }\n\n /**\n * Create a new database\n */\n async createDatabase(name: string): Promise<any> {\n return this.sendRequest('create-db', { databaseName: name });\n }\n\n /**\n * Remove a database\n */\n async removeDatabase(name: string): Promise<any> {\n return this.sendRequest('remove-db', { databaseName: name });\n }\n\n /**\n * Rename a database\n */\n async renameDatabase(oldName: string, newName: string): Promise<any> {\n return this.sendRequest('rename-db', { databaseName: oldName, newName });\n }\n\n /**\n * Execute code in a database\n */\n async run(code: string, databaseName: string): Promise<any> {\n return this.sendRequest('script-code', { code, databaseName });\n }\n\n /**\n * Save a database to disk\n */\n async saveDatabase(databaseName: string): Promise<any> {\n return this.sendRequest('save-db', { databaseName });\n }\n\n /**\n * Update database metadata\n */\n async updateDatabase(databaseName: string, data: any): Promise<any> {\n return this.sendRequest('update-db', { databaseName, ...data });\n }\n\n /**\n * Get database content\n */\n async getDatabase(name: string): Promise<{ success: boolean; databaseName: string; content: string; path?: string }> {\n return this.sendRequest('get-db', { databaseName: name });\n }\n\n /**\n * Get server information\n */\n async getInfo(): Promise<any> {\n return this.sendRequest('get-info', {});\n }\n\n /**\n * Execute shell command on server\n */\n async executeShell(command: string): Promise<{ stdout: string; stderr: string }> {\n return this.sendRequest('shell-command', { command });\n }\n}\n\nexport default BrowserClient;\n\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Browser-compatible ScriptDB Client\n * \n * This is a lightweight WebSocket client that connects to the ScriptDB WebSocket proxy.\n * The proxy handles all communication with the ScriptDB server using @scriptdb/client.\n */\n\ntype Action = 'script-code' | 'save-db' | 'remove-db' | 'rename-db' | 'login' | 'logout' | 'get-info' | 'list-dbs' | 'create-db' | 'update-db' | 'get-db' | 'shell-command';\n\ninterface Logger {\n debug?: (...args: any[]) => void;\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n}\n\ninterface ClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n logger?: Logger;\n requestTimeout?: number;\n secure?: boolean;\n}\n\ninterface PendingRequest {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timer: number | null;\n}\n\ninterface Message {\n id?: number;\n action?: Action;\n message?: string;\n data?: any;\n}\n\nconst noopLogger: Logger = {\n debug: () => { },\n info: () => { },\n warn: () => { },\n error: () => { },\n};\n\nexport class BrowserClient {\n private logger: Logger;\n private host: string;\n private port: number;\n private username: string | null;\n private password: string | null;\n private requestTimeout: number;\n private secure: boolean;\n\n private ws: WebSocket | null = null;\n private _connected: boolean = false;\n private _nextId: number = 1;\n private _pending: Map<number, PendingRequest> = new Map();\n\n constructor(options: ClientOptions) {\n this.logger = options.logger || noopLogger;\n this.host = options.host || 'localhost';\n this.port = options.port || 1234;\n this.username = options.username || null;\n this.password = options.password || null;\n this.requestTimeout = Number.isFinite(options.requestTimeout) ? options.requestTimeout! : 120000; // 2 minutes default\n this.secure = options.secure !== undefined ? options.secure : false;\n }\n\n /**\n * Check if connected\n */\n get connected(): boolean {\n return this._connected;\n }\n\n /**\n * Connect to WebSocket proxy and authenticate\n */\n async connect(): Promise<BrowserClient> {\n return new Promise((resolve, reject) => {\n const wsPort = this.port + 1;\n const wsUrl = `ws://${this.host}:${wsPort}`;\n this.logger.info?.('Connecting to', wsUrl);\n\n try {\n this.ws = new WebSocket(wsUrl);\n } catch (e) {\n const error = e as Error;\n this.logger.error?.(\"Connection failed\", error.message);\n return reject(error);\n }\n\n this.ws.onopen = async () => {\n console.log('WebSocket onopen - browserClient.ts');\n this.logger.info?.('WebSocket connected');\n this._connected = true;\n this._setupListeners();\n\n // Always send login request (even with empty credentials for anonymous access)\n try {\n console.log('Sending login request with credentials:', { username: this.username || '', hasPassword: !!this.password, secure: this.secure });\n await this.sendRequest('login', {\n username: this.username || '',\n password: this.password || '',\n secure: this.secure\n });\n console.log('Authenticated successfully');\n this.logger.info?.('Authenticated successfully');\n resolve(this);\n } catch (err) {\n console.error('Login failed:', err);\n reject(err);\n }\n };\n\n this.ws.onerror = (error) => {\n console.error('WebSocket onerror:', error);\n this.logger.error?.('WebSocket error:', error);\n reject(new Error('WebSocket connection failed'));\n };\n\n this.ws.onclose = () => {\n console.log('WebSocket onclose');\n this.logger.info?.('WebSocket disconnected');\n this._connected = false;\n this._cleanup();\n };\n });\n }\n\n /**\n * Setup message listeners\n */\n private _setupListeners() {\n if (!this.ws) return;\n\n this.ws.onmessage = (event) => {\n console.log('WebSocket onmessage fired - browserClient.ts', event.data);\n try {\n const msg = JSON.parse(event.data) as Message;\n console.log('Parsed message:', msg);\n this._handleMessage(msg);\n } catch (error) {\n console.error('Failed to parse message:', error, event.data);\n this.logger.error?.('Failed to parse message:', error);\n }\n };\n }\n\n /**\n * Handle incoming message\n */\n private _handleMessage(msg: Message) {\n console.log('_handleMessage called with:', msg);\n if (!msg || typeof msg !== \"object\") {\n console.log('Invalid message - not an object');\n return;\n }\n\n this.logger.debug?.('Received message:', msg);\n\n // Handle response with id\n if (typeof msg.id !== \"undefined\") {\n console.log('Message has id:', msg.id);\n const pending = this._pending.get(msg.id);\n console.log('Pending request found:', !!pending, 'total pending:', this._pending.size);\n if (!pending) {\n this.logger.debug?.(\"No pending request for id\", msg.id);\n console.log(\"No pending request for id\", msg.id);\n return;\n }\n\n const { resolve, reject, timer } = pending;\n if (timer) clearTimeout(timer);\n this._pending.delete(msg.id);\n\n console.log('Resolving request with message:', msg.message, 'data:', msg.data);\n\n // Check for errors\n if (msg.message === \"ERROR\" || msg.message === \"AUTH FAILED\" || msg.message === \"AUTH FAIL\") {\n return reject(new Error(typeof msg.data === 'string' ? msg.data : \"Request failed\"));\n }\n\n // Success - AUTH OK, OK, or SUCCESS\n if (msg.message === \"AUTH OK\" || msg.message === \"OK\" || msg.message === \"SUCCESS\") {\n console.log('Calling resolve with data:', msg.data);\n return resolve(msg.data);\n }\n\n // Default to resolve with data\n console.log('Default resolve with data:', msg.data);\n return resolve(msg.data);\n }\n console.log('Message has no id, ignoring');\n }\n\n /**\n * Send request to proxy (internal helper)\n */\n private async _sendRequest(action: Action, data: any = {}): Promise<any> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error('Not connected');\n }\n\n const id = this._nextId++;\n const request = { id, action, data };\n\n return new Promise((resolve, reject) => {\n let timer: number | null = null;\n if (this.requestTimeout > 0) {\n timer = window.setTimeout(() => {\n if (this._pending.has(id)) {\n this._pending.delete(id);\n reject(new Error(\"Request timeout\"));\n }\n }, this.requestTimeout);\n }\n\n this._pending.set(id, { resolve, reject, timer });\n\n try {\n this.ws?.send(JSON.stringify(request));\n } catch (e) {\n if (timer) clearTimeout(timer);\n this._pending.delete(id);\n reject(e);\n }\n });\n }\n\n /**\n * Cleanup on disconnect\n */\n private _cleanup() {\n this._pending.forEach((pending) => {\n if (pending.timer) clearTimeout(pending.timer);\n try {\n pending.reject(new Error(\"Disconnected\"));\n } catch (e) { }\n });\n this._pending.clear();\n }\n\n /**\n * Close connection\n */\n close() {\n if (this.ws) {\n try {\n this.ws.close();\n } catch (e) { }\n this.ws = null;\n }\n this._cleanup();\n }\n\n /**\n * Disconnect (alias for close)\n */\n async disconnect(): Promise<void> {\n this.close();\n }\n\n /**\n * Send request helper (for public API methods)\n */\n async sendRequest(action: Action, data: any = {}): Promise<any> {\n return this.execute({ action, data });\n }\n\n /**\n * Execute a command. Supports concurrent requests via request id mapping.\n * Returns a Promise resolved with response.data or rejected on ERROR/timeout.\n */\n async execute(message: Message): Promise<any> {\n if (!message.action) {\n throw new Error('Action is required');\n }\n return this._sendRequest(message.action, message.data);\n }\n\n // ========== Public API Methods ==========\n\n /**\n * Login with username and password\n */\n async login(username: string, password: string): Promise<any> {\n return this.sendRequest('login', { username, password });\n }\n\n /**\n * Logout from server\n */\n async logout(): Promise<any> {\n return this.sendRequest('logout', {});\n }\n\n /**\n * List all databases\n */\n async listDatabases(): Promise<any> {\n return this.sendRequest('list-dbs', {});\n }\n\n /**\n * Create a new database\n */\n async createDatabase(name: string): Promise<any> {\n return this.sendRequest('create-db', { databaseName: name });\n }\n\n /**\n * Remove a database\n */\n async removeDatabase(name: string): Promise<any> {\n return this.sendRequest('remove-db', { databaseName: name });\n }\n\n /**\n * Rename a database\n */\n async renameDatabase(oldName: string, newName: string): Promise<any> {\n return this.sendRequest('rename-db', { databaseName: oldName, newName });\n }\n\n /**\n * Execute code in a database\n */\n async run(code: string | Function, databaseName: string): Promise<any> {\n let stringCode: string;\n if (typeof code === 'function') {\n const funcStr = code.toString();\n // ตัด arrow function หรือ function keyword และ opening brace ออก\n const arrowMatch = funcStr.match(/^[\\s]*\\(?\\s*\\)?\\s*=>\\s*{?/);\n const functionMatch = funcStr.match(/^[\\s]*function\\s*\\(?[\\w\\s]*\\)?\\s*{/);\n const match = arrowMatch || functionMatch;\n const start = match ? match[0].length : 0;\n const end = funcStr.lastIndexOf('}');\n stringCode = funcStr.substring(start, end);\n // Trim leading newline, spaces, and trailing\n stringCode = stringCode.replace(/^[\\s\\r\\n]+/, '').replace(/[\\s\\r\\n]+$/, '');\n\n // Transform import(aa).from(\"module\") to import aa from \"module\"\n stringCode = stringCode.replace(\n /import\\s*\\(\\s*([^)]+?)\\s*\\)\\s*\\.from\\s*\\(\\s*(['\"])([^'\"]+)\\2\\s*\\)/g,\n (_, importArg, quote, modulePath) => {\n // Check if importArg is wrapped in braces (destructuring)\n const trimmed = importArg.trim();\n if (trimmed.startsWith('{') && trimmed.endsWith('}')) {\n // Destructuring: import({bb}) -> import { bb }\n const inner = trimmed.slice(1, -1).trim();\n return `import { ${inner} } from ${quote}${modulePath}${quote}`;\n } else {\n // Default: import(aa) -> import aa\n return `import ${trimmed} from ${quote}${modulePath}${quote}`;\n }\n }\n );\n\n // Trim leading whitespace from each line\n stringCode = stringCode.split('\\n').map(line => line.trim()).join('\\n').trim();\n } else {\n stringCode = code;\n }\n\n return this.sendRequest('script-code', { code: stringCode, databaseName });\n }\n\n /**\n * Save a database to disk\n */\n async saveDatabase(databaseName: string): Promise<any> {\n return this.sendRequest('save-db', { databaseName });\n }\n\n /**\n * Update database metadata\n */\n async updateDatabase(databaseName: string, data: any): Promise<any> {\n return this.sendRequest('update-db', { databaseName, ...data });\n }\n\n /**\n * Get database content\n */\n async getDatabase(name: string): Promise<{ success: boolean; databaseName: string; content: string; path?: string }> {\n return this.sendRequest('get-db', { databaseName: name });\n }\n\n /**\n * Get server information\n */\n async getInfo(): Promise<any> {\n return this.sendRequest('get-info', {});\n }\n\n /**\n * Execute shell command on server\n */\n async executeShell(command: string): Promise<{ stdout: string; stderr: string }> {\n return this.sendRequest('shell-command', { command });\n }\n}\n\nexport default BrowserClient;\n\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptdb/browser-client",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Browser WebSocket client for ScriptDB",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",