@aws-amplify/datastore-storage-adapter 2.0.71 → 2.0.73

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 (72) hide show
  1. package/.rollup.cache/Volumes/workplace/amplify-js/packages/datastore-storage-adapter/dist/meta/cjs.tsbuildinfo +1 -0
  2. package/CHANGELOG.md +12 -0
  3. package/coverage-ts/assets/source-file.css +21 -0
  4. package/coverage-ts/assets/source-file.js +40 -0
  5. package/coverage-ts/files/lib/ExpoSQLiteAdapter/ExpoSQLiteAdapter.d.ts.html +21 -0
  6. package/coverage-ts/files/lib/ExpoSQLiteAdapter/ExpoSQLiteDatabase.d.ts.html +35 -0
  7. package/coverage-ts/files/lib/SQLiteAdapter/SQLiteAdapter.d.ts.html +21 -0
  8. package/coverage-ts/files/lib/SQLiteAdapter/SQLiteDatabase.d.ts.html +35 -0
  9. package/coverage-ts/files/lib/common/CommonSQLiteAdapter.d.ts.html +41 -0
  10. package/coverage-ts/files/lib/common/SQLiteUtils.d.ts.html +39 -0
  11. package/coverage-ts/files/lib/common/constants.d.ts.html +19 -0
  12. package/coverage-ts/files/lib/common/types.d.ts.html +34 -0
  13. package/coverage-ts/files/lib/index.d.ts.html +20 -0
  14. package/coverage-ts/files/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteAdapter.d.ts.html +21 -0
  15. package/coverage-ts/files/lib-esm/ExpoSQLiteAdapter/ExpoSQLiteDatabase.d.ts.html +35 -0
  16. package/coverage-ts/files/lib-esm/SQLiteAdapter/SQLiteAdapter.d.ts.html +21 -0
  17. package/coverage-ts/files/lib-esm/SQLiteAdapter/SQLiteDatabase.d.ts.html +35 -0
  18. package/coverage-ts/files/lib-esm/common/CommonSQLiteAdapter.d.ts.html +41 -0
  19. package/coverage-ts/files/lib-esm/common/SQLiteUtils.d.ts.html +39 -0
  20. package/coverage-ts/files/lib-esm/common/constants.d.ts.html +19 -0
  21. package/coverage-ts/files/lib-esm/common/types.d.ts.html +34 -0
  22. package/coverage-ts/files/lib-esm/index.d.ts.html +20 -0
  23. package/coverage-ts/files/src/ExpoSQLiteAdapter/ExpoSQLiteAdapter.ts.html +28 -0
  24. package/coverage-ts/files/src/ExpoSQLiteAdapter/ExpoSQLiteDatabase.ts.html +302 -0
  25. package/coverage-ts/files/src/SQLiteAdapter/SQLiteAdapter.ts.html +28 -0
  26. package/coverage-ts/files/src/SQLiteAdapter/SQLiteDatabase.ts.html +183 -0
  27. package/coverage-ts/files/src/common/CommonSQLiteAdapter.ts.html +460 -0
  28. package/coverage-ts/files/src/common/SQLiteUtils.ts.html +520 -0
  29. package/coverage-ts/files/src/common/constants.ts.html +21 -0
  30. package/coverage-ts/files/src/common/types.ts.html +54 -0
  31. package/coverage-ts/files/src/index.ts.html +22 -0
  32. package/coverage-ts/index.html +15 -0
  33. package/coverage-ts/typescript-coverage.json +772 -0
  34. package/dist/aws-amplify-datastore-storage-adapter.js +5 -0
  35. package/dist/aws-amplify-datastore-storage-adapter.js.map +1 -1
  36. package/dist/aws-amplify-datastore-storage-adapter.min.js.map +1 -1
  37. package/lib/SQLiteAdapter/SQLiteAdapter.d.ts +5 -0
  38. package/lib/SQLiteAdapter/SQLiteAdapter.js +5 -0
  39. package/lib/SQLiteAdapter/SQLiteAdapter.js.map +1 -1
  40. package/lib-esm/SQLiteAdapter/SQLiteAdapter.d.ts +5 -0
  41. package/lib-esm/SQLiteAdapter/SQLiteAdapter.js +5 -0
  42. package/lib-esm/SQLiteAdapter/SQLiteAdapter.js.map +1 -1
  43. package/package.json +7 -4
  44. package/src/SQLiteAdapter/SQLiteAdapter.ts +5 -0
  45. package/.rollup.cache/home/runner/work/amplify-js/amplify-js/amplify-js/packages/datastore-storage-adapter/dist/meta/cjs.tsbuildinfo +0 -1
  46. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/ExpoSQLiteAdapter/ExpoSQLiteAdapter.js +0 -0
  47. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/ExpoSQLiteAdapter/ExpoSQLiteDatabase.js +0 -0
  48. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/SQLiteAdapter/SQLiteAdapter.js +0 -0
  49. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/SQLiteAdapter/SQLiteDatabase.js +0 -0
  50. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/common/CommonSQLiteAdapter.js +0 -0
  51. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/common/SQLiteUtils.js +0 -0
  52. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/common/constants.js +0 -0
  53. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/common/types.js +0 -0
  54. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/cjs/index.js +0 -0
  55. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/ExpoSQLiteAdapter/ExpoSQLiteAdapter.d.ts +0 -0
  56. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/ExpoSQLiteAdapter/ExpoSQLiteAdapter.js +0 -0
  57. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/ExpoSQLiteAdapter/ExpoSQLiteDatabase.d.ts +0 -0
  58. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/ExpoSQLiteAdapter/ExpoSQLiteDatabase.js +0 -0
  59. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/SQLiteAdapter/SQLiteAdapter.d.ts +0 -0
  60. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/SQLiteAdapter/SQLiteAdapter.js +0 -0
  61. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/SQLiteAdapter/SQLiteDatabase.d.ts +0 -0
  62. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/SQLiteAdapter/SQLiteDatabase.js +0 -0
  63. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/CommonSQLiteAdapter.d.ts +0 -0
  64. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/CommonSQLiteAdapter.js +0 -0
  65. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/SQLiteUtils.d.ts +0 -0
  66. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/SQLiteUtils.js +0 -0
  67. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/constants.d.ts +0 -0
  68. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/constants.js +0 -0
  69. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/types.d.ts +0 -0
  70. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/common/types.js +0 -0
  71. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/index.d.ts +0 -0
  72. /package/.rollup.cache/{home/runner/work/amplify-js/amplify-js → Volumes/workplace}/amplify-js/packages/datastore-storage-adapter/dist/esm/index.js +0 -0
