@aws-amplify/datastore-storage-adapter 1.2.13 → 1.2.14-unstable.1

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.
Files changed (77) hide show
  1. package/ExpoSQLiteAdapter/index.js +7 -0
  2. package/SQLiteAdapter/index.js +7 -0
  3. package/dist/aws-amplify-datastore-sqlite-adapter-expo.js +2502 -0
  4. package/dist/aws-amplify-datastore-sqlite-adapter-expo.js.map +1 -0
  5. package/dist/aws-amplify-datastore-sqlite-adapter-expo.min.js +2 -0
  6. package/dist/aws-amplify-datastore-sqlite-adapter-expo.min.js.map +1 -0
  7. package/dist/aws-amplify-datastore-storage-adapter.js +1179 -1151
  8. package/dist/aws-amplify-datastore-storage-adapter.js.map +1 -1
  9. package/dist/aws-amplify-datastore-storage-adapter.min.js +1 -1
  10. package/dist/aws-amplify-datastore-storage-adapter.min.js.map +1 -1
  11. package/lib/ExpoSQLiteAdapter/ExpoSQLiteAdapter.d.ts +3 -0
  12. package/lib/ExpoSQLiteAdapter/ExpoSQLiteAdapter.js +10 -0
  13. package/lib/ExpoSQLiteAdapter/ExpoSQLiteAdapter.js.map +1 -0
  14. package/lib/ExpoSQLiteAdapter/ExpoSQLiteDatabase.d.ts +17 -0
  15. package/lib/ExpoSQLiteAdapter/ExpoSQLiteDatabase.js +362 -0
  16. package/lib/ExpoSQLiteAdapter/ExpoSQLiteDatabase.js.map +1 -0
  17. package/lib/SQLiteAdapter/SQLiteAdapter.d.ts +3 -23
  18. package/lib/SQLiteAdapter/SQLiteAdapter.js +3 -582
  19. package/lib/SQLiteAdapter/SQLiteAdapter.js.map +1 -1
  20. package/lib/SQLiteAdapter/SQLiteDatabase.d.ts +8 -8
  21. package/lib/SQLiteAdapter/SQLiteDatabase.js +46 -42
  22. package/lib/SQLiteAdapter/SQLiteDatabase.js.map +1 -1
  23. package/lib/common/CommonSQLiteAdapter.d.ts +23 -0
  24. package/lib/common/CommonSQLiteAdapter.js +579 -0
  25. package/lib/common/CommonSQLiteAdapter.js.map +1 -0
  26. package/lib/{SQLiteAdapter → common}/SQLiteUtils.d.ts +3 -2
  27. package/lib/{SQLiteAdapter → common}/SQLiteUtils.js +26 -2
  28. package/lib/common/SQLiteUtils.js.map +1 -0
  29. package/lib/common/constants.d.ts +1 -0
  30. package/lib/common/constants.js +4 -0
  31. package/lib/common/constants.js.map +1 -0
  32. package/lib/common/types.d.ts +13 -0
  33. package/lib/common/types.js +3 -0
  34. package/lib/common/types.js.map +1 -0
  35. package/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteAdapter.d.ts +3 -0
  36. package/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteAdapter.js +5 -0
  37. package/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteAdapter.js.map +1 -0
  38. package/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteDatabase.d.ts +17 -0
  39. package/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteDatabase.js +360 -0
  40. package/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteDatabase.js.map +1 -0
  41. package/lib-esm/SQLiteAdapter/SQLiteAdapter.d.ts +3 -23
  42. package/lib-esm/SQLiteAdapter/SQLiteAdapter.js +3 -582
  43. package/lib-esm/SQLiteAdapter/SQLiteAdapter.js.map +1 -1
  44. package/lib-esm/SQLiteAdapter/SQLiteDatabase.d.ts +8 -8
  45. package/lib-esm/SQLiteAdapter/SQLiteDatabase.js +46 -42
  46. package/lib-esm/SQLiteAdapter/SQLiteDatabase.js.map +1 -1
  47. package/lib-esm/common/CommonSQLiteAdapter.d.ts +23 -0
  48. package/lib-esm/common/CommonSQLiteAdapter.js +577 -0
  49. package/lib-esm/common/CommonSQLiteAdapter.js.map +1 -0
  50. package/lib-esm/{SQLiteAdapter → common}/SQLiteUtils.d.ts +3 -2
  51. package/lib-esm/{SQLiteAdapter → common}/SQLiteUtils.js +24 -1
  52. package/lib-esm/common/SQLiteUtils.js.map +1 -0
  53. package/lib-esm/common/constants.d.ts +1 -0
  54. package/lib-esm/common/constants.js +2 -0
  55. package/lib-esm/common/constants.js.map +1 -0
  56. package/lib-esm/common/types.d.ts +13 -0
  57. package/lib-esm/common/types.js +1 -0
  58. package/lib-esm/common/types.js.map +1 -0
  59. package/package.json +7 -4
  60. package/src/ExpoSQLiteAdapter/ExpoSQLiteAdapter.ts +8 -0
  61. package/src/ExpoSQLiteAdapter/ExpoSQLiteDatabase.ts +282 -0
  62. package/src/SQLiteAdapter/SQLiteAdapter.ts +5 -475
  63. package/src/SQLiteAdapter/SQLiteDatabase.ts +49 -53
  64. package/src/common/CommonSQLiteAdapter.ts +478 -0
  65. package/src/{SQLiteAdapter → common}/SQLiteUtils.ts +32 -3
  66. package/src/common/constants.ts +1 -0
  67. package/src/common/types.ts +29 -0
  68. package/webpack.config.dev.js +2 -0
  69. package/lib/SQLiteAdapter/SQLiteUtils.js.map +0 -1
  70. package/lib/SQLiteAdapter/types.d.ts +0 -2
  71. package/lib/SQLiteAdapter/types.js +0 -28
  72. package/lib/SQLiteAdapter/types.js.map +0 -1
  73. package/lib-esm/SQLiteAdapter/SQLiteUtils.js.map +0 -1
  74. package/lib-esm/SQLiteAdapter/types.d.ts +0 -2
  75. package/lib-esm/SQLiteAdapter/types.js +0 -25
  76. package/lib-esm/SQLiteAdapter/types.js.map +0 -1
  77. package/src/SQLiteAdapter/types.ts +0 -31
