1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.Database = void 0;
|
4 | const Statement_1 = require("./Statement");
|
5 | const migrate_1 = require("./utils/migrate");
|
6 | const strings_1 = require("./utils/strings");
|
7 | const format_error_1 = require("./utils/format-error");
|
8 | /**
|
9 | * Promisified wrapper for the sqlite3#Database interface.
|
10 | */
|
11 | class Database {
|
12 | constructor(config) {
|
13 | this.config = config;
|
14 | this.db = null;
|
15 | }
|
16 | /**
|
17 | * Event handler when verbose mode is enabled.
|
18 | * @see https://github.com/mapbox/node-sqlite3/wiki/Debugging
|
19 | */
|
20 | on(event, listener) {
|
21 | this.db.on(event, listener);
|
22 | }
|
23 | /**
|
24 | * Returns the underlying sqlite3 Database instance
|
25 | */
|
26 | getDatabaseInstance() {
|
27 | return this.db;
|
28 | }
|
29 | /**
|
30 | * Opens the database
|
31 | */
|
32 | open() {
|
33 | return new Promise((resolve, reject) => {
|
34 | let { filename, mode, driver } = this.config;
|
35 | // https://github.com/mapbox/node-sqlite3/wiki/API#new-sqlite3databasefilename-mode-callback
|
36 | if (filename === null || filename === undefined) {
|
37 | throw new Error('sqlite: filename cannot be null / undefined');
|
38 | }
|
39 | if (!driver) {
|
40 | throw new Error('sqlite: driver is not defined');
|
41 | }
|
42 | if (mode) {
|
43 | this.db = new driver(filename, mode, err => {
|
44 | if (err) {
|
45 | return reject((0, format_error_1.formatError)(err));
|
46 | }
|
47 | resolve();
|
48 | });
|
49 | }
|
50 | else {
|
51 | this.db = new driver(filename, err => {
|
52 | if (err) {
|
53 | return reject((0, format_error_1.formatError)(err));
|
54 | }
|
55 | resolve();
|
56 | });
|
57 | }
|
58 | });
|
59 | }
|
60 | /**
|
61 | * Closes the database.
|
62 | */
|
63 | close() {
|
64 | return new Promise((resolve, reject) => {
|
65 | this.db.close(err => {
|
66 | if (err) {
|
67 | return reject((0, format_error_1.formatError)(err));
|
68 | }
|
69 | resolve();
|
70 | });
|
71 | });
|
72 | }
|
73 | /**
|
74 | * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaseconfigureoption-value
|
75 | */
|
76 | configure(option, value) {
|
77 | this.db.configure(option, value);
|
78 | }
|
79 | /**
|
80 | * Runs the SQL query with the specified parameters. It does not retrieve any result data.
|
81 | * The function returns the Database object for which it was called to allow for function chaining.
|
82 | *
|
83 | * @param {string} sql The SQL query to run.
|
84 | *
|
85 | * @param {any} [params, ...] When the SQL statement contains placeholders, you
|
86 | * can pass them in here. They will be bound to the statement before it is
|
87 | * executed. There are three ways of passing bind parameters: directly in
|
88 | * the function's arguments, as an array, and as an object for named
|
89 | * parameters. This automatically sanitizes inputs.
|
90 | *
|
91 | * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaserunsql-param--callback
|
92 | */
|
93 | run(sql, ...params) {
|
94 | return new Promise((resolve, reject) => {
|
95 | const sqlObj = (0, strings_1.toSqlParams)(sql, params);
|
96 | this.db.run(sqlObj.sql, ...sqlObj.params, function (err) {
|
97 | if (err) {
|
98 | return reject((0, format_error_1.formatError)(err));
|
99 | }
|
100 | resolve({
|
101 | stmt: new Statement_1.Statement(this.stmt),
|
102 | lastID: this.lastID,
|
103 | changes: this.changes
|
104 | });
|
105 | });
|
106 | });
|
107 | }
|
108 | /**
|
109 | * Runs the SQL query with the specified parameters and resolves with
|
110 | * with the first result row afterwards. If the result set is empty, returns undefined.
|
111 | *
|
112 | * The property names correspond to the column names of the result set.
|
113 | * It is impossible to access them by column index; the only supported way is by column name.
|
114 | *
|
115 | * @param {string} sql The SQL query to run.
|
116 | *
|
117 | * @param {any} [params, ...] When the SQL statement contains placeholders, you
|
118 | * can pass them in here. They will be bound to the statement before it is
|
119 | * executed. There are three ways of passing bind parameters: directly in
|
120 | * the function's arguments, as an array, and as an object for named
|
121 | * parameters. This automatically sanitizes inputs.
|
122 | *
|
123 | * @see https://github.com/mapbox/node-sqlite3/wiki/API#databasegetsql-param--callback
|
124 | */
|
125 | get(sql, ...params) {
|
126 | return new Promise((resolve, reject) => {
|
127 | const sqlObj = (0, strings_1.toSqlParams)(sql, params);
|
128 | this.db.get(sqlObj.sql, ...sqlObj.params, (err, row) => {
|
129 | if (err) {
|
130 | return reject((0, format_error_1.formatError)(err));
|
131 | }
|
132 | resolve(row);
|
133 | });
|
134 | });
|
135 | }
|
136 | each(sql, ...params) {
|
137 | return new Promise((resolve, reject) => {
|
138 | const callback = params.pop();
|
139 | if (!callback || typeof callback !== 'function') {
|
140 | throw new Error('sqlite: Last param of Database#each() must be a callback function');
|
141 | }
|
142 | if (params.length > 0) {
|
143 | const positional = params.pop();
|
144 | if (typeof positional === 'function') {
|
145 | throw new Error('sqlite: Database#each() should only have a single callback defined. See readme for usage.');
|
146 | }
|
147 | params.push(positional);
|
148 | }
|
149 | const sqlObj = (0, strings_1.toSqlParams)(sql, params);
|
150 | this.db.each(sqlObj.sql, ...sqlObj.params, (err, row) => {
|
151 | if (err) {
|
152 | return callback((0, format_error_1.formatError)(err), null);
|
153 | }
|
154 | callback(null, row);
|
155 | }, (err, count) => {
|
156 | if (err) {
|
157 | return reject((0, format_error_1.formatError)(err));
|
158 | }
|
159 | resolve(count);
|
160 | });
|
161 | });
|
162 | }
|
163 | /**
|
164 | * Runs the SQL query with the specified parameters. The parameters are the same as the
|
165 | * Database#run function, with the following differences:
|
166 | *
|
167 | * If the result set is empty, it will be an empty array, otherwise it will
|
168 | * have an object for each result row which
|
169 | * in turn contains the values of that row, like the Database#get function.
|
170 | *
|
171 | * Note that it first retrieves all result rows and stores them in memory.
|
172 | * For queries that have potentially large result sets, use the Database#each
|
173 | * function to retrieve all rows or Database#prepare followed by multiple
|
174 | * Statement#get calls to retrieve a previously unknown amount of rows.
|
175 | *
|
176 | * @param {string} sql The SQL query to run.
|
177 | *
|
178 | * @param {any} [params, ...] When the SQL statement contains placeholders, you
|
179 | * can pass them in here. They will be bound to the statement before it is
|
180 | * executed. There are three ways of passing bind parameters: directly in
|
181 | * the function's arguments, as an array, and as an object for named
|
182 | * parameters. This automatically sanitizes inputs.
|
183 | *
|
184 | * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaseallsql-param--callback
|
185 | */
|
186 | all(sql, ...params) {
|
187 | return new Promise((resolve, reject) => {
|
188 | const sqlObj = (0, strings_1.toSqlParams)(sql, params);
|
189 | this.db.all(sqlObj.sql, ...sqlObj.params, (err, rows) => {
|
190 | if (err) {
|
191 | return reject((0, format_error_1.formatError)(err));
|
192 | }
|
193 | resolve(rows);
|
194 | });
|
195 | });
|
196 | }
|
197 | /**
|
198 | * Runs all SQL queries in the supplied string. No result rows are retrieved. If a query fails,
|
199 | * no subsequent statements will be executed (wrap it in a transaction if you want all
|
200 | * or none to be executed).
|
201 | *
|
202 | * Note: This function will only execute statements up to the first NULL byte.
|
203 | * Comments are not allowed and will lead to runtime errors.
|
204 | *
|
205 | * @param {string} sql The SQL query to run.
|
206 | * @param {any} [params, ...] Same as the `params` parameter of `all`
|
207 | * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaseexecsql-callback
|
208 | */
|
209 | exec(sql, ...params) {
|
210 | return new Promise((resolve, reject) => {
|
211 | const sqlObj = (0, strings_1.toSqlParams)(sql, params);
|
212 | this.db.exec(sqlObj.sql, err => {
|
213 | if (err) {
|
214 | return reject((0, format_error_1.formatError)(err));
|
215 | }
|
216 | resolve();
|
217 | });
|
218 | });
|
219 | }
|
220 | /**
|
221 | * Prepares the SQL statement and optionally binds the specified parameters.
|
222 | * When bind parameters are supplied, they are bound to the prepared statement.
|
223 | *
|
224 | * @param {string} sql The SQL query to run.
|
225 | * @param {any} [params, ...] When the SQL statement contains placeholders, you
|
226 | * can pass them in here. They will be bound to the statement before it is
|
227 | * executed. There are three ways of passing bind parameters: directly in
|
228 | * the function's arguments, as an array, and as an object for named
|
229 | * parameters. This automatically sanitizes inputs.
|
230 | * @returns Promise<Statement> Statement object
|
231 | */
|
232 | prepare(sql, ...params) {
|
233 | return new Promise((resolve, reject) => {
|
234 | const sqlObj = (0, strings_1.toSqlParams)(sql, params);
|
235 | const stmt = this.db.prepare(sqlObj.sql, ...sqlObj.params, err => {
|
236 | if (err) {
|
237 | return reject(err);
|
238 | }
|
239 | resolve(new Statement_1.Statement(stmt));
|
240 | });
|
241 | });
|
242 | }
|
243 | /**
|
244 | * Loads a compiled SQLite extension into the database connection object.
|
245 | *
|
246 | * @param {string} path Filename of the extension to load
|
247 | */
|
248 | loadExtension(path) {
|
249 | return new Promise((resolve, reject) => {
|
250 | this.db.loadExtension(path, err => {
|
251 | if (err) {
|
252 | return reject((0, format_error_1.formatError)(err));
|
253 | }
|
254 | resolve();
|
255 | });
|
256 | });
|
257 | }
|
258 | /**
|
259 | * Performs a database migration.
|
260 | */
|
261 | async migrate(config) {
|
262 | await (0, migrate_1.migrate)(this, config);
|
263 | }
|
264 | /**
|
265 | * The methods underneath requires creative work to implement. PRs / proposals accepted!
|
266 | */
|
267 | /*
|
268 | * Unsure if serialize can be made into a promise.
|
269 | */
|
270 | serialize() {
|
271 | throw new Error('sqlite: Currently not implemented. Use getDatabaseInstance().serialize() instead.');
|
272 | }
|
273 | /*
|
274 | * Unsure if parallelize can be made into a promise.
|
275 | */
|
276 | parallelize() {
|
277 | throw new Error('sqlite: Currently not implemented. Use getDatabaseInstance().parallelize() instead.');
|
278 | }
|
279 | }
|
280 | exports.Database = Database;
|
281 | //# sourceMappingURL=Database.js.map |
\ | No newline at end of file |