@@ -0,0 +1,460 @@
1
+
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <title>CommonSQLiteAdapter.ts</title>
6
+ <link href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css" type="text/css" rel="stylesheet">
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.2/codemirror.min.js" type="text/javascript" charset="utf-8"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.2/mode/javascript/javascript.min.js" type="text/javascript" charset="utf-8"></script>
9
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.2/codemirror.min.css" type="text/css" rel="stylesheet">
10
+ <script src="../../../assets/source-file.js" type="text/javascript" charset="utf-8"></script>
11
+ <link href="../../../assets/source-file.css" type="text/css" rel="stylesheet">
12
+ </head>
13
+ <body>
14
+ <div style="margin-top:3em" class="ui container"><h1 class="ui header"><a href="../../../index.html">TypeScript coverage report</a></h1><table style="margin-top:2em" class="ui celled table"><thead class=""><tr class=""><th class="">Filename</th><th class="">Percent</th><th class="">Threshold</th><th class="">Total</th><th class="">Covered</th><th class="">Uncovered</th></tr></thead><tbody class=""><tr class="positive"><td class="">src/common/CommonSQLiteAdapter.ts</td><td class="">96.60%</td><td class="">94.16%</td><td class="">765</td><td class="">739</td><td class="">26</td></tr></tbody></table><textarea id="editor" readonly="" style="margin-top:3em">// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
15
+ // SPDX-License-Identifier: Apache-2.0
16
+ import { ConsoleLogger as Logger } from &#x27;@aws-amplify/core&#x27;;
17
+ import {
18
+ generateSchemaStatements,
19
+ queryByIdStatement,
20
+ modelUpdateStatement,
21
+ modelInsertStatement,
22
+ queryAllStatement,
23
+ queryOneStatement,
24
+ deleteByIdStatement,
25
+ deleteByPredicateStatement,
26
+ } from &#x27;../common/SQLiteUtils&#x27;;
27
+
28
+ import {
29
+ StorageAdapter,
30
+ ModelInstanceCreator,
31
+ ModelPredicateCreator,
32
+ ModelSortPredicateCreator,
33
+ InternalSchema,
34
+ isPredicateObj,
35
+ ModelPredicate,
36
+ NamespaceResolver,
37
+ NAMESPACES,
38
+ OpType,
39
+ PaginationInput,
40
+ PersistentModel,
41
+ PersistentModelConstructor,
42
+ PredicateObject,
43
+ PredicatesGroup,
44
+ QueryOne,
45
+ utils,
46
+ } from &#x27;@aws-amplify/datastore&#x27;;
47
+ import {
48
+ CommonSQLiteDatabase,
49
+ ParameterizedStatement,
50
+ ModelInstanceMetadataWithId,
51
+ } from &#x27;./types&#x27;;
52
+
53
+ const { traverseModel, validatePredicate, isModelConstructor } = utils;
54
+
55
+ const logger = new Logger(&#x27;DataStore&#x27;);
56
+
57
+ export class CommonSQLiteAdapter implements StorageAdapter {
58
+ private schema: InternalSchema;
59
+ private namespaceResolver: NamespaceResolver;
60
+ private modelInstanceCreator: ModelInstanceCreator;
61
+ private getModelConstructorByModelName: (
62
+ namsespaceName: string,
63
+ modelName: string
64
+ ) =&gt; PersistentModelConstructor&lt;any&gt;;
65
+ private db: CommonSQLiteDatabase;
66
+ private initPromise: Promise&lt;void&gt;;
67
+ private resolve: (value?: any) =&gt; void;
68
+ private reject: (value?: any) =&gt; void;
69
+
70
+ constructor(db: CommonSQLiteDatabase) {
71
+ this.db = db;
72
+ }
73
+
74
+ public async setUp(
75
+ theSchema: InternalSchema,
76
+ namespaceResolver: NamespaceResolver,
77
+ modelInstanceCreator: ModelInstanceCreator,
78
+ getModelConstructorByModelName: (
79
+ namsespaceName: NAMESPACES,
80
+ modelName: string
81
+ ) =&gt; PersistentModelConstructor&lt;any&gt;
82
+ ) {
83
+ if (!this.initPromise) {
84
+ this.initPromise = new Promise((res, rej) =&gt; {
85
+ this.resolve = res;
86
+ this.reject = rej;
87
+ });
88
+ } else {
89
+ await this.initPromise;
90
+ return;
91
+ }
92
+ this.schema = theSchema;
93
+ this.namespaceResolver = namespaceResolver;
94
+ this.modelInstanceCreator = modelInstanceCreator;
95
+ this.getModelConstructorByModelName = getModelConstructorByModelName;
96
+
97
+ try {
98
+ const usesCPKCodegen = Object.values(
99
+ this.schema.namespaces.user.models
100
+ ).some(model =&gt;
101
+ Object.values(model.fields).some(field =&gt;
102
+ field.association?.hasOwnProperty(&#x27;targetNames&#x27;)
103
+ )
104
+ );
105
+ if (usesCPKCodegen) {
106
+ logger.error(
107
+ &#x27;The SQLite adapter does not support schemas using custom primary key. Set `graphQLTransformer.respectPrimaryKeyAttributesOnConnectionField in `amplify/cli.json` to false to disable custom primary key. To regenerate your API, add or remove an empty newline to your GraphQL schema (to change the computed hash) then run `amplify push`.&#x27;
108
+ );
109
+ }
110
+ await this.db.init();
111
+ const statements = generateSchemaStatements(this.schema);
112
+ await this.db.createSchema(statements);
113
+
114
+ this.resolve();
115
+ } catch (error) {
116
+ this.reject(error);
117
+ }
118
+ }
119
+
120
+ async clear(): Promise&lt;void&gt; {
121
+ await this.db.clear();
122
+
123
+ this.initPromise = undefined;
124
+ }
125
+
126
+ async save&lt;T extends PersistentModel&gt;(
127
+ model: T,
128
+ condition?: ModelPredicate&lt;T&gt;
129
+ ): Promise&lt;[T, OpType.INSERT | OpType.UPDATE][]&gt; {
130
+ const modelConstructor = Object.getPrototypeOf(model)
131
+ .constructor as PersistentModelConstructor&lt;T&gt;;
132
+ const { name: tableName } = modelConstructor;
133
+ const connectedModels = traverseModel(
134
+ modelConstructor.name,
135
+ model,
136
+ this.schema.namespaces[this.namespaceResolver(modelConstructor)],
137
+ this.modelInstanceCreator,
138
+ this.getModelConstructorByModelName
139
+ );
140
+ const connectionStoreNames = Object.values(connectedModels).map(
141
+ ({ modelName, item, instance }) =&gt; {
142
+ return { modelName, item, instance };
143
+ }
144
+ );
145
+
146
+ const [queryStatement, params] = queryByIdStatement(model.id, tableName);
147
+
148
+ const fromDB = await this.db.get(queryStatement, params);
149
+
150
+ if (condition &amp;&amp; fromDB) {
151
+ const predicates = ModelPredicateCreator.getPredicates(condition);
152
+ const { predicates: predicateObjs, type } = predicates;
153
+
154
+ const isValid = validatePredicate(fromDB, type, predicateObjs);
155
+
156
+ if (!isValid) {
157
+ const msg = &#x27;Conditional update failed&#x27;;
158
+ logger.error(msg, { model: fromDB, condition: predicateObjs });
159
+
160
+ throw new Error(msg);
161
+ }
162
+ }
163
+
164
+ const result: [T, OpType.INSERT | OpType.UPDATE][] = [];
165
+ const saveStatements = new Set&lt;ParameterizedStatement&gt;();
166
+
167
+ for await (const resItem of connectionStoreNames) {
168
+ const { modelName, item, instance } = resItem;
169
+ const { id } = item;
170
+
171
+ const [queryStatement, params] = queryByIdStatement(id, modelName);
172
+ const fromDB = await this.db.get(queryStatement, params);
173
+
174
+ const opType: OpType =
175
+ fromDB === undefined ? OpType.INSERT : OpType.UPDATE;
176
+
177
+ const saveStatement = fromDB
178
+ ? modelUpdateStatement(instance, modelName)
179
+ : modelInsertStatement(instance, modelName);
180
+
181
+ if (id === model.id || opType === OpType.INSERT) {
182
+ saveStatements.add(saveStatement);
183
+ result.push([instance, opType]);
184
+ }
185
+ }
186
+
187
+ await this.db.batchSave(saveStatements);
188
+
189
+ return result;
190
+ }
191
+
192
+ private async load&lt;T&gt;(
193
+ namespaceName: string,
194
+ srcModelName: string,
195
+ records: T[]
196
+ ): Promise&lt;T[]&gt; {
197
+ const namespace = this.schema.namespaces[namespaceName];
198
+ const relations = namespace.relationships[srcModelName].relationTypes;
199
+ const connectionTableNames = relations.map(({ modelName }) =&gt; modelName);
200
+
201
+ const modelConstructor = this.getModelConstructorByModelName(
202
+ namespaceName,
203
+ srcModelName
204
+ );
205
+
206
+ if (connectionTableNames.length === 0) {
207
+ return records.map(record =&gt;
208
+ this.modelInstanceCreator(modelConstructor, record)
209
+ );
210
+ }
211
+
212
+ // Remove related-model fields. They&#x27;re all `null` in the database,
213
+ // and any that happen to be required will result in a false validation
214
+ // error when DataStore attempts to initialize with `null`.
215
+ // These fields aren&#x27;t actually needed here. DataStore will use the FK&#x27;s
216
+ // from the schema model.
217
+ return records.map(record =&gt; {
218
+ for (const r of relations) {
219
+ delete record[r.fieldName];
220
+ }
221
+ return this.modelInstanceCreator(modelConstructor, record);
222
+ });
223
+ }
224
+
225
+ async query&lt;T extends PersistentModel&gt;(
226
+ modelConstructor: PersistentModelConstructor&lt;T&gt;,
227
+ predicate?: ModelPredicate&lt;T&gt;,
228
+ pagination?: PaginationInput&lt;T&gt;
229
+ ): Promise&lt;T[]&gt; {
230
+ const { name: tableName } = modelConstructor;
231
+ const namespaceName = this.namespaceResolver(modelConstructor);
232
+
233
+ const predicates =
234
+ predicate &amp;&amp; ModelPredicateCreator.getPredicates(predicate);
235
+ const sortPredicates =
236
+ pagination &amp;&amp;
237
+ pagination.sort &amp;&amp;
238
+ ModelSortPredicateCreator.getPredicates(pagination.sort);
239
+ const limit = pagination &amp;&amp; pagination.limit;
240
+ const page = limit &amp;&amp; pagination.page;
241
+
242
+ const queryById = predicates &amp;&amp; this.idFromPredicate(predicates);
243
+
244
+ const records: T[] = &lt;T[]&gt;await (async () =&gt; {
245
+ if (queryById) {
246
+ const record = await this.getById(tableName, queryById);
247
+ return record ? [record] : [];
248
+ }
249
+
250
+ const [queryStatement, params] = queryAllStatement(
251
+ tableName,
252
+ predicates,
253
+ sortPredicates,
254
+ limit,
255
+ page
256
+ );
257
+
258
+ return await this.db.getAll(queryStatement, params);
259
+ })();
260
+
261
+ return await this.load(namespaceName, modelConstructor.name, records);
262
+ }
263
+
264
+ private async getById&lt;T extends PersistentModel&gt;(
265
+ tableName: string,
266
+ id: string
267
+ ): Promise&lt;T&gt; {
268
+ const [queryStatement, params] = queryByIdStatement(id, tableName);
269
+ const record = await this.db.get&lt;T&gt;(queryStatement, params);
270
+
271
+ return record;
272
+ }
273
+
274
+ private idFromPredicate&lt;T extends PersistentModel&gt;(
275
+ predicates: PredicatesGroup&lt;T&gt;
276
+ ) {
277
+ const { predicates: predicateObjs } = predicates;
278
+ const idPredicate =
279
+ predicateObjs.length === 1 &amp;&amp;
280
+ (predicateObjs.find(
281
+ p =&gt; isPredicateObj(p) &amp;&amp; p.field === &#x27;id&#x27; &amp;&amp; p.operator === &#x27;eq&#x27;
282
+ ) as PredicateObject&lt;T&gt;);
283
+
284
+ return idPredicate &amp;&amp; idPredicate.operand;
285
+ }
286
+
287
+ async queryOne&lt;T extends PersistentModel&gt;(
288
+ modelConstructor: PersistentModelConstructor&lt;T&gt;,
289
+ firstOrLast: QueryOne = QueryOne.FIRST
290
+ ): Promise&lt;T | undefined&gt; {
291
+ const { name: tableName } = modelConstructor;
292
+ const [queryStatement, params] = queryOneStatement(firstOrLast, tableName);
293
+
294
+ const result = await this.db.get&lt;T&gt;(queryStatement, params);
295
+
296
+ const modelInstance =
297
+ result &amp;&amp; this.modelInstanceCreator(modelConstructor, result);
298
+
299
+ return modelInstance;
300
+ }
301
+
302
+ // Currently does not cascade
303
+ // TODO: use FKs in relations and have `ON DELETE CASCADE` set
304
+ // For Has Many and Has One relations to have SQL handle cascades automatically
305
+ async delete&lt;T extends PersistentModel&gt;(
306
+ modelOrModelConstructor: T | PersistentModelConstructor&lt;T&gt;,
307
+ condition?: ModelPredicate&lt;T&gt;
308
+ ): Promise&lt;[T[], T[]]&gt; {
309
+ if (isModelConstructor(modelOrModelConstructor)) {
310
+ const modelConstructor = modelOrModelConstructor;
311
+ const namespaceName = this.namespaceResolver(modelConstructor);
312
+ const { name: tableName } = modelConstructor;
313
+
314
+ const predicates =
315
+ condition &amp;&amp; ModelPredicateCreator.getPredicates(condition);
316
+
317
+ const queryStatement = queryAllStatement(tableName, predicates);
318
+ const deleteStatement = deleteByPredicateStatement(tableName, predicates);
319
+
320
+ const models = await this.db.selectAndDelete(
321
+ queryStatement,
322
+ deleteStatement
323
+ );
324
+
325
+ const modelInstances = await this.load(
326
+ namespaceName,
327
+ modelConstructor.name,
328
+ models
329
+ );
330
+
331
+ return [modelInstances, modelInstances];
332
+ } else {
333
+ const model = modelOrModelConstructor as T;
334
+ const modelConstructor = Object.getPrototypeOf(model)
335
+ .constructor as PersistentModelConstructor&lt;T&gt;;
336
+ const { name: tableName } = modelConstructor;
337
+
338
+ if (condition) {
339
+ const [queryStatement, params] = queryByIdStatement(
340
+ model.id,
341
+ tableName
342
+ );
343
+
344
+ const fromDB = await this.db.get(queryStatement, params);
345
+
346
+ if (fromDB === undefined) {
347
+ const msg = &#x27;Model instance not found in storage&#x27;;
348
+ logger.warn(msg, { model });
349
+
350
+ return [[model], []];
351
+ }
352
+
353
+ const predicates = ModelPredicateCreator.getPredicates(condition);
354
+ const { predicates: predicateObjs, type } = predicates;
355
+
356
+ const isValid = validatePredicate(fromDB, type, predicateObjs);
357
+
358
+ if (!isValid) {
359
+ const msg = &#x27;Conditional update failed&#x27;;
360
+ logger.error(msg, { model: fromDB, condition: predicateObjs });
361
+
362
+ throw new Error(msg);
363
+ }
364
+
365
+ const [deleteStatement, deleteParams] = deleteByIdStatement(
366
+ model.id,
367
+ tableName
368
+ );
369
+ await this.db.save(deleteStatement, deleteParams);
370
+
371
+ return [[model], [model]];
372
+ } else {
373
+ const [deleteStatement, params] = deleteByIdStatement(
374
+ model.id,
375
+ tableName
376
+ );
377
+ await this.db.save(deleteStatement, params);
378
+
379
+ return [[model], [model]];
380
+ }
381
+ }
382
+ }
383
+
384
+ async batchSave&lt;T extends PersistentModel&gt;(
385
+ modelConstructor: PersistentModelConstructor&lt;any&gt;,
386
+ items: ModelInstanceMetadataWithId[]
387
+ ): Promise&lt;[T, OpType][]&gt; {
388
+ const { name: tableName } = modelConstructor;
389
+ const result: [T, OpType][] = [];
390
+
391
+ const itemsToSave: T[] = [];
392
+ // To determine whether an item should result in an insert or update operation
393
+ // We first need to query the local DB on the item id
394
+ const queryStatements = new Set&lt;ParameterizedStatement&gt;();
395
+ // Deletes don&#x27;t need to be queried first, because if the item doesn&#x27;t exist,
396
+ // the delete operation will be a no-op
397
+ const deleteStatements = new Set&lt;ParameterizedStatement&gt;();
398
+ const saveStatements = new Set&lt;ParameterizedStatement&gt;();
399
+
400
+ for (const item of items) {
401
+ const connectedModels = traverseModel(
402
+ modelConstructor.name,
403
+ this.modelInstanceCreator(modelConstructor, item),
404
+ this.schema.namespaces[this.namespaceResolver(modelConstructor)],
405
+ this.modelInstanceCreator,
406
+ this.getModelConstructorByModelName
407
+ );
408
+
409
+ const { id, _deleted } = item;
410
+
411
+ const { instance } = connectedModels.find(
412
+ ({ instance }) =&gt; instance.id === id
413
+ );
414
+
415
+ if (_deleted) {
416
+ // create the delete statements right away
417
+ const deleteStatement = deleteByIdStatement(instance.id, tableName);
418
+ deleteStatements.add(deleteStatement);
419
+ result.push([&lt;T&gt;(&lt;unknown&gt;item), OpType.DELETE]);
420
+ } else {
421
+ // query statements for the saves at first
422
+ const queryStatement = queryByIdStatement(id, tableName);
423
+ queryStatements.add(queryStatement);
424
+ // combination of insert and update items
425
+ itemsToSave.push(instance);
426
+ }
427
+ }
428
+
429
+ // returns the query results for each of the save items
430
+ const queryResponses = await this.db.batchQuery(queryStatements);
431
+
432
+ queryResponses.forEach((response, idx) =&gt; {
433
+ if (response === undefined) {
434
+ const insertStatement = modelInsertStatement(
435
+ itemsToSave[idx],
436
+ tableName
437
+ );
438
+ saveStatements.add(insertStatement);
439
+ result.push([&lt;T&gt;(&lt;unknown&gt;itemsToSave[idx]), OpType.INSERT]);
440
+ } else {
441
+ const updateStatement = modelUpdateStatement(
442
+ itemsToSave[idx],
443
+ tableName
444
+ );
445
+ saveStatements.add(updateStatement);
446
+ result.push([&lt;T&gt;(&lt;unknown&gt;itemsToSave[idx]), OpType.UPDATE]);
447
+ }
448
+ });
449
+
450
+ // perform all of the insert/update/delete operations in a single transaction
451
+ await this.db.batchSave(saveStatements, deleteStatements);
452
+
453
+ return result;
454
+ }
455
+ }
456
+ </textarea><pre id="annotations" style="display:none">[{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:53,&quot;character&quot;:19,&quot;text&quot;:&quot;value&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:54,&quot;character&quot;:18,&quot;text&quot;:&quot;value&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:102,&quot;character&quot;:15,&quot;text&quot;:&quot;error&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:101,&quot;character&quot;:11,&quot;text&quot;:&quot;error&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:132,&quot;character&quot;:60,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:140,&quot;character&quot;:9,&quot;text&quot;:&quot;isValid&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:142,&quot;character&quot;:8,&quot;text&quot;:&quot;isValid&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:155,&quot;character&quot;:11,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:167,&quot;character&quot;:7,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:167,&quot;character&quot;:20,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:228,&quot;character&quot;:8,&quot;text&quot;:&quot;queryById&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:231,&quot;character&quot;:7,&quot;text&quot;:&quot;queryById&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:270,&quot;character&quot;:36,&quot;text&quot;:&quot;operand&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:326,&quot;character&quot;:11,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:342,&quot;character&quot;:10,&quot;text&quot;:&quot;isValid&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:344,&quot;character&quot;:9,&quot;text&quot;:&quot;isValid&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:352,&quot;character&quot;:11,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:360,&quot;character&quot;:11,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:397,&quot;character&quot;:11,&quot;text&quot;:&quot;instance&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:398,&quot;character&quot;:7,&quot;text&quot;:&quot;instance&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:398,&quot;character&quot;:22,&quot;text&quot;:&quot;instance&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:398,&quot;character&quot;:31,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:403,&quot;character&quot;:48,&quot;text&quot;:&quot;instance&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:403,&quot;character&quot;:57,&quot;text&quot;:&quot;id&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:418,&quot;character&quot;:26,&quot;text&quot;:&quot;response&quot;,&quot;kind&quot;:1},{&quot;file&quot;:&quot;src/common/CommonSQLiteAdapter.ts&quot;,&quot;line&quot;:419,&quot;character&quot;:7,&quot;text&quot;:&quot;response&quot;,&quot;kind&quot;:1}]</pre></div>
457
+ <p class="footer-text">TypeScript Coverage Report generated by <a href="https://github.com/plantain-00/type-coverage">type-coverage</a> and <a href="https://github.com/alexcanessa/typescript-coverage-report">typescript-coverage-report</a> at Mon, 20 Apr 2026 10:42:30 GMT</p>
458
+ </body>
459
+ </html>
460
+