sql-js / sql.js

A javascript library to run SQLite on the web.
http://sql.js.org
Other
12.39k stars 1.06k forks source link

Feature request: Support ES module #284

Open Gladear opened 4 years ago

Gladear commented 4 years ago

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 !

m-schuetz commented 4 years ago

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.

rhashimoto commented 3 years ago

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.

Ciantic commented 2 years ago

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");
});
gotjoshua commented 1 year ago

This is still a hack

why is this still needed in 2022 ?? : (

skypack score

Maintainers, are there plans to improve this?

or any one working on a PR ?

johncardiologs commented 1 year ago

The absence of this feature has proved to be a real pain point for use of sql.js in typescript / angular.

anaestheticsapp commented 1 year ago

Also would love typescript and es modules. Would be nice to use rollup without the hack described above.

stephen commented 1 year ago

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...).

Robin-Lord commented 1 year ago

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?