
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
web-sqlite-js
Advanced tools
web-sqlite-js is a friendly, out-of-the-box SQLite database for the web that makes persistent client-side storage simple for every developer.
web-sqlite-js is a friendly, out-of-the-box SQLite database for the web that makes persistent client-side storage simple for every developer.
Designed to be truly effortless, it allows you to get a high-performance relational database running in the browser in seconds. Just install, set your HTTP headers, and start querying—no complex infrastructure required.
onLog().Pick the path that fits your setup:
# npm
npm install web-sqlite-js
import openDB from "web-sqlite-js";
// ...
For quick demos or plain HTML pages you can load the prebuilt module directly:
<script type="module">
import openDB from "https://cdn.jsdelivr.net/npm/web-sqlite-js@2.2.0/dist/index.js";
// ...
</script>
See samples/cdn.html for a copy/paste page you can serve .
Heads up:
SharedArrayBufferrequires COOP/COEP headers; see the section below.
Pick your stack below to set the headers:
This library depends on SharedArrayBuffer for high performance, which requires your server to send the following HTTP headers:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Update your vite.config.ts:
import { defineConfig } from "vite";
export default defineConfig({
server: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
},
preview: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
},
});
Update your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: "/(.*)",
headers: [
{
key: "Cross-Origin-Opener-Policy",
value: "same-origin",
},
{
key: "Cross-Origin-Embedder-Policy",
value: "require-corp",
},
],
},
];
},
};
module.exports = nextConfig;
Update your webpack.config.js:
module.exports = {
// ...
devServer: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
},
};
Add the headers to your server block:
server {
# ...
add_header Cross-Origin-Opener-Policy "same-origin";
add_header Cross-Origin-Embedder-Policy "require-corp";
# ...
}
Use a middleware:
const express = require("express");
const app = express();
app.use((req, res, next) => {
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
next();
});
// ...
Most modern React/Vue setups use Vite. Please refer to the Vite section above.
If you are using an older webpack-based setup (like CRA react-scripts), you technically need to configure the underlying webpack-dev-server, but CRA doesn't expose this easily without ejecting or using tools like craco or react-app-rewired to modify the dev server configuration as shown in the Webpack section.
// 1. Open the database (creates 'my-database.sqlite3' in OPFS)
const db = await openDB("local.sqlite3");
// 2. Initialize schema
await db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
email TEXT
);
`);
// 3. Insert data (Parameterized)
await db.exec("INSERT INTO users (name, email) VALUES (?, ?)", [
"Alice",
"alice@example.com",
]);
await db.exec("INSERT INTO users (name, email) VALUES ($name, $email)", {
$name: "Bob",
$email: "bob@example.com",
});
// 4. Query data
const users = await db.query("SELECT * FROM users");
console.log(users);
// Output: [{ id: 1, name: 'Alice', ... }, { id: 2, name: 'Bob', ... }]
// 5. Close when done
await db.close();
Add { debug: true } when opening the database to stream worker-side SQL logs (including bind values and timings) to your browser's console.debug. This is useful for profiling and verifying queries during development.
const db = await openDB("local.sqlite3", { debug: true });
await db.exec("CREATE TABLE IF NOT EXISTS notes (body TEXT)");
await db.query("SELECT * FROM notes WHERE id = ?", [1]);
The console output highlights SQL keywords and shows how long each statement took (click to preview):
Transactions are atomic. If any command inside the callback fails, the entire transaction is rolled back.
await db.transaction(async (tx) => {
await tx.exec("INSERT INTO users (name) VALUES (?)", ["Charlie"]);
// You can perform multiple operations safely
await tx.exec("INSERT INTO logs (action) VALUES (?)", ["User Created"]);
// If you throw an error here, both INSERTs will be rolled back!
// throw new Error('Something went wrong');
});
Manage database schema changes across releases using the built-in versioning system. Define releases with migration SQL and optional seed data.
const db = await openDB("myapp", {
releases: [
{
version: "1.0.0",
migrationSQL: `
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
);
`,
seedSQL: `
INSERT INTO users (name, email) VALUES
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com');
`,
},
{
version: "1.1.0",
migrationSQL: `
ALTER TABLE users ADD COLUMN created_at TEXT DEFAULT (datetime('now'));
`,
},
],
});
// Database is now at version 1.1.0 with all migrations applied
const users = await db.query("SELECT * FROM users");
console.log(users);
// Output: [{ id: 1, name: 'Alice', email: 'alice@example.com', created_at: '...' }, ...]
Starting with v2.2.0, web-sqlite-js uses a two-tier validation system that intelligently handles SQL formatting changes:
Tier 1: Fast Path (< 0.1ms)
Tier 2: Slow Path (1-5ms, only on hash mismatch)
What this means for you:
// You can reformat your SQL without breaking migrations!
const db1 = await openDB("myapp", {
releases: [
{
version: "1.0.0",
migrationSQL: "CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT);",
},
],
});
await db1.close();
// Reopen with reformatted SQL (whitespace-only change)
const db2 = await openDB("myapp", {
releases: [
{
version: "1.0.0",
migrationSQL: `
CREATE TABLE items (
id INTEGER PRIMARY KEY,
name TEXT
);
`,
},
],
});
// ✅ Works! Hash auto-updated (no error)
Enhanced Error Messages:
If you accidentally change the SQL semantics, you'll get detailed error messages:
Hash mismatch for 1.0.0 migrationSQL:
Expected: abc123...
Actual: def456...
SQL has changed:
- Original: CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT);
+ Current: CREATE TABLE items (id INTEGER PRIMARY KEY, email TEXT);
1.0.0.sqlite3, 1.1.0.sqlite3)MAJOR.MINOR.PATCH formatSubscribe to structured log events for monitoring, debugging, and analytics. The onLog() API allows you to capture SQL execution details, errors, and application events.
const db = await openDB("myapp");
// Register log listener
const cancelLog = db.onLog((log) => {
if (log.level === "error") {
// Send errors to tracking service
errorTracking.capture(log.data);
} else if (log.level === "debug") {
// Log SQL execution details
console.log(`SQL: ${log.data.sql}, Duration: ${log.data.duration}ms`);
} else if (log.level === "info") {
// Track application events (open, close, transactions)
console.log(`Event: ${log.data.action}`);
}
});
// Execute some SQL to generate logs
await db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
await db.exec("INSERT INTO users (name) VALUES (?)", ["Alice"]);
// Later: stop listening
cancelLog();
Log Levels:
"debug" - SQL execution details (sql, duration, bind parameters)"info" - Application events (open, close, commit, rollback)"error" - SQL errors and exceptionsMultiple Callbacks: You can register multiple log listeners simultaneously:
const cancel1 = db.onLog((log) => console.log("Logger 1:", log));
const cancel2 = db.onLog((log) => {
if (log.level === "error") sendToAlerting(log.data);
});
FAQs
web-sqlite-js is a friendly, out-of-the-box SQLite database for the web that makes persistent client-side storage simple for every developer.
The npm package web-sqlite-js receives a total of 4 weekly downloads. As such, web-sqlite-js popularity was classified as not popular.
We found that web-sqlite-js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.