@@ -1,478 +1,8 @@
1
- import { ConsoleLogger as Logger } from '@aws-amplify/core';
1
+ import { CommonSQLiteAdapter } from '../common/CommonSQLiteAdapter';
2
2
  import SQLiteDatabase from './SQLiteDatabase';
3
- import {
4
- generateSchemaStatements,
5
- queryByIdStatement,
6
- modelUpdateStatement,
7
- modelInsertStatement,
8
- queryAllStatement,
9
- queryOneStatement,
10
- deleteByIdStatement,
11
- deleteByPredicateStatement,
12
- ParameterizedStatement,
13
- } from './SQLiteUtils';
14
3
 
15
- import {
16
- StorageAdapter,
17
- ModelInstanceCreator,
18
- ModelPredicateCreator,
19
- ModelSortPredicateCreator,
20
- InternalSchema,
21
- isPredicateObj,
22
- ModelInstanceMetadata,
23
- ModelPredicate,
24
- NamespaceResolver,
25
- OpType,
26
- PaginationInput,
27
- PersistentModel,
28
- PersistentModelConstructor,
29
- PredicateObject,
30
- PredicatesGroup,
31
- QueryOne,
32
- utils,
33
- } from '@aws-amplify/datastore';
4
+ const SQLiteAdapter: CommonSQLiteAdapter = new CommonSQLiteAdapter(
5
+ new SQLiteDatabase()
6
+ );
34
7
 
