333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
import * as tslib_1 from "tslib";
import { AbstractSqliteDriver } from "../sqlite-abstract/AbstractSqliteDriver";
import { SqljsQueryRunner } from "./SqljsQueryRunner";
import { DriverPackageNotInstalledError } from "../../error/DriverPackageNotInstalledError";
import { DriverOptionNotSetError } from "../../error/DriverOptionNotSetError";
import { PlatformTools } from "../../platform/PlatformTools";
import { OrmUtils } from "../../util/OrmUtils";
var SqljsDriver = /** @class */ (function (_super) {
    tslib_1.__extends(SqljsDriver, _super);
    // -------------------------------------------------------------------------
    // Constructor
    // -------------------------------------------------------------------------
    function SqljsDriver(connection) {
        var _this = _super.call(this, connection) || this;
        // If autoSave is enabled by user, location or autoSaveCallback have to be set
        // because either autoSave saves to location or calls autoSaveCallback.
        if (_this.options.autoSave && !_this.options.location && !_this.options.autoSaveCallback) {
            throw new DriverOptionNotSetError("location or autoSaveCallback");
        }
        // load sql.js package
        _this.loadDependencies();
        return _this;
    }
    // -------------------------------------------------------------------------
    // Public Methods
    // -------------------------------------------------------------------------
    /**
     * Performs connection to the database.
     */
    SqljsDriver.prototype.connect = function () {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _a;
            return tslib_1.__generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this;
                        return [4 /*yield*/, this.createDatabaseConnection()];
                    case 1:
                        _a.databaseConnection = _b.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Closes connection with database.
     */
    SqljsDriver.prototype.disconnect = function () {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                return [2 /*return*/, new Promise(function (ok, fail) {
                        try {
                            _this.queryRunner = undefined;
                            _this.databaseConnection.close();
                            ok();
                        }
                        catch (e) {
                            fail(e);
                        }
                    })];
            });
        });
    };
    /**
     * Creates a query runner used to execute database queries.
     */
    SqljsDriver.prototype.createQueryRunner = function (mode) {
        if (mode === void 0) { mode = "master"; }
        if (!this.queryRunner)
            this.queryRunner = new SqljsQueryRunner(this);
        return this.queryRunner;
    };
    /**
     * Loads a database from a given file (Node.js), local storage key (browser) or array.
     * This will delete the current database!
     */
    SqljsDriver.prototype.load = function (fileNameOrLocalStorageOrData, checkIfFileOrLocalStorageExists) {
        if (checkIfFileOrLocalStorageExists === void 0) { checkIfFileOrLocalStorageExists = true; }
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var database, localStorageContent;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(typeof fileNameOrLocalStorageOrData === "string")) return [3 /*break*/, 8];
                        if (!(PlatformTools.type === "node")) return [3 /*break*/, 1];
                        // Node.js
                        // fileNameOrLocalStorageOrData should be a path to the file
                        if (PlatformTools.fileExist(fileNameOrLocalStorageOrData)) {
                            database = PlatformTools.readFileSync(fileNameOrLocalStorageOrData);
                            return [2 /*return*/, this.createDatabaseConnectionWithImport(database)];
                        }
                        else if (checkIfFileOrLocalStorageExists) {
                            throw new Error("File " + fileNameOrLocalStorageOrData + " does not exist");
                        }
                        else {
                            // File doesn't exist and checkIfFileOrLocalStorageExists is set to false.
                            // Therefore open a database without importing an existing file.
                            // File will be written on first write operation.
                            return [2 /*return*/, this.createDatabaseConnectionWithImport()];
                        }
                        return [3 /*break*/, 7];
                    case 1:
                        localStorageContent = null;
                        if (!this.options.useLocalForage) return [3 /*break*/, 5];
                        if (!window.localforage) return [3 /*break*/, 3];
                        return [4 /*yield*/, window.localforage.getItem(fileNameOrLocalStorageOrData)];
                    case 2:
                        localStorageContent = _a.sent();
                        return [3 /*break*/, 4];
                    case 3: throw new Error("localforage is not defined - please import localforage.js into your site");
                    case 4: return [3 /*break*/, 6];
                    case 5:
                        localStorageContent = PlatformTools.getGlobalVariable().localStorage.getItem(fileNameOrLocalStorageOrData);
                        _a.label = 6;
                    case 6:
                        if (localStorageContent != null) {
                            // localStorage value exists.
                            return [2 /*return*/, this.createDatabaseConnectionWithImport(JSON.parse(localStorageContent))];
                        }
                        else if (checkIfFileOrLocalStorageExists) {
                            throw new Error("File " + fileNameOrLocalStorageOrData + " does not exist");
                        }
                        else {
                            // localStorage value doesn't exist and checkIfFileOrLocalStorageExists is set to false.
                            // Therefore open a database without importing anything.
                            // localStorage value will be written on first write operation.
                            return [2 /*return*/, this.createDatabaseConnectionWithImport()];
                        }
                        _a.label = 7;
                    case 7: return [3 /*break*/, 9];
                    case 8: return [2 /*return*/, this.createDatabaseConnectionWithImport(fileNameOrLocalStorageOrData)];
                    case 9: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Saved the current database to the given file (Node.js), local storage key (browser) or
     * indexedDB key (browser with enabled useLocalForage option).
     * If no location path is given, the location path in the options (if specified) will be used.
     */
    SqljsDriver.prototype.save = function (location) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var path, content, e_1, database, databaseArray;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!location && !this.options.location) {
                            throw new Error("No location is set, specify a location parameter or add the location option to your configuration");
                        }
                        path = "";
                        if (location) {
                            path = location;
                        }
                        else if (this.options.location) {
                            path = this.options.location;
                        }
                        if (!(PlatformTools.type === "node")) return [3 /*break*/, 5];
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 3, , 4]);
                        content = new Buffer(this.databaseConnection.export());
                        return [4 /*yield*/, PlatformTools.writeFile(path, content)];
                    case 2:
                        _a.sent();
                        return [3 /*break*/, 4];
                    case 3:
                        e_1 = _a.sent();
                        throw new Error("Could not save database, error: " + e_1);
                    case 4: return [3 /*break*/, 10];
                    case 5:
                        database = this.databaseConnection.export();
                        databaseArray = [].slice.call(database);
                        if (!this.options.useLocalForage) return [3 /*break*/, 9];
                        if (!window.localforage) return [3 /*break*/, 7];
                        return [4 /*yield*/, window.localforage.setItem(path, JSON.stringify(databaseArray))];
                    case 6:
                        _a.sent();
                        return [3 /*break*/, 8];
                    case 7: throw new Error("localforage is not defined - please import localforage.js into your site");
                    case 8: return [3 /*break*/, 10];
                    case 9:
                        PlatformTools.getGlobalVariable().localStorage.setItem(path, JSON.stringify(databaseArray));
                        _a.label = 10;
                    case 10: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * This gets called by the QueryRunner when a change to the database is made.
     * If a custom autoSaveCallback is specified, it get's called with the database as Uint8Array,
     * otherwise the save method is called which saves it to file (Node.js), local storage (browser)
     * or indexedDB (browser with enabled useLocalForage option).
     */
    SqljsDriver.prototype.autoSave = function () {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!this.options.autoSave) return [3 /*break*/, 4];
                        if (!this.options.autoSaveCallback) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.options.autoSaveCallback(this.export())];
                    case 1:
                        _a.sent();
                        return [3 /*break*/, 4];
                    case 2: return [4 /*yield*/, this.save()];
                    case 3:
                        _a.sent();
                        _a.label = 4;
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Returns the current database as Uint8Array.
     */
    SqljsDriver.prototype.export = function () {
        return this.databaseConnection.export();
    };
    /**
     * Creates generated map of values generated or returned by database after INSERT query.
     */
    SqljsDriver.prototype.createGeneratedMap = function (metadata, insertResult) {
        var _this = this;
        var generatedMap = metadata.generatedColumns.reduce(function (map, generatedColumn) {
            // seems to be the only way to get the inserted id, see https://github.com/kripken/sql.js/issues/77
            if (generatedColumn.isPrimary && generatedColumn.generationStrategy === "increment") {
                var query = "SELECT last_insert_rowid()";
                try {
                    var result = _this.databaseConnection.exec(query);
                    _this.connection.logger.logQuery(query);
                    return OrmUtils.mergeDeep(map, generatedColumn.createValueMap(result[0].values[0][0]));
                }
                catch (e) {
                    _this.connection.logger.logQueryError(e, query, []);
                }
            }
            return map;
        }, {});
        return Object.keys(generatedMap).length > 0 ? generatedMap : undefined;
    };
    // -------------------------------------------------------------------------
    // Protected Methods
    // -------------------------------------------------------------------------
    /**
     * Creates connection with the database.
     * If the location option is set, the database is loaded first.
     */
    SqljsDriver.prototype.createDatabaseConnection = function () {
        if (this.options.location) {
            return this.load(this.options.location, false);
        }
        return this.createDatabaseConnectionWithImport(this.options.database);
    };
    /**
     * Creates connection with an optional database.
     * If database is specified it is loaded, otherwise a new empty database is created.
     */
    SqljsDriver.prototype.createDatabaseConnectionWithImport = function (database) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                if (database && database.length > 0) {
                    this.databaseConnection = new this.sqlite.Database(database);
                }
                else {
                    this.databaseConnection = new this.sqlite.Database();
                }
                // Enable foreign keys for database
                return [2 /*return*/, new Promise(function (ok, fail) {
                        try {
                            _this.databaseConnection.exec("PRAGMA foreign_keys = ON;");
                            ok(_this.databaseConnection);
                        }
                        catch (e) {
                            fail(e);
                        }
                    })];
            });
        });
    };
    /**
     * If driver dependency is not given explicitly, then try to load it via "require".
     */
    SqljsDriver.prototype.loadDependencies = function () {
        if (PlatformTools.type === "browser") {
            this.sqlite = window.SQL;
        }
        else {
            try {
                this.sqlite = PlatformTools.load("sql.js");
            }
            catch (e) {
                throw new DriverPackageNotInstalledError("sql.js", "sql.js");
            }
        }
    };
    return SqljsDriver;
}(AbstractSqliteDriver));
export { SqljsDriver };
 
//# sourceMappingURL=SqljsDriver.js.map