diff --git a/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteAdapter.ts b/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteAdapter.ts index c767ed80981..785e4bc8901 100644 --- a/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteAdapter.ts +++ b/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteAdapter.ts @@ -1,6 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { CommonSQLiteAdapter } from '../common/CommonSQLiteAdapter'; + import ExpoSQLiteDatabase from './ExpoSQLiteDatabase'; const ExpoSQLiteAdapter: CommonSQLiteAdapter = new CommonSQLiteAdapter( diff --git a/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteDatabase.ts b/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteDatabase.ts index b4536b5f838..3cab19acc04 100644 --- a/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteDatabase.ts +++ b/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteDatabase.ts @@ -3,7 +3,8 @@ import { ConsoleLogger } from '@aws-amplify/core'; import { PersistentModel } from '@aws-amplify/datastore'; import { deleteAsync, documentDirectory } from 'expo-file-system'; -import { openDatabase, WebSQLDatabase } from 'expo-sqlite'; +import { WebSQLDatabase, openDatabase } from 'expo-sqlite'; + import { DB_NAME } from '../common/constants'; import { CommonSQLiteDatabase, ParameterizedStatement } from '../common/types'; @@ -11,9 +12,9 @@ const logger = new ConsoleLogger('ExpoSQLiteDatabase'); /* -Note: -ExpoSQLite transaction error callbacks require returning a boolean value to indicate whether the -error was handled or not. Returning a true value indicates the error was handled and does not +Note: +ExpoSQLite transaction error callbacks require returning a boolean value to indicate whether the +error was handled or not. Returning a true value indicates the error was handled and does not rollback the whole transaction. */ @@ -56,6 +57,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { params: (string | number)[], ): Promise { const results: T[] = await this.getAll(statement, params); + return results[0]; } @@ -74,6 +76,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { (_, error) => { reject(error); logger.warn(error); + return true; }, ); @@ -93,6 +96,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { (_, error) => { reject(error); logger.warn(error); + return true; }, ); @@ -101,7 +105,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { } public batchQuery( - queryParameterizedStatements: Set = new Set(), + queryParameterizedStatements = new Set(), ): Promise { return new Promise((resolveTransaction, rejectTransaction) => { this.db.transaction(async transaction => { @@ -119,6 +123,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { (_, error) => { reject(error); logger.warn(error); + return true; }, ); @@ -135,7 +140,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { } public batchSave( - saveParameterizedStatements: Set = new Set(), + saveParameterizedStatements = new Set(), deleteParameterizedStatements?: Set, ): Promise { return new Promise((resolveTransaction, rejectTransaction) => { @@ -155,6 +160,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { (_, error) => { reject(error); logger.warn(error); + return true; }, ); @@ -165,7 +171,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { await Promise.all( [...deleteParameterizedStatements].map( ([statement, params]) => - new Promise((resolve, reject) => + new Promise((resolve, reject) => { transaction.executeSql( statement, params, @@ -175,10 +181,11 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { (_, error) => { reject(error); logger.warn(error); + return true; }, - ), - ), + ); + }), ), ); } @@ -211,6 +218,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { (_, error) => { reject(error); logger.warn(error); + return true; }, ); @@ -225,6 +233,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { (_, error) => { reject(error); logger.warn(error); + return true; }, ); @@ -254,6 +263,7 @@ class ExpoSQLiteDatabase implements CommonSQLiteDatabase { }, (_, error) => { reject(error); + return true; }, ); diff --git a/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteAdapter.ts b/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteAdapter.ts index b84e39ffb47..8d2823f0f05 100644 --- a/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteAdapter.ts +++ b/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteAdapter.ts @@ -1,6 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { CommonSQLiteAdapter } from '../common/CommonSQLiteAdapter'; + import SQLiteDatabase from './SQLiteDatabase'; const SQLiteAdapter: CommonSQLiteAdapter = new CommonSQLiteAdapter( diff --git a/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteDatabase.ts b/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteDatabase.ts index 869f8be816f..fc7bb66e426 100644 --- a/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteDatabase.ts +++ b/packages/datastore-storage-adapter/src/SQLiteAdapter/SQLiteDatabase.ts @@ -3,6 +3,7 @@ import SQLite from 'react-native-sqlite-storage'; import { ConsoleLogger } from '@aws-amplify/core'; import { PersistentModel } from '@aws-amplify/datastore'; + import { DB_NAME } from '../common/constants'; import { CommonSQLiteDatabase, ParameterizedStatement } from '../common/types'; @@ -16,7 +17,7 @@ if (ConsoleLogger.LOG_LEVEL === 'DEBUG') { /* -Note: +Note: I purposely avoided using arrow functions () => {} in this class, Because I ran into issues with them in some of the SQLite method callbacks @@ -41,7 +42,7 @@ class SQLiteDatabase implements CommonSQLiteDatabase { } public async createSchema(statements: string[]): Promise { - return await this.executeStatements(statements); + await this.executeStatements(statements); } public async clear(): Promise { @@ -56,6 +57,7 @@ class SQLiteDatabase implements CommonSQLiteDatabase { params: (string | number)[], ): Promise { const results: T[] = await this.getAll(statement, params); + return results[0]; } diff --git a/packages/datastore-storage-adapter/src/common/CommonSQLiteAdapter.ts b/packages/datastore-storage-adapter/src/common/CommonSQLiteAdapter.ts index 1caab5f0c8a..5ddf2e2ac53 100644 --- a/packages/datastore-storage-adapter/src/common/CommonSQLiteAdapter.ts +++ b/packages/datastore-storage-adapter/src/common/CommonSQLiteAdapter.ts @@ -2,26 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { ConsoleLogger } from '@aws-amplify/core'; import { - generateSchemaStatements, - queryByIdStatement, - modelUpdateStatement, - modelInsertStatement, - queryAllStatement, - queryOneStatement, - deleteByIdStatement, - deleteByPredicateStatement, -} from '../common/SQLiteUtils'; - -import { - StorageAdapter, + InternalSchema, ModelInstanceCreator, + ModelPredicate, ModelPredicateCreator, ModelSortPredicateCreator, - InternalSchema, - isPredicateObj, - ModelPredicate, - NamespaceResolver, NAMESPACES, + NamespaceResolver, OpType, PaginationInput, PersistentModel, @@ -29,12 +16,26 @@ import { PredicateObject, PredicatesGroup, QueryOne, + StorageAdapter, + isPredicateObj, utils, } from '@aws-amplify/datastore'; + +import { + deleteByIdStatement, + deleteByPredicateStatement, + generateSchemaStatements, + modelInsertStatement, + modelUpdateStatement, + queryAllStatement, + queryByIdStatement, + queryOneStatement, +} from '../common/SQLiteUtils'; + import { CommonSQLiteDatabase, - ParameterizedStatement, ModelInstanceMetadataWithId, + ParameterizedStatement, } from './types'; const { traverseModel, validatePredicate, isModelConstructor } = utils; @@ -49,6 +50,7 @@ export class CommonSQLiteAdapter implements StorageAdapter { namsespaceName: string, modelName: string, ) => PersistentModelConstructor; + private db: CommonSQLiteDatabase; private initPromise: Promise; private resolve: (value?: any) => void; @@ -74,6 +76,7 @@ export class CommonSQLiteAdapter implements StorageAdapter { }); } else { await this.initPromise; + return; } this.schema = theSchema; @@ -205,6 +208,7 @@ export class CommonSQLiteAdapter implements StorageAdapter { for (const r of relations) { delete record[r.fieldName]; } + return this.modelInstanceCreator(modelConstructor, record); }); } @@ -228,9 +232,10 @@ export class CommonSQLiteAdapter implements StorageAdapter { const queryById = predicates && this.idFromPredicate(predicates); - const records: T[] = await (async () => { + const records: T[] = (await (async () => { if (queryById) { const record = await this.getById(tableName, queryById); + return record ? [record] : []; } @@ -243,7 +248,7 @@ export class CommonSQLiteAdapter implements StorageAdapter { ); return await this.db.getAll(queryStatement, params); - })(); + })()) as T[]; return await this.load(namespaceName, modelConstructor.name, records); } @@ -403,7 +408,7 @@ export class CommonSQLiteAdapter implements StorageAdapter { // create the delete statements right away const deleteStatement = deleteByIdStatement(instance.id, tableName); deleteStatements.add(deleteStatement); - result.push([(item), OpType.DELETE]); + result.push([item as unknown as T, OpType.DELETE]); } else { // query statements for the saves at first const queryStatement = queryByIdStatement(id, tableName); @@ -423,14 +428,14 @@ export class CommonSQLiteAdapter implements StorageAdapter { tableName, ); saveStatements.add(insertStatement); - result.push([(itemsToSave[idx]), OpType.INSERT]); + result.push([itemsToSave[idx] as unknown as T, OpType.INSERT]); } else { const updateStatement = modelUpdateStatement( itemsToSave[idx], tableName, ); saveStatements.add(updateStatement); - result.push([(itemsToSave[idx]), OpType.UPDATE]); + result.push([itemsToSave[idx] as unknown as T, OpType.UPDATE]); } }); diff --git a/packages/datastore-storage-adapter/src/common/SQLiteUtils.ts b/packages/datastore-storage-adapter/src/common/SQLiteUtils.ts index 431b4918fff..4b9dca12ae0 100644 --- a/packages/datastore-storage-adapter/src/common/SQLiteUtils.ts +++ b/packages/datastore-storage-adapter/src/common/SQLiteUtils.ts @@ -1,24 +1,24 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { + GraphQLScalarType, InternalSchema, - SchemaModel, + ModelAttributeAuth, + ModelAuthRule, ModelField, PersistentModel, - isGraphQLScalarType, - QueryOne, + PredicateObject, PredicatesGroup, - isPredicateObj, + QueryOne, + SchemaModel, SortPredicatesGroup, - PredicateObject, - isPredicateGroup, + isGraphQLScalarType, + isModelAttributeAuth, isModelFieldType, + isPredicateGroup, + isPredicateObj, isTargetNameAssociation, - isModelAttributeAuth, - ModelAttributeAuth, - ModelAuthRule, utils, - GraphQLScalarType, } from '@aws-amplify/datastore'; import { ParameterizedStatement } from './types'; @@ -43,6 +43,7 @@ const updateSet: (model: any) => [any, any] = model => { .filter(([k]) => k !== 'id') .map(([k, v]) => { values.push(prepareValueForDML(v)); + return `"${k}"=?`; }) .join(', '); @@ -136,13 +137,14 @@ export const implicitAuthFieldsForModel: (model: SchemaModel) => string[] = ( const authFieldExplicitlyDefined = Object.values(model.fields).find( (f: ModelField) => f.name === authField, ); + return !authFieldExplicitlyDefined; }); }; export function modelCreateTableStatement( model: SchemaModel, - userModel: boolean = false, + userModel = false, ): string { // implicitly defined auth fields, e.g., `owner`, `groupsField`, etc. const implicitAuthFields = implicitAuthFieldsForModel(model); @@ -210,6 +212,7 @@ export function modelCreateTableStatement( const createTableStatement = `CREATE TABLE IF NOT EXISTS "${ model.name }" (${fields.join(', ')});`; + return createTableStatement; } @@ -316,7 +319,7 @@ export const whereConditionFromPredicateObject = ({ return [`"${field}" ${comparisonOperator} ?`, [operand]]; } - const logicalOperatorKey = operator; + const logicalOperatorKey = operator as keyof typeof logicalOperatorMap; const logicalOperator = logicalOperatorMap[logicalOperatorKey]; @@ -367,7 +370,7 @@ export function whereClauseFromPredicate( ): void { if (isPredicateGroup(predicate)) { const { type: groupType, predicates: groupPredicates } = predicate; - let filterType: string = ''; + let filterType = ''; let isNegation = false; switch (groupType) { case 'not': @@ -423,7 +426,7 @@ export function orderByClauseFromSort( export function limitClauseFromPagination( limit: number, - page: number = 0, + page = 0, ): ParameterizedStatement { const params = [limit]; let clause = 'LIMIT ?'; @@ -483,6 +486,7 @@ export function deleteByIdStatement( tableName: string, ): ParameterizedStatement { const deleteStatement = `DELETE FROM "${tableName}" WHERE "id"=?`; + return [deleteStatement, [id]]; } @@ -498,5 +502,6 @@ export function deleteByPredicateStatement( statement += ` ${whereClause}`; params.push(...whereParams); } + return [statement, params]; } diff --git a/packages/datastore-storage-adapter/src/common/types.ts b/packages/datastore-storage-adapter/src/common/types.ts index 2957233176b..c1bce70b876 100644 --- a/packages/datastore-storage-adapter/src/common/types.ts +++ b/packages/datastore-storage-adapter/src/common/types.ts @@ -1,6 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { PersistentModel, ModelInstanceMetadata } from '@aws-amplify/datastore'; +import { ModelInstanceMetadata, PersistentModel } from '@aws-amplify/datastore'; export interface CommonSQLiteDatabase { init(): Promise; diff --git a/packages/datastore-storage-adapter/src/index.ts b/packages/datastore-storage-adapter/src/index.ts index 064a0f2b12c..19ba93a509b 100644 --- a/packages/datastore-storage-adapter/src/index.ts +++ b/packages/datastore-storage-adapter/src/index.ts @@ -1,4 +1,5 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import SQLiteAdapter from './SQLiteAdapter/SQLiteAdapter'; + export { SQLiteAdapter };