Add deleteDatabase to plugin interface, FastSQL class, and all native platforms - #5
Conversation
…iOS, and Android Co-authored-by: caspinos <16002933+caspinos@users.noreply.github.com> Agent-Logs-Url: https://github.com/caspinos/capacitor-fast-sql/sessions/9baa1535-e716-4660-93b7-b1cc0e8810ed
There was a problem hiding this comment.
Pull request overview
Adds a new deleteDatabase API across the TypeScript interface, high-level FastSQL wrapper, and platform implementations (Web/iOS/Android) to permanently remove a database (vs. only disconnecting).
Changes:
- Extend the plugin TypeScript interface with
deleteDatabase({ database }). - Add
FastSQL.deleteDatabase(database)that disconnects if needed and delegates to the plugin. - Implement
deleteDatabaseon Web/iOS/Android to close any open connection and remove persisted storage.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/definitions.ts | Adds deleteDatabase to the public Capacitor plugin interface and docs. |
| src/fast-sql.ts | Adds high-level FastSQL.deleteDatabase wrapper with auto-disconnect. |
| src/web.ts | Adds Web implementation to close sql.js DB if open and delete the IndexedDB record. |
| ios/Sources/CapgoCapacitorFastSqlPlugin/CapgoCapacitorFastSqlPlugin.swift | Registers and implements native deletion (close/stop server if needed/delete .db file). |
| android/src/main/java/app/capgo/capacitor/fastsql/CapgoCapacitorFastSqlPlugin.java | Implements native deletion (close/stop server if needed/delete .db file). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @objc func deleteDatabase(_ call: CAPPluginCall) { | ||
| guard let database = call.getString("database") else { | ||
| call.reject("Database name is required") | ||
| return | ||
| } |
There was a problem hiding this comment.
deleteDatabase accepts an arbitrary database string and passes it into getDatabasePath(). Because getDatabasePath() simply appends the name into a file path, callers can potentially use path separators (e.g. ../) to target files outside the intended app database directory. Please validate/sanitize the database name (e.g., reject names containing /, \, or .., or ensure the resolved path stays within Documents) before deleting.
| let fileManager = FileManager.default | ||
| if fileManager.fileExists(atPath: dbPath) { | ||
| try fileManager.removeItem(atPath: dbPath) | ||
| } |
There was a problem hiding this comment.
This deletes only the main *.db file. If the database has WAL/journal sidecar files (e.g. *.db-wal, *.db-shm, *.db-journal), they can be left behind, which conflicts with the method’s “permanently delete” intent and can leak disk usage/data remnants. Consider removing common SQLite sidecar files for the same base path as part of deletion.
| } | |
| } | |
| // Best-effort removal of common SQLite sidecar files for the same database base path. | |
| // These can be created when WAL/journaling is enabled (e.g. <database>.db-wal). | |
| let sidecarSuffixes = ["-wal", "-shm", "-journal"] | |
| for suffix in sidecarSuffixes { | |
| let sidecarPath = dbPath + suffix | |
| if fileManager.fileExists(atPath: sidecarPath) { | |
| // Ignore errors for sidecar deletions to preserve existing behavior. | |
| try? fileManager.removeItem(atPath: sidecarPath) | |
| } | |
| } |
| public void deleteDatabase(PluginCall call) { | ||
| String database = call.getString("database"); | ||
| if (database == null) { | ||
| call.reject("Database name is required"); | ||
| return; | ||
| } | ||
|
|
There was a problem hiding this comment.
deleteDatabase uses the raw database string to build a File path (new File(dataDir, database + ".db")). If database contains path separators or traversal sequences (e.g. ../), this can escape filesDir and delete unintended files. Please validate/sanitize the database name (or verify the canonical path remains under filesDir) before performing deletion.
| call.reject("Failed to delete database file for '" + database + "'. The file may be locked or there are insufficient permissions."); | ||
| return; | ||
| } | ||
|
|
There was a problem hiding this comment.
This deletes only database + ".db". If SQLite is in WAL mode or has an active rollback journal, sidecar files like *.db-wal, *.db-shm, or *.db-journal can remain on disk, undermining the “permanent delete” behavior. Consider deleting these common sidecar files (if they exist) alongside the main DB file.
| // Best-effort deletion of common SQLite sidecar files (WAL, shared memory, journal) | |
| String dbPath = dbFile.getPath(); | |
| String[] sidecarSuffixes = { "-wal", "-shm", "-journal" }; | |
| for (String suffix : sidecarSuffixes) { | |
| File sidecarFile = new File(dbPath + suffix); | |
| if (sidecarFile.exists()) { | |
| sidecarFile.delete(); | |
| } | |
| } |
No API existed to permanently remove a database file — only disconnect (close the connection) was available.
Changes
src/definitions.ts— AddeddeleteDatabase(options: { database: string }): Promise<void>toCapgoCapacitorFastSqlPlugininterfacesrc/fast-sql.ts— AddedFastSQL.deleteDatabase(database: string): auto-disconnects if the DB is currently open, then delegates to the pluginsrc/web.ts— ImplementeddeleteDatabase: closes the in-memory sql.js instance if open, then removes the record from IndexedDBdeleteDatabase: closes the connection, stops the HTTP server if no databases remain, deletes the.dbfile from diskUsage
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
dl.google.com/usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -Xmx1536m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-8.14.4-all/231zbbez8dqwqz4pvbcxtcw84/gradle-8.14.4/lib/gradle-daemon-main-8.14.4.jar(dns block)/usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED -XX:MaxMetaspaceSize=384m -XX:+HeapDumpOnOutOfMemoryError -Xms256m -Xmx512m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-8.6-bin/afr5mpiioh2wthjmwnkmdsd5w/gradle-8.6/lib/gradle-launcher-8.6.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-8.6-bin/afr5mpiioh2wthjmwnkmdsd5w/gradle-8.6/lib/agents/gradle-instrumentation-agent-8.6.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon(dns block)If you need me to access, download, or install something from one of these locations, you can either:
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.