Skip to content

Commit

Permalink
introduce wa-sqlite for music-store example
Browse files Browse the repository at this point in the history
  • Loading branch information
tantaman committed Jul 29, 2022
1 parent dacf87d commit 921e403
Show file tree
Hide file tree
Showing 13 changed files with 1,527 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This project implements [CRDTs](https://crdt.tech/) and [CRRs](https://hal.inria

[![loom](https://cdn.loom.com/sessions/thumbnails/0934f93364d340e0ba658146a974edb4-with-play.gif)](https://www.loom.com/share/0934f93364d340e0ba658146a974edb4)

I'm working on a demo application to show how to use cfsqlite in practice. This will live in `examples/music-app`.
I'm working on a demo application to show how to use cfsqlite in practice. This will live in `examples/music-store`.

You can view a conflict-free DB in action in the `__tests__` folder of the `replicator` package: https://github.com/tantaman/conflict-free-sqlite/blob/main/prototype/replicator/src/__tests__/merge-random-2.test.ts

Expand Down
Empty file.
File renamed without changes.
18 changes: 18 additions & 0 deletions prototype/examples/music-store/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html lang="en">
<html>

<head>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="viewport" content="width=device-width, initial-scale=1.0,
user-scalable=no">
<title>CF Music</title>
</head>

<body>
<div id="app"></div>
<script type="module" src="./src/main.tsx"></script>
</body>

</html>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@cfsql/music-app",
"version": "0.0.1",
"description": "",
"main": "dist/index.js",
"main": "dist/main.js",
"type": "module",
"scripts": {
"build": "tsc --noEmit",
Expand All @@ -11,10 +11,11 @@
},
"keywords": [],
"author": "",
"license": "ISC",
"license": "GPL",
"dependencies": {
"@cfsql/replicator": "workspace:*",
"nanoid": "^4.0.0"
"nanoid": "^4.0.0",
"wa-sqlite": "github:rhashimoto/wa-sqlite#buildless"
},
"devDependencies": {
"@types/node": "^17.0.45",
Expand Down
61 changes: 61 additions & 0 deletions prototype/examples/music-store/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import SQLiteAsyncESMFactory from "wa-sqlite/dist/wa-sqlite-async.mjs";
import * as SQLite from "wa-sqlite";
import { IDBBatchAtomicVFS } from "./wa-sqlite/vfs/IDBBatchAtomicVFS.js";

async function hello() {
const module = await SQLiteAsyncESMFactory();
const sqlite3 = SQLite.Factory(module);
sqlite3.vfs_register(
new IDBBatchAtomicVFS("idb-batch-atomic", { durability: "relaxed" })
);

const db = await sqlite3.open_v2(
"music-store",
SQLite.SQLITE_OPEN_CREATE |
SQLite.SQLITE_OPEN_READWRITE |
SQLite.SQLITE_OPEN_URI,
"idb-batch-atomic"
);

const sql = tag(sqlite3, db);

console.log(await sql`SELECT 'Hello, world!'`);
// await sqlite3.exec(db, `SELECT 'Hello, world!'`, (row, columns) => {
// console.log(row);
// });
await sqlite3.close(db);
}

// from wa-sqlite demo -- https://github.com/rhashimoto/wa-sqlite/blob/66bc483115d8c5bb37abd5939cd51dd71f973998/src/examples/tag.js#L21
export function tag(sqlite3: SQLiteAPI, db: number) {
return async function (strings: TemplateStringsArray, ...values) {
// Assemble the template string components.
const interleaved: string[] = [];
strings.forEach((s, i) => {
interleaved.push(s, values[i]);
});
const sql = interleaved.join("");

// Loop over the SQL statements. sqlite3.statements is an API
// convenience function (not in the C API) that iterates over
// compiled statements, automatically managing resources.
const results: { columns: string[]; rows: any[] }[] = [];
for await (const stmt of sqlite3.statements(db, sql)) {
const rows: any[] = [];
const columns = sqlite3.column_names(stmt);
while ((await sqlite3.step(stmt)) === SQLite.SQLITE_ROW) {
// Collect row elements. sqlite3.row is an API convenience
// function (not in the C API) that extracts values for all
// the columns of the row.
const row = sqlite3.row(stmt);
rows.push(row);
}
if (columns.length) {
results.push({ columns, rows });
}
}
return results;
};
}

hello();
168 changes: 168 additions & 0 deletions prototype/examples/music-store/src/wa-sqlite/VFS.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright 2022 Roy T. Hashimoto. All Rights Reserved.
import * as VFS from "./sqlite-constants.js";
export * from "./sqlite-constants.js";

// Base class for a VFS.
export class Base {
mxPathName = 64;

/**
* @param {number} fileId
* @returns {number|Promise<number>}
*/
xClose(fileId) {
return VFS.SQLITE_IOERR;
}

/**
* @param {number} fileId
* @param {{ size: number, value: Int8Array }} pData
* @param {number} iOffset
* @returns {number|Promise<number>}
*/
xRead(fileId, pData, iOffset) {
return VFS.SQLITE_IOERR;
}

/**
* @param {number} fileId
* @param {{ size: number, value: Int8Array }} pData
* @param {number} iOffset
* @returns {number|Promise<number>}
*/
xWrite(fileId, pData, iOffset) {
return VFS.SQLITE_IOERR;
}

/**
* @param {number} fileId
* @param {number} iSize
* @returns {number|Promise<number>}
*/
xTruncate(fileId, iSize) {
return VFS.SQLITE_IOERR;
}

/**
* @param {number} fileId
* @param {*} flags
* @returns {number|Promise<number>}
*/
xSync(fileId, flags) {
return VFS.SQLITE_OK;
}

/**
* @param {number} fileId
* @param {{ set: function(number): void }} pSize64
* @returns {number|Promise<number>}
*/
xFileSize(fileId, pSize64) {
return VFS.SQLITE_IOERR;
}

/**
* @param {number} fileId
* @param {number} flags
* @returns {number|Promise<number>}
*/
xLock(fileId, flags) {
return VFS.SQLITE_OK;
}

/**
* @param {number} fileId
* @param {number} flags
* @returns {number|Promise<number>}
*/
xUnlock(fileId, flags) {
return VFS.SQLITE_OK;
}

/**
* @param {number} fileId
* @param {{ set: function(number): void }} pResOut
* @returns {number|Promise<number>}
*/
xCheckReservedLock(fileId, pResOut) {
pResOut.set(0);
return VFS.SQLITE_OK;
}

/**
* @param {number} fileId
* @param {number} flags
* @param {{ value: Int8Array }} pOut
* @returns {number|Promise<number>}
*/
xFileControl(fileId, flags, pOut) {
return VFS.SQLITE_NOTFOUND;
}

/**
* @param {number} fileId
* @returns {number|Promise<number>}
*/
xSectorSize(fileId) {
return 512;
}

/**
* @param {number} fileId
* @returns {number|Promise<number>}
*/
xDeviceCharacteristics(fileId) {
return 0;
}

/**
* @param {string?} name
* @param {number} fileId
* @param {number} flags
* @param {{ set: function(number): void }} pOutFlags
* @returns {number|Promise<number>}
*/
xOpen(name, fileId, flags, pOutFlags) {
return VFS.SQLITE_CANTOPEN;
}

/**
*
* @param {string} name
* @param {number} syncDir
* @returns {number|Promise<number>}
*/
xDelete(name, syncDir) {
return VFS.SQLITE_IOERR;
}

/**
* @param {string} name
* @param {number} flags
* @param {{ set: function(number): void }} pResOut
* @returns {number|Promise<number>}
*/
xAccess(name, flags, pResOut) {
return VFS.SQLITE_IOERR;
}

/**
* Handle asynchronous operation. This implementation will be overriden on
* registration by an Asyncify build.
* @param {function(): Promise<number>} f
* @returns {Promise<number>}
*/
handleAsync(f) {
return f();
}
}

export const FILE_TYPE_MASK = [
VFS.SQLITE_OPEN_MAIN_DB,
VFS.SQLITE_OPEN_MAIN_JOURNAL,
VFS.SQLITE_OPEN_TEMP_DB,
VFS.SQLITE_OPEN_TEMP_JOURNAL,
VFS.SQLITE_OPEN_TRANSIENT_DB,
VFS.SQLITE_OPEN_SUBJOURNAL,
VFS.SQLITE_OPEN_SUPER_JOURNAL,
].reduce((mask, element) => mask | element);
Loading

0 comments on commit 921e403

Please sign in to comment.