sql.js
sql.js copied to clipboard
Feature request: Support ES module
Hi,
It would be nice to add a module target to the project.
This would allow to dynamically import the library with import()
function, and would probably work better with some bundlers (thinking about rollup now).
I'm trying to work on it, but I'm not used to work with coffeescript and make, so any help is welcome !
I've had some luck with this adaption: https://pastebin.com/d70TyxZq
const sql = await import("../libs/sql.js/sql-wasm.js");
window.initSqlJs = sql.initSqlJs;
using it together with geopackage.js like this:
...
initSqlJs({ locateFile: filename => "../libs/sql.js/sql-wasm.wasm" })
.then(async (SQL) => {
const u8 = new Uint8Array(buffer);
const data = await geopackage.open(u8);
...
EDIT: Okay, I'm not actually sure if this really works. It does seem to work but apparently geopackage.js bundles it's own sql.js. I still have to import sql.js or I will get an error. So I'm not sure if geopackage ends up using this ES module adaption, or it's own bundled sql.js.
In the previous comment, the linked pastebin uses a modified sql-wasm.js. I think all it really does is add export {initSqlJs};
at the end so it's an easy hack, but it is not the distributed version.
The hack I use instead in the browser is to fetch the official sql-wasm.js as plain text and use that to create a Function that I can call to extract initSqlJs:
/**
* Workaround lack of ES6 support in SQL.js.
*
* https://github.com/sql-js/sql.js/issues/284
*
* Sample usage:
* ```
* import { initSqlJs } from './SqlJs';
*
* initSqlJs(file => `path/to/dist/${file}`).then(SQL => {
* const db = new SQL.Database();
* });
* ```
* @param {function(string): string} fileMap
*/
export async function initSqlJs(fileMap) {
// Get the SqlJs code as a string.
const response = await fetch(fileMap('sql-wasm.js'));
const code = await response.text();
// Instantiate the code and access its exports.
const f = new Function('exports', code);
const exports = {};
f(exports);
// Call the real initSqlJs().
return exports.Module({ locateFile: fileMap });
}
This is still a hack - it may break if/when the SQL.js module wrapper code is changed - but it doesn't require changing the distributed files.
edit: Changed the workaround to provide the same initialization API as SQL.js itself.
I think this makes sql.js unusable from Vite which uses rollup underneath. The page it creates just freezes the whole Google Chrome. Just with simple code:
import initSqlite from "sql.js";
initSqlite({
locateFile: (file) => `https://sql.js.org/dist/${file}`,
}).then((SQL) => {
const db = new SQL.Database();
console.log("SQLite is loaded");
});
This is still a hack
why is this still needed in 2022 ?? : (
Maintainers, are there plans to improve this?
or any one working on a PR ?
The absence of this feature has proved to be a real pain point for use of sql.js in typescript / angular.
Also would love typescript and es modules. Would be nice to use rollup without the hack described above.
I've attempted to make this work with https://github.com/sql-js/sql.js/pull/539.
I've published this as @stephen/sql.js
for now to test in my own projects, though I can't promise that it will not have breaking changes (i.e. also added typescript types there...).
Hi @stephen thanks for going to the trouble of making that!
I can't submit an issue on your fork but I'm hitting some issues and wondered if you can help. I'm finding that the WASM file import is blocked when running
SQL = await import("@stephen/sql.js")
Which causes the import to fail. Don't want to clutter this thread with unrelated error messages/debugging.
Where is appropriate for me to ask you for more info?