npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

userbase-sql.js

v0.0.0

Published

sql.js wrapper for Userbase JS SDK

Downloads

16

Readme

Userbase + sql.js

End-to-end encrypted SQL! (still experimental)

What is Userbase?

Userbase is the easiest way to add user accounts and user data persistence to your static site. All Userbase features are accessible through a very simple JavaScript SDK, directly from the browser. No backend necessary.

What is sql.js?

sql.js is a javascript SQL database. It allows you to create a relational database and query it entirely in the browser... It uses a virtual database file stored in memory, and thus doesn't persist the changes made to the database.

What is userbase-sql.js?

userbase-sql.js brings SQL to Userbase, and end-to-end encrypted persistence to sql.js (+ concurrent real-time updates across browsers). It wraps the Userbase JavaScript SDK database API with the sql.js API, exposing SQLite features to Userbase developers:

  • Structure relational data
  • Construct SQL queries
  • Build indexes
  • Maintain referential integrity
  • Transactions across tables
  • Uniqueness constraints across columns
  • etc.

A single user can create as many of their own individual end-to-end encrypted sql.js databases as they want, and only they can access their own databases. The Userbase server handles ordering of writes to each individual database, and each database is completely partitioned from other databases on the server-side.

Usage

Installation

Create an admin account

First, you need to create a free Userbase admin account. No credit card required.

Install userbase-sql.js

Then, you need to include userbase-sql.js in your web app.

You can either use the npm package:

npm install userbase-sql.js

Or, you can include it with a <script> tag:

<script type="text/javascript" src="https://sql.userbase.com/0/userbase-sql.js"></script>

Set the App ID

In your admin account, you will find a Trial app. Get its App ID, and then in your browser code, initialize userbase-sql.js with it.

await userbaseSqlJs.init({ appId: 'YOUR_APP_ID' })

And you're now ready to use userbase-sql.js.

Creating a user

You'll need to create a user to store data.

await userbaseSqlJs.signUp({ username: 'my_first_user', password: '1A$dHz9@leupyCns' })

Now, the SQL

First register a changeHandler:

let sqlJsDb

// this creates the database on the server and connects the client to it for real-time updates
await userbaseSqlJs.openSqlJsDatabase({
  databaseName: 'my_secret_db',
  changeHandler: ({ db }) => {
    sqlJsDb = db
  }
})

Execute some sql:

const sql1 = "CREATE TABLE hello (a int PRIMARY KEY, b char);"
const sql2 = "INSERT INTO hello VALUES (0, 'hello');"
const sql3 = "INSERT INTO hello VALUES (1, 'world');"

// each SQL statement is encrypted and sent to the server for storage
await userbaseSqlJs.execSql({ databaseName: 'my_secret_db', sql: sql1 })

// the server then broadcasts the encrypted statement to all the user's connected clients
await userbaseSqlJs.execSql({ databaseName: 'my_secret_db', sql: sql2 })

// each client decrypts the statement, applies it to an in-memory sql.js database in the order set by the server,
// then calls the changeHandler with the updated sql.js database
await userbaseSqlJs.execSql({ databaseName: 'my_secret_db', sql: sql3 })

And read the result:

// read the global sql.js database updated by the changeHandler
const res = sqlJsDb.exec("SELECT * FROM hello")
/*
[
  {columns:['a','b'], values:[[0,'hello'],[1,'world']]}
]
*/

Every time the database grows a fixed amount, the client compresses and encrypts the entire sql.js database, and stores it on the server. When the user signs back in and loads their data, the client decrypts and decompresses that database, then applies any individual SQL statements that come after it. This all happens smoothly under the hood.

Bind values

const sql = "INSERT INTO hello VALUES (?, ?);"
const bindValues = [2, '"foo"']
await userbaseSqlJs.execSql({ databaseName: 'my_secret_db', sql, bindValues })
const sql = "INSERT INTO hello VALUES ($a, $b);"
const bindValues = { $a: 3, $b: '"bar"' }
await userbaseSqlJs.execSql({ databaseName: 'my_secret_db', sql, bindValues })

See more on bind values here.

Transactions

const sqlStatements = [
  { sql: "INSERT INTO hello VALUES (?, ?);", bindValues: [4, 'duplicate'] },
  { sql: "INSERT INTO hello VALUES (?, ?);", bindValues: [4, 'duplicate'] }
]

try {
  // executes sqlStatements in sequential order, all-or-nothing inside a single transaction
  await userbaseSqlJs.execSql({ databaseName: 'my_secret_db', sqlStatements })
} catch (e) {
  // Error: UNIQUE constraint failed: hello.a
}

// sql.js database excludes both of the above SQL statements
const res = sqlJsDb.exec("SELECT * FROM hello");

Additional helpful resources

License

This project is released under the MIT License.