Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added better error handling, support for optional SQLite extension(upcoming) #7

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ This library supports the following backing mechanism:
* OPFS (Worker)
* OPFS SyncAccessHandles (Worker)

## Chrome Extension
Available when using this library: Magieno SQLite Viewer Chrome Extension. This extension allows you to execute SQL Queries and see the results in a table format.

## Installation using NPM

This library has two important files: `sqlite-client.js` and `sqlite-client-worker.js`.
Expand Down
16 changes: 16 additions & 0 deletions e2e/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
"description": "E2E testing ==========",
"main": "rollup.config.e2e.js",
"type": "module",
"private": true,
"scripts": {
"build": "tsc -p tsconfig.json && mkdir -p public_html/dist && cp -r ../dist/bundle/sqlite-client-worker.js public_html/dist/sqlite-client-worker.mjs && cp -r ../node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/* public_html/dist/ && rollup -c rollup.config.e2e.js --compact",
"build": "tsc -p tsconfig.json && mkdir -p public_html/dist && cp -r ../dist/bundle/sqlite-client-worker.js public_html/dist/sqlite-client-worker.mjs && cp -r node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/* public_html/dist/ && rollup -c rollup.config.e2e.js --compact",
"start:server": "pristine file-server:start --directory=./public_html --header=cross-origin-opener-policy:same-origin --header=cross-origin-embedder-policy:require-corp",
"test": "pristine file-server:start --directory=./public_html --header=cross-origin-opener-policy:same-origin --header=cross-origin-embedder-policy:require-corp & jest --runInBand --detectOpenHandles --forceExit --verbose --silent=false --coverage"
},
Expand All @@ -17,6 +18,7 @@
"jest": "^29.7.0",
"jest-puppeteer": "^10.0.1",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2"
"ts-node": "^10.9.2",
"@sqlite.org/sqlite-wasm": "^3.45.2-build1"
}
}
55 changes: 55 additions & 0 deletions e2e/public_html/opfs-error.worker.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>@magieno/sqlite-client Memory (Worker) Error</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css"
integrity="sha384-4LISF5TTJX/fLmGSxO53rV4miRxdg84mZsxmO8Rx5jGtp/LbrixFETvWa5a6sESd" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12">

<nav aria-label="breadcrumb" class="mt-2">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">OPFS (Worker)</li>
</ol>
</nav>

<h1 class="mt-3"><i class="bi bi-directory"></i> OPFS</h1>

<h2 class="badge text-bg-warning "><i class="bi bi-gear-fill"></i> Worker</h2>

<div id="alert-container" class="mt-4"></div>
</div>
</div>
</div>

<script type="module" src="dist/main.js">
</script>

<script type="module">
const sqliteClient = window.opfsWorkerSqliteClient;
await sqliteClient.init();

try {
await sqliteClient.executeSql("INVALID SQL");
} catch (e) {
console.log("Error in page", e);
document.getElementById("alert-container").innerHTML = "<div class=\"alert alert-danger\" id='error' role=\"alert\">\n" +
" <h4 class=\"alert-heading\">Error!</h4>\n" +
" <p>There was an error executing the SQL Query:</p>\n" +
" <pre>" + e.message + "</pre>" +
"</div>";
}
</script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+"
crossorigin="anonymous"></script>
</body>
</html>
23 changes: 23 additions & 0 deletions e2e/specs/main-thread-and-worker-error.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const htmlFilesToLoad = [
"opfs-error.worker.html",
]