35
- const { traverseModel, validatePredicate, isModelConstructor } = utils;
36
-
37
- const logger = new Logger('DataStore');
38
- export class SQLiteAdapter implements StorageAdapter {
39
- private schema: InternalSchema;
40
- private namespaceResolver: NamespaceResolver;
41
- private modelInstanceCreator: ModelInstanceCreator;
42
- private getModelConstructorByModelName: (
43
- namsespaceName: string,
44
- modelName: string
45
- ) => PersistentModelConstructor<any>;
46
- private db: SQLiteDatabase;
47
- private initPromise: Promise<void>;
48
- private resolve: (value?: any) => void;
49
- private reject: (value?: any) => void;
50
-
51
- public async setUp(
52
- theSchema: InternalSchema,
53
- namespaceResolver: NamespaceResolver,
54
- modelInstanceCreator: ModelInstanceCreator,
55
- getModelConstructorByModelName: (
56
- namsespaceName: string,
57
- modelName: string
58
- ) => PersistentModelConstructor<any>
59
- ) {
60
- if (!this.initPromise) {
61
- this.initPromise = new Promise((res, rej) => {
62
- this.resolve = res;
63
- this.reject = rej;
64
- });
65
- } else {
66
- await this.initPromise;
67
- return;
68
- }
69
- this.schema = theSchema;
70
- this.namespaceResolver = namespaceResolver;
71
- this.modelInstanceCreator = modelInstanceCreator;
72
- this.getModelConstructorByModelName = getModelConstructorByModelName;
73
-
74
- try {
75
- if (!this.db) {
76
- this.db = new SQLiteDatabase();
77
- await this.db.init();
78
-
79
- const statements = generateSchemaStatements(this.schema);
80
- await this.db.createSchema(statements);
81
- this.resolve();
82
- }
83
- } catch (error) {
84
- this.reject(error);
85
- }
86
- }
87
-
88
- async clear(): Promise<void> {
89
- await this.db.clear();
90
-
91
- this.db = undefined;
92
- this.initPromise = undefined;
93
- }
94
-
95
- async save<T extends PersistentModel>(
96
- model: T,
97
- condition?: ModelPredicate<T>
98
- ): Promise<[T, OpType.INSERT | OpType.UPDATE][]> {
99
- const modelConstructor = Object.getPrototypeOf(model)
100
- .constructor as PersistentModelConstructor<T>;
101
- const { name: tableName } = modelConstructor;
102
- const connectedModels = traverseModel(
103
- modelConstructor.name,
104
- model,
105
- this.schema.namespaces[this.namespaceResolver(modelConstructor)],
106
- this.modelInstanceCreator,
107
- this.getModelConstructorByModelName
108
- );
109
-
110
- const connectionStoreNames = Object.values(connectedModels).map(
111
- ({ modelName, item, instance }) => {
112
- return { modelName, item, instance };
113
- }
114
- );
115
-
116
- const [queryStatement, params] = queryByIdStatement(model.id, tableName);
117
-
118
- const fromDB = await this.db.get(queryStatement, params);
119
-
120
- if (condition && fromDB) {
121
- const predicates = ModelPredicateCreator.getPredicates(condition);
122
- const { predicates: predicateObjs, type } = predicates;
123
-
124
- const isValid = validatePredicate(fromDB, type, predicateObjs);
125
-
126
- if (!isValid) {
127
- const msg = 'Conditional update failed';
128
- logger.error(msg, { model: fromDB, condition: predicateObjs });
129
-
130
- throw new Error(msg);
131
- }
132
- }
133
-
134
- const result: [T, OpType.INSERT | OpType.UPDATE][] = [];
135
- const saveStatements = new Set<ParameterizedStatement>();
136
-
137
- for await (const resItem of connectionStoreNames) {
138
- const { modelName, item, instance } = resItem;
139
- const { id } = item;
140
-
141
- const [queryStatement, params] = queryByIdStatement(id, modelName);
142
- const fromDB = await this.db.get(queryStatement, params);
143
-
144
- const opType: OpType =
145
- fromDB === undefined ? OpType.INSERT : OpType.UPDATE;
146
-
147
- const saveStatement = fromDB
148
- ? modelUpdateStatement(instance, modelName)
149
- : modelInsertStatement(instance, modelName);
150
-
151
- if (id === model.id || opType === OpType.INSERT) {
152
- saveStatements.add(saveStatement);
153
- result.push([instance, opType]);
154
- }
155
- }
156
-
157
- await this.db.batchSave(saveStatements);
158
- return result;
159
- }
160
-
161
- private async load<T>(
162
- namespaceName: string,
163
- srcModelName: string,
164
- records: T[]
165
- ): Promise<T[]> {
166
- const namespace = this.schema.namespaces[namespaceName];
167
- const relations = namespace.relationships[srcModelName].relationTypes;
168
- const connectionTableNames = relations.map(({ modelName }) => modelName);
169
-
170
- const modelConstructor = this.getModelConstructorByModelName(
171
- namespaceName,
172
- srcModelName
173
- );
174
-
175
- if (connectionTableNames.length === 0) {
176
- return records.map(record =>
177
- this.modelInstanceCreator(modelConstructor, record)
178
- );
179
- }
180
-
181
- for await (const relation of relations) {
182
- const {
183
- fieldName,
184
- modelName: tableName,
185
- targetName,
186
- relationType,
187
- } = relation;
188
-
189
- const modelConstructor = this.getModelConstructorByModelName(
190
- namespaceName,
191
- tableName
192
- );
193
-
194
- // TODO: use SQL JOIN instead
195
- switch (relationType) {
196
- case 'HAS_ONE':
197
- for await (const recordItem of records) {
198
- const getByfield = recordItem[targetName] ? targetName : fieldName;
199
- if (!recordItem[getByfield]) break;
200
-
201
- const [queryStatement, params] = queryByIdStatement(
202
- recordItem[getByfield],
203
- tableName
204
- );
205
-
206
- const connectionRecord = await this.db.get(queryStatement, params);
207
-
208
- recordItem[fieldName] =
209
- connectionRecord &&
210
- this.modelInstanceCreator(modelConstructor, connectionRecord);
211
- }
212
-
213
- break;
214
- case 'BELONGS_TO':
215
- for await (const recordItem of records) {
216
- if (recordItem[targetName]) {
217
- const [queryStatement, params] = queryByIdStatement(
218
- recordItem[targetName],
219
- tableName
220
- );
221
- const connectionRecord = await this.db.get(
222
- queryStatement,
223
- params
224
- );
225
-
226
- recordItem[fieldName] =
227
- connectionRecord &&
228
- this.modelInstanceCreator(modelConstructor, connectionRecord);
229
- delete recordItem[targetName];
230
- }
231
- }
232
-
233
- break;
234
- case 'HAS_MANY':
235
- // TODO: Lazy loading
236
- break;
237
- default:
238
- const _: never = relationType as never;
239
- throw new Error(`invalid relation type ${relationType}`);
240
- break;
241
- }
242
- }
243
-
244
- return records.map(record =>
245
- this.modelInstanceCreator(modelConstructor, record)
246
- );
247
- }
248
-
249
- async query<T extends PersistentModel>(
250
- modelConstructor: PersistentModelConstructor<T>,
251
- predicate?: ModelPredicate<T>,
252
- pagination?: PaginationInput<T>
253
- ): Promise<T[]> {
254
- const { name: tableName } = modelConstructor;
255
- const namespaceName = this.namespaceResolver(modelConstructor);
256
-
257
- const predicates =
258
- predicate && ModelPredicateCreator.getPredicates(predicate);
259
- const sortPredicates =
260
- pagination &&
261
- pagination.sort &&
262
- ModelSortPredicateCreator.getPredicates(pagination.sort);
263
- const limit = pagination && pagination.limit;
264
- const page = limit && pagination.page;
265
-
266
- const queryById = predicates && this.idFromPredicate(predicates);
267
-
268
- const records: T[] = <T[]>await (async () => {
269
- if (queryById) {
270
- const record = await this.getById(tableName, queryById);
271
- return record ? [record] : [];
272
- }
273
-
274
- const [queryStatement, params] = queryAllStatement(
275
- tableName,
276
- predicates,
277
- sortPredicates,
278
- limit,
279
- page
280
- );
281
-
282
- return await this.db.getAll(queryStatement, params);
283
- })();
284
-
285
- return await this.load(namespaceName, modelConstructor.name, records);
286
- }
287
-
288
- private async getById<T extends PersistentModel>(
289
- tableName: string,
290
- id: string
291
- ): Promise<T> {
292
- const [queryStatement, params] = queryByIdStatement(id, tableName);
293
- const record = await this.db.get<T>(queryStatement, params);
294
- return record;
295
- }
296
-
297
- private idFromPredicate<T extends PersistentModel>(
298
- predicates: PredicatesGroup<T>
299
- ) {
300
- const { predicates: predicateObjs } = predicates;
301
- const idPredicate =
302
- predicateObjs.length === 1 &&
303
- (predicateObjs.find(
304
- p => isPredicateObj(p) && p.field === 'id' && p.operator === 'eq'
305
- ) as PredicateObject<T>);
306
-
307
- return idPredicate && idPredicate.operand;
308
- }
309
-
310
- async queryOne<T extends PersistentModel>(
311
- modelConstructor: PersistentModelConstructor<T>,
312
- firstOrLast: QueryOne = QueryOne.FIRST
313
- ): Promise<T | undefined> {
314
- const { name: tableName } = modelConstructor;
315
- const [queryStatement, params] = queryOneStatement(firstOrLast, tableName);
316
-
317
- const result = await this.db.get<T>(queryStatement, params);
318
-
319
- const modelInstance =
320
- result && this.modelInstanceCreator(modelConstructor, result);
321
-
322
- return modelInstance;
323
- }
324
-
325
- // Currently does not cascade
326
- // TODO: use FKs in relations and have `ON DELETE CASCADE` set
327
- // For Has Many and Has One relations to have SQL handle cascades automatically
328
- async delete<T extends PersistentModel>(
329
- modelOrModelConstructor: T | PersistentModelConstructor<T>,
330
- condition?: ModelPredicate<T>
331
- ): Promise<[T[], T[]]> {
332
- if (isModelConstructor(modelOrModelConstructor)) {
333
- const modelConstructor = modelOrModelConstructor;
334
- const namespaceName = this.namespaceResolver(modelConstructor);
335
- const { name: tableName } = modelConstructor;
336
-
337
- const predicates =
338
- condition && ModelPredicateCreator.getPredicates(condition);
339
-
340
- const queryStatement = queryAllStatement(tableName, predicates);
341
- const deleteStatement = deleteByPredicateStatement(tableName, predicates);
342
-
343
- const models = await this.db.selectAndDelete(
344
- queryStatement,
345
- deleteStatement
346
- );
347
-
348
- const modelInstances = await this.load(
349
- namespaceName,
350
- modelConstructor.name,
351
- models
352
- );
353
-
354
- return [modelInstances, modelInstances];
355
- } else {
356
- const model = modelOrModelConstructor as T;
357
- const modelConstructor = Object.getPrototypeOf(model)
358
- .constructor as PersistentModelConstructor<T>;
359
- const { name: tableName } = modelConstructor;
360
-
361
- if (condition) {
362
- const [queryStatement, params] = queryByIdStatement(
363
- model.id,
364
- tableName
365
- );
366
-
367
- const fromDB = await this.db.get(queryStatement, params);
368
-
369
- if (fromDB === undefined) {
370
- const msg = 'Model instance not found in storage';
371
- logger.warn(msg, { model });
372
-
373
- return [[model], []];
374
- }
375
-
376
- const predicates = ModelPredicateCreator.getPredicates(condition);
377
- const { predicates: predicateObjs, type } = predicates;
378
-
379
- const isValid = validatePredicate(fromDB, type, predicateObjs);
380
-
381
- if (!isValid) {
382
- const msg = 'Conditional update failed';
383
- logger.error(msg, { model: fromDB, condition: predicateObjs });
384
-
385
- throw new Error(msg);
386
- }
387
-
388
- const [deleteStatement, deleteParams] = deleteByIdStatement(
389
- model.id,
390
- tableName
391
- );
392
- await this.db.save(deleteStatement, deleteParams);
393
- return [[model], [model]];
394
- } else {
395
- const [deleteStatement, params] = deleteByIdStatement(
396
- model.id,
397
- tableName
398
- );
399
- await this.db.save(deleteStatement, params);
400
- return [[model], [model]];
401
- }
402
- }
403
- }
404
-
405
- async batchSave<T extends PersistentModel>(
406
- modelConstructor: PersistentModelConstructor<any>,
407
- items: ModelInstanceMetadata[]
408
- ): Promise<[T, OpType][]> {
409
- const { name: tableName } = modelConstructor;
410
-
411
- const result: [T, OpType][] = [];
412
-
413
- const itemsToSave: T[] = [];
414
- // To determine whether an item should result in an insert or update operation
415
- // We first need to query the local DB on the item id
416
- const queryStatements = new Set<ParameterizedStatement>();
417
- // Deletes don't need to be queried first, because if the item doesn't exist,
418
- // the delete operation will be a no-op
419
- const deleteStatements = new Set<ParameterizedStatement>();
420
- const saveStatements = new Set<ParameterizedStatement>();
421
-
422
- for (const item of items) {
423
- const connectedModels = traverseModel(
424
- modelConstructor.name,
425
- this.modelInstanceCreator(modelConstructor, item),
426
- this.schema.namespaces[this.namespaceResolver(modelConstructor)],
427
- this.modelInstanceCreator,
428
- this.getModelConstructorByModelName
429
- );
430
-
431
- const { id, _deleted } = item;
432
-
433
- const { instance } = connectedModels.find(
434
- ({ instance }) => instance.id === id
435
- );
436
-
437
- if (_deleted) {
438
- // create the delete statements right away
439
- const deleteStatement = deleteByIdStatement(instance.id, tableName);
440
- deleteStatements.add(deleteStatement);
441
- result.push([<T>(<unknown>item), OpType.DELETE]);
442
- } else {
443
- // query statements for the saves at first
444
- const queryStatement = queryByIdStatement(id, tableName);
445
- queryStatements.add(queryStatement);
446
- // combination of insert and update items
447
- itemsToSave.push(instance);
448
- }
449
- }
450
-
451
- // returns the query results for each of the save items
452
- const queryResponses = await this.db.batchQuery(queryStatements);
453
-
454
- queryResponses.forEach((response, idx) => {
455
- if (response === undefined) {
456
- const insertStatement = modelInsertStatement(
457
- itemsToSave[idx],
458
- tableName
459
- );
460
- saveStatements.add(insertStatement);
461
- result.push([<T>(<unknown>itemsToSave[idx]), OpType.INSERT]);
462
- } else {
463
- const updateStatement = modelUpdateStatement(
464
- itemsToSave[idx],
465
- tableName
466
- );
467
- saveStatements.add(updateStatement);
468
- result.push([<T>(<unknown>itemsToSave[idx]), OpType.UPDATE]);
469
- }
470
- });
471
-
472
- // perform all of the insert/update/delete operations in a single transaction
473
- await this.db.batchSave(saveStatements, deleteStatements);
474
- return result;
475
- }
476
- }
477
-
478
- export default new SQLiteAdapter();
8
+ export default SQLiteAdapter;
@@ -1,7 +1,8 @@
1
1
  import SQLite from 'react-native-sqlite-storage';
