angular-sqlite-app-starter
Ionic/Angular application demonstrating the use of the
@capacitor-community/sqlite@web
this app uses Capacitor 4
Maintainer | GitHub | Social |
---|---|---|
Quéau Jean Pierre | jepiqueau |
To start building your App using this Starter App, clone this repo to a new directory:
git clone https://github.com/jepiqueau/angular-sqlite-app-starter.git
cd angular-sqlite-app-starter
git remote rm origin
- then install it
npm install
npx cap update
To run the app for developing, you can do any of these commands:
ionic serve
npm start
ionic serve --lab
To run angular test:
ng test
To build the app for testing:
npm run build
npx cap copy
To build the app for production:
npm run build-production
npx cap copy
To change the app name and app id, go to capacitor.config.ts
and change:
"appId": "com.jeep.app.ionic.angular",
"appName": "angular-sqlite-app-starter",
If you don't see the tests on android you could put the biometrics to false in capacitor.config.ts
androidBiometric.biometricAuth = false;
npx cap open android
Once Android Studio launches, you can build your app through the standard Android Studio workflow.
npx cap open ios
🛑 Now available with @capacitor-community/sqlite@web
🛑
The @capacitor-community/sqlite@web
is now implementing sqlite for Web Browsers using a companion Stencil component jeep-sqlite
which itself is based on sql.js
for in-memory and localforage
for storing the database in an IndexedDB storage.
if you run
ionic serve
-
with
jeep-sqlite
installed:you will be able to run SQLite queries. The sqlite.service.ts has been modified to handle them. see Web Usage documentation
-
without
jeep-sqlite
installed:
Not implemented on Web
cd electron
npm install
npm run build
cd ..
npx cap sync @capacitor-community/electron
npm run build
npx cap copy @capacitor-community/electron
npx cap open @capacitor-community/electron
When your Electron app is tested and you would like to create an executable either for Mac or for Windows
cd electron
npm run electron:make
The @capacitor-community/sqlite
tests are accessible through the home page.
- Test 2 Databases
- Test Existing Connection
- Test Upgrade Versions
- Test Encryption
- Test Import Json
- Test Export Json
- Test Export Json #59
- Test Copy From Assets
The application uses a service class as a wrapper to the @capacitor-community/sqlite
plugin
At the end of the test, seven databases should have been created,
- testNewSQLite.db
- testSetSQLite.db encrypted password
sqlite secret
- test-updversionSQLite.db
- db-from-jsonSQLite.db
- db-from-json59SQLite.db
- dbForCopySQLite.db
- myDBSQLite.db
An Angular Service has been defined as a wrapper to the @capacitor-community/sqlite
plugin and from release 2.9.0-alpha.5
can be used at a singleton service
initialized in app.component.ts
and imported as a provider in app.module.ts
. In this case the DBConnection
can be used through Pages (see example in existingconnection.page.ts
which can be called after the execution of test2dbs.page.ts
).
import { Injectable } from '@angular/core';
import { Capacitor } from '@capacitor/core';
import { CapacitorSQLite, SQLiteDBConnection, SQLiteConnection, capSQLiteSet,
capSQLiteChanges, capSQLiteValues, capEchoResult, capSQLiteResult
} from '@capacitor-community/sqlite';
@Injectable()
export class SQLiteService {
sqlite: SQLiteConnection;
isService: boolean = false;
platform: string;
sqlitePlugin: any;
native: boolean = false;
constructor() {
}
/**
* Plugin Initialization
*/
initializePlugin(): Promise<boolean> {
return new Promise (resolve => {
this.platform = Capacitor.getPlatform();
if(this.platform === 'ios' || this.platform === 'android') this.native = true;
console.log("*** native " + this.native)
this.sqlitePlugin = CapacitorSQLite;
this.sqlite = new SQLiteConnection(this.sqlitePlugin);
this.isService = true;
console.log("$$$ in service this.isService " + this.isService + " $$$")
resolve(true);
});
}
/**
* Echo a value
* @param value
*/
async echo(value: string): Promise<capEchoResult> {
if(this.sqlite != null) {
try {
return await this.sqlite.echo(value);
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error("no connection open"));
}
}
async isSecretStored(): Promise<capSQLiteResult> {
if(!this.native) {
return Promise.reject(new Error(`Not implemented for ${this.platform} platform`));
}
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.isSecretStored());
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
async setEncryptionSecret(passphrase: string): Promise<void> {
if(!this.native) {
return Promise.reject(new Error(`Not implemented for ${this.platform} platform`));
}
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.setEncryptionSecret(passphrase));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
async changeEncryptionSecret(passphrase: string, oldpassphrase: string): Promise<void> {
if(!this.native) {
return Promise.reject(new Error(`Not implemented for ${this.platform} platform`));
}
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.changeEncryptionSecret(passphrase, oldpassphrase));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* addUpgradeStatement
* @param database
* @param fromVersion
* @param toVersion
* @param statement
* @param set
*/
async addUpgradeStatement(database:string, fromVersion: number,
toVersion: number, statement: string,
set?: capSQLiteSet[])
: Promise<void> {
if(this.sqlite != null) {
try {
await this.sqlite.addUpgradeStatement(database, fromVersion, toVersion,
statement, set ? set : []);
return Promise.resolve();
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open for ${database}`));
}
}
/**
* Create a connection to a database
* @param database
* @param encrypted
* @param mode
* @param version
*/
async createConnection(database:string, encrypted: boolean,
mode: string, version: number
): Promise<SQLiteDBConnection> {
if(this.sqlite != null) {
try {
const db: SQLiteDBConnection = await this.sqlite.createConnection(
database, encrypted, mode, version);
if (db != null) {
return Promise.resolve(db);
} else {
return Promise.reject(new Error(`no db returned is null`));
}
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open for ${database}`));
}
}
/**
* Close a connection to a database
* @param database
*/
async closeConnection(database:string): Promise<void> {
if(this.sqlite != null) {
try {
await this.sqlite.closeConnection(database);
return Promise.resolve();
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open for ${database}`));
}
}
/**
* Retrieve an existing connection to a database
* @param database
*/
async retrieveConnection(database:string):
Promise<SQLiteDBConnection> {
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.retrieveConnection(database));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open for ${database}`));
}
}
/**
* Retrieve all existing connections
*/
async retrieveAllConnections():
Promise<Map<string, SQLiteDBConnection>> {
if(this.sqlite != null) {
try {
const myConns = await this.sqlite.retrieveAllConnections();
/* let keys = [...myConns.keys()];
keys.forEach( (value) => {
console.log("Connection: " + value);
});
*/
return Promise.resolve(myConns);
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Close all existing connections
*/
async closeAllConnections(): Promise<void> {
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.closeAllConnections());
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Check if connection exists
* @param database
*/
async isConnection(database: string): Promise<capSQLiteResult> {
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.isConnection(database));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Check Connections Consistency
* @returns
*/
async checkConnectionsConsistency(): Promise<capSQLiteResult> {
if(this.sqlite != null) {
try {
const res = await this.sqlite.checkConnectionsConsistency();
return Promise.resolve(res);
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Check if database exists
* @param database
*/
async isDatabase(database: string): Promise<capSQLiteResult> {
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.isDatabase(database));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Get the list of databases
*/
async getDatabaseList() : Promise<capSQLiteValues> {
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.getDatabaseList());
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Add "SQLite" suffix to old database's names
*/
async addSQLiteSuffix(folderPath?: string): Promise<void>{
if(!this.native) {
return Promise.reject(new Error(`Not implemented for ${this.platform} platform`));
}
if(this.sqlite != null) {
try {
const path: string = folderPath ? folderPath : "default";
return Promise.resolve(await this.sqlite.addSQLiteSuffix(path));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Delete old databases
*/
async deleteOldDatabases(folderPath?: string): Promise<void>{
if(!this.native) {
return Promise.reject(new Error(`Not implemented for ${this.platform} platform`));
}
if(this.sqlite != null) {
try {
const path: string = folderPath ? folderPath : "default";
return Promise.resolve(await this.sqlite.deleteOldDatabases(path));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Import from a Json Object
* @param jsonstring
*/
async importFromJson(jsonstring:string): Promise<capSQLiteChanges> {
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.importFromJson(jsonstring));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Is Json Object Valid
* @param jsonstring Check the validity of a given Json Object
*/
async isJsonValid(jsonstring:string): Promise<capSQLiteResult> {
if(this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.isJsonValid(jsonstring));
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
/**
* Copy databases from public/assets/databases folder to application databases folder
*/
async copyFromAssets(): Promise<void> {
if (this.sqlite != null) {
try {
return Promise.resolve(await this.sqlite.copyFromAssets());
} catch (err) {
return Promise.reject(new Error(err));
}
} else {
return Promise.reject(new Error(`no connection open`));
}
}
}
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!