htmlFilesToLoad.forEach((htmlFile) => {
describe(htmlFile, () => {
beforeAll(async () => {
await page.goto(`http://127.0.0.1:9000/${htmlFile}`, {
headless: true,
});

await page.waitForSelector('#error');
});

it('should have the error alert', async () => {
const errorFound = await page.evaluate(() => {
return document.querySelector("#error") !== null;
})

expect(errorFound).toBeTruthy();
});
});
})
40 changes: 21 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@magieno/sqlite-client",
"version": "3.45.1-build1",
"version": "10.0.0",
"description": "SQLite Client is a wrapper for Sqlite on Wasm that uses the Origin Private File System to persist the sqlite database file.",
"keywords": [
"sqlite",
Expand Down Expand Up @@ -39,7 +39,9 @@
},
"homepage": "https://github.com/magieno/sqlite-client#readme",
"dependencies": {
"@sqlite.org/sqlite-wasm": "^3.45.1-build1"
},
"peerDependencies": {
"@sqlite.org/sqlite-wasm": "^3.41.2-build10"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.1",
Expand All @@ -49,7 +51,7 @@
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-ignore": "^1.0.10",
"rollup-plugin-typescript2": "^0.34.1",
"typescript": "^5.0.4"
"typescript": "^5.4.3"
},
"files": [
"dist"
Expand Down
2 changes: 2 additions & 0 deletions src/adapters/adapters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./in-main-thread.sqlite-adapter";
export * from "./in-worker.sqlite-adapter";
4 changes: 4 additions & 0 deletions src/enums/enums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./return-value.enum";
export * from "./row-mode.enum";
export * from "./sqlite-client-type.enum";
export * from "./sqlite-message-type.enum";
6 changes: 6 additions & 0 deletions src/interfaces/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from "./memory-main-thread-sqlite-options.interface";
export * from "./memory-worker-sqlite-options.interface";
export * from "./opfs-sah-worker-sqlite-options.interface";
export * from "./opfs-worker-sqlite-options.interface";
export * from "./sqlite-adapter.interface";
export * from "./sqlite-message.interface";
3 changes: 3 additions & 0 deletions src/interfaces/opfs-worker-sqlite-options.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ export interface OpfsWorkerSqliteOptionsInterface {
flags: string;

sqliteWorkerPath: string;

// Default: false;
emitEventsToMagienoSqliteChromeExtension?: boolean;
}
4 changes: 4 additions & 0 deletions src/messages/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./create-database.message";
export * from "./create-database-result.message";
export * from "./execute-sql.message";
export * from "./execute-sql-result.message";
1 change: 1 addition & 0 deletions src/proxies/proxies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./sqlite-client-worker.proxy";
68 changes: 68 additions & 0 deletions src/sqlite-client-extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {SqliteClientTypeEnum} from "./enums/sqlite-client-type.enum";
import {ReturnValueEnum, RowModeEnum, SqliteClient} from "./sqlite-client";

export class SqliteClientExtension {
public static workerPath: string;

error: string;

static dispatchEvent(event: {type: string, uniqueId: string, [x: string]: any}) {
window.dispatchEvent(new CustomEvent("MAGIENO_SQLITE_CLIENT_TO_EXTENSION", {
detail: event,
}));
}

public static registerWorkerPath(sqliteWorkerPath) {
SqliteClientExtension.workerPath = sqliteWorkerPath;

// Cache the worker path in CacheStorage, so that the extension can use it when the app is in other pages.
caches.open("magieno").then(cache => {
cache.put("sqlite-worker", new Response(sqliteWorkerPath));
});
}

/**
* This method registers and enables event listeners that will be used by the Magieno SQLite Editor Chrome Extension.
* @param workerPath
*/
static register(workerPath: string) {
SqliteClientExtension.registerWorkerPath(workerPath);

// Setup the listeners
window.addEventListener('MAGIENO_SQLITE_CLIENT_FROM_EXTENSION', async (event: CustomEvent) => {
await SqliteClientExtension.receiveEvent(event);
});
}

static async receiveEvent(event: CustomEvent) {
const detail = event.detail;

switch (detail.type) {
case "INIT":
if(SqliteClientExtension.workerPath === undefined) {
SqliteClientExtension.dispatchEvent({"type": "INIT_RESULT", "uniqueId": detail.uniqueId, "error": "Cannot find the SqliteWorkerPath. For security reasons, you must manually register it in your page: `SqliteClientExtension.registerWorkerPath('/path/to/sqlite-worker.mjs')`"});
return;
}

SqliteClientExtension.dispatchEvent({"type": "INIT_RESULT", "uniqueId": detail.uniqueId});
return;
case "EXECUTE_SQL_QUERY":
const client = new SqliteClient({
type: SqliteClientTypeEnum.OpfsWorker,
filename: detail.filename,
flags: "c",
sqliteWorkerPath: SqliteClientExtension.workerPath,
})

await client.init();

try {
const response = await client.executeSql(detail.query, [], ReturnValueEnum.ResultRows, RowModeEnum.Object);
SqliteClientExtension.dispatchEvent({"type": "EXECUTE_SQL_QUERY_RESULT", "uniqueId": detail.uniqueId, "filename": detail.filename, "response": response});
return;
} catch (error) {
SqliteClientExtension.dispatchEvent({"type": "EXECUTE_SQL_QUERY_RESULT", "uniqueId": detail.uniqueId, "error": error.message});
}
}
}
}
Loading
Loading