@mimersql/node-mimer 1.0.0

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/index.d.ts ADDED
@@ -0,0 +1,153 @@
1
+ /**
2
+ * node-mimer - Node.js bindings for Mimer SQL
3
+ */
4
+
5
+ export interface ConnectOptions {
6
+ /** Database name */
7
+ dsn: string;
8
+ /** Username */
9
+ user: string;
10
+ /** Password */
11
+ password: string;
12
+ }
13
+
14
+ export interface PoolOptions extends ConnectOptions {
15
+ /** Maximum number of connections (default 10) */
16
+ max?: number;
17
+ /** Milliseconds before an idle connection is closed (default 30000) */
18
+ idleTimeout?: number;
19
+ /** Milliseconds to wait for a connection when pool is full (default 5000) */
20
+ acquireTimeout?: number;
21
+ }
22
+
23
+ export interface FieldInfo {
24
+ /** Column name */
25
+ name: string;
26
+ /** Numeric Mimer type code */
27
+ dataTypeCode: number;
28
+ /** Human-readable SQL type name (e.g. "INTEGER", "NVARCHAR") */
29
+ dataTypeName: string;
30
+ /** Whether the column allows NULL values */
31
+ nullable: boolean;
32
+ }
33
+
34
+ export interface QueryResult {
35
+ /** Array of row objects (SELECT only) */
36
+ rows?: Record<string, any>[];
37
+ /** Number of rows returned or affected */
38
+ rowCount: number;
39
+ /** Column metadata (SELECT only) */
40
+ fields?: FieldInfo[];
41
+ }
42
+
43
+ export class MimerClient {
44
+ /** Whether the client is currently connected */
45
+ connected: boolean;
46
+
47
+ /** Connect to a Mimer SQL database */
48
+ connect(options: ConnectOptions): Promise<void>;
49
+
50
+ /** Execute a SQL statement with optional parameter binding */
51
+ query(sql: string, params?: any[]): Promise<QueryResult>;
52
+
53
+ /** Prepare a SQL statement for repeated execution */
54
+ prepare(sql: string): Promise<PreparedStatement>;
55
+
56
+ /** Execute a SELECT and return a cursor for row-at-a-time streaming */
57
+ queryCursor(sql: string, params?: any[]): Promise<ResultSet>;
58
+
59
+ /** Begin a new transaction */
60
+ beginTransaction(): Promise<void>;
61
+
62
+ /** Commit the current transaction */
63
+ commit(): Promise<void>;
64
+
65
+ /** Rollback the current transaction */
66
+ rollback(): Promise<void>;
67
+
68
+ /** Close the database connection */
69
+ close(): Promise<void>;
70
+
71
+ /** Check if connected to database */
72
+ isConnected(): boolean;
73
+ }
74
+
75
+ export class PreparedStatement {
76
+ /** Execute the prepared statement with parameter values */
77
+ execute(params?: any[]): Promise<QueryResult>;
78
+
79
+ /** Close the prepared statement and release resources */
80
+ close(): Promise<void>;
81
+ }
82
+
83
+ export class ResultSet {
84
+ /** Column metadata array */
85
+ readonly fields: FieldInfo[];
86
+
87
+ /** Fetch the next row, or null when exhausted */
88
+ next(): Promise<Record<string, any> | null>;
89
+
90
+ /** Close the cursor and release resources */
91
+ close(): Promise<void>;
92
+
93
+ /** Async iterator for for-await-of */
94
+ [Symbol.asyncIterator](): AsyncIterableIterator<Record<string, any>>;
95
+ }
96
+
97
+ export class Pool {
98
+ /** Total number of connections (idle + active) */
99
+ readonly totalCount: number;
100
+
101
+ /** Number of idle connections */
102
+ readonly idleCount: number;
103
+
104
+ /** Number of checked-out connections */
105
+ readonly activeCount: number;
106
+
107
+ /** Number of callers waiting for a connection */
108
+ readonly waitingCount: number;
109
+
110
+ /** Acquire a connection, execute the query, and release */
111
+ query(sql: string, params?: any[]): Promise<QueryResult>;
112
+
113
+ /** Acquire a connection and open a cursor (auto-released on close) */
114
+ queryCursor(sql: string, params?: any[]): Promise<ResultSet>;
115
+
116
+ /** Check out a connection for multiple operations */
117
+ connect(): Promise<PoolClient>;
118
+
119
+ /** Close all connections and shut down the pool */
120
+ end(): Promise<void>;
121
+ }
122
+
123
+ export class PoolClient {
124
+ /** Execute a SQL statement */
125
+ query(sql: string, params?: any[]): Promise<QueryResult>;
126
+
127
+ /** Open a cursor for row-at-a-time streaming */
128
+ queryCursor(sql: string, params?: any[]): Promise<ResultSet>;
129
+
130
+ /** Prepare a SQL statement */
131
+ prepare(sql: string): Promise<PreparedStatement>;
132
+
133
+ /** Begin a new transaction */
134
+ beginTransaction(): Promise<void>;
135
+
136
+ /** Commit the current transaction */
137
+ commit(): Promise<void>;
138
+
139
+ /** Rollback the current transaction */
140
+ rollback(): Promise<void>;
141
+
142
+ /** Return the connection to the pool */
143
+ release(): void;
144
+ }
145
+
146
+ /** Create and connect a new MimerClient */
147
+ export function connect(options: ConnectOptions): Promise<MimerClient>;
148
+
149
+ /** Create a new connection pool */
150
+ export function createPool(options: PoolOptions): Pool;
151
+
152
+ /** Native addon version string */
153
+ export const version: string;
package/index.js ADDED
@@ -0,0 +1,48 @@
1
+ // Copyright (c) 2026 Mimer Information Technology
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in all
11
+ // copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ // SOFTWARE.
20
+ //
21
+ // See license for more details.
22
+
23
+ /**
24
+ * node-mimer - Node.js bindings for Mimer SQL
25
+ *
26
+ * This module provides a JavaScript interface to the native Mimer API bindings.
27
+ */
28
+
29
+ const mimer = require('./lib/native');
30
+ const { MimerClient, connect } = require('./lib/client');
31
+ const { PreparedStatement } = require('./lib/prepared');
32
+ const { ResultSet } = require('./lib/resultset');
33
+ const { Pool, PoolClient } = require('./lib/pool');
34
+
35
+ function createPool(options) {
36
+ return new Pool(options);
37
+ }
38
+
39
+ module.exports = {
40
+ MimerClient,
41
+ PreparedStatement,
42
+ ResultSet,
43
+ Pool,
44
+ PoolClient,
45
+ connect,
46
+ createPool,
47
+ version: mimer.version,
48
+ };
package/lib/client.js ADDED
@@ -0,0 +1,225 @@
1
+ // Copyright (c) 2026 Mimer Information Technology
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in all
11
+ // copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ // SOFTWARE.
20
+ //
21
+ // See license for more details.
22
+
23
+ const mimer = require('./native');
24
+ const { PreparedStatement } = require('./prepared');
25
+ const { ResultSet } = require('./resultset');
26
+
27
+ /**
28
+ * MimerClient provides a Promise-based interface to Mimer SQL
29
+ */
30
+ class MimerClient {
31
+ constructor() {
32
+ this.connection = new mimer.Connection();
33
+ this.connected = false;
34
+ }
35
+
36
+ /**
37
+ * Connect to a Mimer SQL database
38
+ * @param {Object} options - Connection options
39
+ * @param {string} options.dsn - Database name
40
+ * @param {string} options.user - Username
41
+ * @param {string} options.password - Password
42
+ * @returns {Promise<void>}
43
+ */
44
+ async connect(options) {
45
+ const { dsn, user, password } = options;
46
+
47
+ if (!dsn || !user || !password) {
48
+ throw new Error('dsn, user, and password are required');
49
+ }
50
+
51
+ return new Promise((resolve, reject) => {
52
+ try {
53
+ const result = this.connection.connect(dsn, user, password);
54
+ if (result) {
55
+ this.connected = true;
56
+ resolve();
57
+ } else {
58
+ reject(new Error('Connection failed'));
59
+ }
60
+ } catch (error) {
61
+ reject(error);
62
+ }
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Execute a SQL query
68
+ * @param {string} sql - SQL statement to execute
69
+ * @param {Array} params - Optional parameters (for future prepared statement support)
70
+ * @returns {Promise<Object>} Result object with rows and metadata
71
+ */
72
+ async query(sql, params = []) {
73
+ if (!this.connected) {
74
+ throw new Error('Not connected to database');
75
+ }
76
+
77
+ return new Promise((resolve, reject) => {
78
+ try {
79
+ const result = this.connection.execute(sql, params);
80
+ resolve(result);
81
+ } catch (error) {
82
+ reject(error);
83
+ }
84
+ });
85
+ }
86
+
87
+ /**
88
+ * Begin a transaction
89
+ * @returns {Promise<void>}
90
+ */
91
+ async beginTransaction() {
92
+ if (!this.connected) {
93
+ throw new Error('Not connected to database');
94
+ }
95
+
96
+ return new Promise((resolve, reject) => {
97
+ try {
98
+ this.connection.beginTransaction();
99
+ resolve();
100
+ } catch (error) {
101
+ reject(error);
102
+ }
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Commit the current transaction
108
+ * @returns {Promise<void>}
109
+ */
110
+ async commit() {
111
+ if (!this.connected) {
112
+ throw new Error('Not connected to database');
113
+ }
114
+
115
+ return new Promise((resolve, reject) => {
116
+ try {
117
+ this.connection.commit();
118
+ resolve();
119
+ } catch (error) {
120
+ reject(error);
121
+ }
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Rollback the current transaction
127
+ * @returns {Promise<void>}
128
+ */
129
+ async rollback() {
130
+ if (!this.connected) {
131
+ throw new Error('Not connected to database');
132
+ }
133
+
134
+ return new Promise((resolve, reject) => {
135
+ try {
136
+ this.connection.rollback();
137
+ resolve();
138
+ } catch (error) {
139
+ reject(error);
140
+ }
141
+ });
142
+ }
143
+
144
+ /**
145
+ * Close the database connection
146
+ * @returns {Promise<void>}
147
+ */
148
+ async close() {
149
+ if (!this.connected) {
150
+ return;
151
+ }
152
+
153
+ return new Promise((resolve, reject) => {
154
+ try {
155
+ this.connection.close();
156
+ this.connected = false;
157
+ resolve();
158
+ } catch (error) {
159
+ reject(error);
160
+ }
161
+ });
162
+ }
163
+
164
+ /**
165
+ * Prepare a SQL statement for repeated execution
166
+ * @param {string} sql - SQL statement with ? placeholders
167
+ * @returns {Promise<PreparedStatement>}
168
+ */
169
+ async prepare(sql) {
170
+ if (!this.connected) {
171
+ throw new Error('Not connected to database');
172
+ }
173
+
174
+ return new Promise((resolve, reject) => {
175
+ try {
176
+ const stmt = this.connection.prepare(sql);
177
+ resolve(new PreparedStatement(stmt));
178
+ } catch (error) {
179
+ reject(error);
180
+ }
181
+ });
182
+ }
183
+
184
+ /**
185
+ * Execute a SELECT query and return a cursor for row-at-a-time iteration.
186
+ * @param {string} sql - SELECT statement (with optional ? placeholders)
187
+ * @param {Array} params - Optional parameter values
188
+ * @returns {Promise<ResultSet>}
189
+ */
190
+ async queryCursor(sql, params = []) {
191
+ if (!this.connected) {
192
+ throw new Error('Not connected to database');
193
+ }
194
+
195
+ return new Promise((resolve, reject) => {
196
+ try {
197
+ const nativeRs = this.connection.executeQuery(sql, params);
198
+ resolve(new ResultSet(nativeRs));
199
+ } catch (error) {
200
+ reject(error);
201
+ }
202
+ });
203
+ }
204
+
205
+ /**
206
+ * Check if connected to database
207
+ * @returns {boolean}
208
+ */
209
+ isConnected() {
210
+ return this.connection.isConnected();
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Helper function to create a connection with options
216
+ * @param {Object} options - Connection options
217
+ * @returns {Promise<MimerClient>} Connected client instance
218
+ */
219
+ async function connect(options) {
220
+ const client = new MimerClient();
221
+ await client.connect(options);
222
+ return client;
223
+ }
224
+
225
+ module.exports = { MimerClient, connect };
@@ -0,0 +1,154 @@
1
+ // Copyright (c) 2026 Mimer Information Technology
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in all
11
+ // copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ // SOFTWARE.
20
+ //
21
+ // See license for more details.
22
+
23
+ 'use strict';
24
+
25
+ const fs = require('fs');
26
+ const path = require('path');
27
+
28
+ /**
29
+ * Find the Mimer SQL shared library path for the current platform.
30
+ * Returns the path (or library name for ld search) to load with koffi.load().
31
+ */
32
+ function findMimerLibrary() {
33
+ switch (process.platform) {
34
+ case 'linux':
35
+ return 'libmimerapi.so';
36
+
37
+ case 'darwin':
38
+ return '/usr/local/lib/libmimerapi.dylib';
39
+
40
+ case 'win32':
41
+ return findMimerWindows();
42
+
43
+ default:
44
+ throw new Error(`Unsupported platform: ${process.platform}`);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Find mimapi64.dll on Windows.
50
+ * Search order: MIMER_HOME → Registry → Program Files scan → defaults.
51
+ */
52
+ function findMimerWindows() {
53
+ // Helper to check if a directory contains the Mimer DLL
54
+ function hasDll(dir) {
55
+ if (!dir) return false;
56
+ const dllPath = path.join(dir, 'lib', 'mimapi64.dll');
57
+ return fs.existsSync(dllPath) ? dllPath : null;
58
+ }
59
+
60
+ // Try 1: MIMER_HOME environment variable
61
+ if (process.env.MIMER_HOME) {
62
+ const dll = hasDll(process.env.MIMER_HOME);
63
+ if (dll) return dll;
64
+ }
65
+
66
+ // Try 2: Windows Registry
67
+ try {
68
+ const { execSync } = require('child_process');
69
+ const regEnum = 'reg query "HKLM\\SOFTWARE\\Mimer\\Mimer SQL" 2>nul';
70
+ const output = execSync(regEnum, { encoding: 'utf8' });
71
+
72
+ const registryVersions = [];
73
+ for (const line of output.split('\n')) {
74
+ const versionMatch = line.match(/Mimer SQL\\(\d+\.\d+)\s*$/);
75
+ if (versionMatch) {
76
+ const version = versionMatch[1];
77
+ try {
78
+ const pathQuery = `reg query "HKLM\\SOFTWARE\\Mimer\\Mimer SQL\\${version}" /v PathName 2>nul`;
79
+ const pathOutput = execSync(pathQuery, { encoding: 'utf8' });
80
+ const pathMatch = pathOutput.match(/PathName\s+REG_SZ\s+(.+)/);
81
+ if (pathMatch && pathMatch[1]) {
82
+ const mimerPath = pathMatch[1].trim();
83
+ const dll = hasDll(mimerPath);
84
+ if (dll) {
85
+ registryVersions.push({ version, path: dll });
86
+ }
87
+ }
88
+ } catch (_) { /* skip */ }
89
+ }
90
+ }
91
+
92
+ if (registryVersions.length > 0) {
93
+ registryVersions.sort((a, b) => {
94
+ const va = a.version.split('.').map(Number);
95
+ const vb = b.version.split('.').map(Number);
96
+ if (va[0] !== vb[0]) return vb[0] - va[0];
97
+ return vb[1] - va[1];
98
+ });
99
+ return registryVersions[0].path;
100
+ }
101
+ } catch (_) { /* registry not available */ }
102
+
103
+ // Try 3: Program Files scan
104
+ const programFiles = [
105
+ process.env.ProgramFiles,
106
+ process.env['ProgramFiles(x86)'],
107
+ ].filter(Boolean);
108
+
109
+ const foundPaths = [];
110
+ for (const pf of programFiles) {
111
+ if (!fs.existsSync(pf)) continue;
112
+ try {
113
+ const entries = fs.readdirSync(pf, { withFileTypes: true });
114
+ for (const entry of entries) {
115
+ if (entry.isDirectory() && entry.name.startsWith('Mimer SQL Experience')) {
116
+ const fullPath = path.join(pf, entry.name);
117
+ const dll = hasDll(fullPath);
118
+ if (dll) {
119
+ foundPaths.push({
120
+ path: dll,
121
+ version: entry.name.match(/(\d+\.\d+)/)?.[1] || '0.0',
122
+ });
123
+ }
124
+ }
125
+ }
126
+ } catch (_) { /* permission error */ }
127
+ }
128
+
129
+ if (foundPaths.length > 0) {
130
+ foundPaths.sort((a, b) => {
131
+ const va = a.version.split('.').map(Number);
132
+ const vb = b.version.split('.').map(Number);
133
+ if (va[0] !== vb[0]) return vb[0] - va[0];
134
+ return vb[1] - va[1];
135
+ });
136
+ return foundPaths[0].path;
137
+ }
138
+
139
+ // Try 4: Default locations
140
+ const defaultPaths = [
141
+ 'C:\\Program Files\\Mimer SQL Experience 12.0',
142
+ 'C:\\Program Files\\Mimer SQL Experience 11.0',
143
+ ];
144
+ for (const dp of defaultPaths) {
145
+ const dll = hasDll(dp);
146
+ if (dll) return dll;
147
+ }
148
+
149
+ throw new Error(
150
+ 'Mimer SQL library not found. Please install Mimer SQL or set MIMER_HOME.'
151
+ );
152
+ }
153
+
154
+ module.exports = findMimerLibrary;