2
2
  import { ConsoleLogger as Logger } from '@aws-amplify/core';
3
3
  import { PersistentModel } from '@aws-amplify/datastore';
4
- import { ParameterizedStatement } from './SQLiteUtils';
4
+ import { DB_NAME } from '../common/constants';
5
+ import { CommonSQLiteDatabase, ParameterizedStatement } from '../common/types';
5
6
 
6
7
  const logger = new Logger('SQLiteDatabase');
7
8
 
@@ -11,13 +12,6 @@ if (Logger.LOG_LEVEL === 'DEBUG') {
11
12
  SQLite.DEBUG(true);
12
13
  }
13
14
 
14
- const DB_NAME = 'AmplifyDatastore';
15
- const DB_DISPLAYNAME = 'AWS Amplify DataStore SQLite Database';
16
-
17
- // TODO: make these configurable
18
- const DB_SIZE = 200000;
19
- const DB_VERSION = '1.0';
20
-
21
15
  /*
22
16
 
23
17
  Note:
@@ -31,47 +25,41 @@ get the result of an `executeSql` command inside of a transaction
31
25
 
32
26
  */
33
27
 
34
- class SQLiteDatabase {
28
+ class SQLiteDatabase implements CommonSQLiteDatabase {
35
29
  private db: SQLite.SQLiteDatabase;
36
30
 
37
31
  public async init(): Promise<void> {
38
- this.db = await SQLite.openDatabase(
39
- DB_NAME,
40
- DB_VERSION,
41
- DB_DISPLAYNAME,
42
- DB_SIZE
43
- );
32
+ // only open database once.
33
+ if (!this.db) {
34
+ this.db = await SQLite.openDatabase({
35
+ name: DB_NAME,
36
+ location: 'default',
37
+ });
38
+ }
44
39
  }
45
40
 
46
- public async createSchema(statements: string[]) {
41
+ public async createSchema(statements: string[]): Promise<void> {
47
42
  return await this.executeStatements(statements);
48
43
  }
49
44
 
50
- public async clear() {
45
+ public async clear(): Promise<void> {
51
46
  await this.closeDB();
52
47
  logger.debug('Deleting database');
53
- await SQLite.deleteDatabase(DB_NAME);
48
+ await SQLite.deleteDatabase({ name: DB_NAME, location: 'default' });
54
49
  logger.debug('Database deleted');
55
50
  }
56
51
 
57
52
  public async get<T extends PersistentModel>(
58
53
  statement: string,
59
- params: any[]
54
+ params: (string | number)[]
60
55
  ): Promise<T> {
61
- const [resultSet] = await this.db.executeSql(statement, params);
62
- const result =
63
- resultSet &&
64
- resultSet.rows &&
65
- resultSet.rows.length &&
66
- resultSet.rows.raw &&
67
- resultSet.rows.raw();
68
-
69
- return result?.[0] || undefined;
56
+ const results: T[] = await this.getAll(statement, params);
57
+ return results[0];
70
58
  }
71
59
 
72
60
  public async getAll<T extends PersistentModel>(
73
61
  statement: string,
74
- params: any[]
62
+ params: (string | number)[]
75
63
  ): Promise<T[]> {
76
64
  const [resultSet] = await this.db.executeSql(statement, params);
77
65
  const result =
@@ -84,19 +72,24 @@ class SQLiteDatabase {
84
72
  return result || [];
85
73
  }
86
74
 
87
- public async save(statement: string, params: any[]): Promise<void> {
75
+ public async save(
76
+ statement: string,
77
+ params: (string | number)[]
78
+ ): Promise<void> {
88
79
  await this.db.executeSql(statement, params);
89
80
  }
90
81
 
91
- public async batchQuery(queryStatements: Set<ParameterizedStatement>) {
82
+ public async batchQuery<T = any>(
83
+ queryParameterizedStatements: Set<ParameterizedStatement>
84
+ ): Promise<T[]> {
92
85
  const results = [];
93
86
 
94
- await this.db.readTransaction(function (tx) {
95
- for (const [statement, params] of queryStatements) {
87
+ await this.db.readTransaction(tx => {
88
+ for (const [statement, params] of queryParameterizedStatements) {
96
89
  tx.executeSql(
97
90
  statement,
98
91
  params,
99
- function (_tx, res) {
92
+ (_, res) => {
100
93
  results.push(res.rows.raw()[0]);
101
94
  },
102
95
  logger.warn
@@ -108,35 +101,37 @@ class SQLiteDatabase {
108
101
  }
109
102
 
110
103
  public async batchSave(
111
- saveStatements: Set<ParameterizedStatement>,
112
- deleteStatements?: Set<ParameterizedStatement>
113
- ) {
114
- await this.db.transaction(function (tx) {
115
- for (const [statement, params] of saveStatements) {
104
+ saveParameterizedStatements: Set<ParameterizedStatement>,
105
+ deleteParameterizedStatements?: Set<ParameterizedStatement>
106
+ ): Promise<void> {
107
+ await this.db.transaction(tx => {
108
+ for (const [statement, params] of saveParameterizedStatements) {
116
109
  tx.executeSql(statement, params);
117
110
  }
118
- if (deleteStatements) {
119
- for (const [statement, params] of deleteStatements) {
111
+ });
112
+ if (deleteParameterizedStatements) {
113
+ await this.db.transaction(tx => {
114
+ for (const [statement, params] of deleteParameterizedStatements) {
120
115
  tx.executeSql(statement, params);
121
116
  }
122
- }
123
- });
117
+ });
118
+ }
124
119
  }
125
120
 
126
- public async selectAndDelete(
127
- query: ParameterizedStatement,
128
- _delete: ParameterizedStatement
129
- ) {
130
- let results = [];
121
+ public async selectAndDelete<T = any>(
122
+ queryParameterizedStatement: ParameterizedStatement,
123
+ deleteParameterizedStatement: ParameterizedStatement
124
+ ): Promise<T[]> {
125
+ let results: T[] = [];
131
126
 
132
- const [queryStatement, queryParams] = query;
133
- const [deleteStatement, deleteParams] = _delete;
127
+ const [queryStatement, queryParams] = queryParameterizedStatement;
128
+ const [deleteStatement, deleteParams] = deleteParameterizedStatement;
134
129
 
135
- await this.db.transaction(function (tx) {
130
+ await this.db.transaction(tx => {
136
131
  tx.executeSql(
137
132
  queryStatement,
138
133
  queryParams,
139
- function (_tx, res) {
134
+ (_, res) => {
140
135
  results = res.rows.raw();
141
136
  },
142
137
  logger.warn
@@ -148,7 +143,7 @@ class SQLiteDatabase {
148
143
  }
149
144
 
150
145
  private async executeStatements(statements: string[]): Promise<void> {
151
- return await this.db.transaction(function (tx) {
146
+ await this.db.transaction(tx => {
152
147
  for (const statement of statements) {
153
148
  tx.executeSql(statement);
154
149
  }
@@ -160,6 +155,7 @@ class SQLiteDatabase {
160
155
  logger.debug('Closing Database');
161
156
  await this.db.close();
162
157
  logger.debug('Database closed');
158
+ this.db = undefined;
163
159
  }
164
160
  }
165
161
  }