-
Notifications
You must be signed in to change notification settings - Fork 133
Use Node.js native sqlite instead of better-sqlite3 #1357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Maybe it is better to move to nodejs build-in sql support https://nodejs.org/api/sqlite.html (available from Node 22) Spago next is a new tool and still not widely used so I don't think that there need to worry about old node version and ignore node platform development. |
|
@wclr sure, let's get some buy-in first from the maintainers and then we can also go that route. Main motivation is to avoid having to rebuild spago for different node versions. |
Replaces @libsql/client with Node.js's built-in node:sqlite module. Changes: - Replace libsql/turso client with DatabaseSync from node:sqlite - Remove @libsql/client dependency from package.json - Remove --external:@libsql/client from bundler config - Add NODE_NO_WARNINGS=1 to suppress experimental sqlite warnings - Add explicit directory creation (was built-in with better-sqlite3) - Use db.exec() for PRAGMA statements (db.pragma() doesn't exist) - Wrap all operations in Promise.resolve() for FFI compatibility Benefits: - Zero external dependencies for SQLite - Simpler implementation (no remote database support needed) - Nearly identical API to the original better-sqlite3 version All tests pass (235/239, same as baseline - 4 pre-existing failures unrelated to SQLite changes).
- Add missing getMetadataImpl export (was declared in FFI but not exported) - Use --no-warnings flag to suppress experimental SQLite warnings - In bin/index.dev.js shebang for direct execution - In test/Prelude.purs when spawning spago in tests - Add trailing newline to Db.js
bin/index.dev.js
Outdated
| @@ -1,4 +1,4 @@ | |||
| #!/usr/bin/env node | |||
| #!/usr/bin/env -S node --no-warnings | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing all the warnings is a terrible idea for a set of reasons 😄
Let's just exclude the warnings for experimental modules: --no-warnings=ExperimentalWarning
| FS.mkdirp Paths.globalCachePath | ||
| logDebug $ "Global cache: " <> Path.quote Paths.globalCachePath | ||
|
|
||
| -- Make sure we have git and purs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Node will fail with a horrible error if it doesn't find the module, so I think we should catch it at the startup and error out then.
Implementation sketch:
import Data.Int as Int
import Data.String as String
import Effect.Console as Console
import Node.Process as Process
-- first thing inside main:
main = do
-- Check that we're running on Node.js >= 22.5.0 (required for node:sqlite)
let
-- version is like "v22.5.0" or "22.5.0"
versionStr = String.stripPrefix (String.Pattern "v") Process.version
# fromMaybe Process.version
parts = String.split (String.Pattern ".") versionStr
case Array.take 2 parts >>= traverse Int.fromString of
Just [major, minor]
| major > 22 -> pure unit
| major == 22 && minor >= 5 -> pure unit
| otherwise -> do
Console.error $ "Error: spago requires Node.js v22.5.0 or later (found " <> Process.version <> ")"
Process.exit' 1
_ -> do
-- couldn't parse, issue a warning and let it crash later
..together with this we should also add the engines field to the package.json. Node won't enforce it on install, but will complain about it:
{
"engines": {
"node": ">=22.5.0"
}
}
src/Spago/Db.js
Outdated
| fs.mkdirSync(dir, { recursive: true }); | ||
| } | ||
| } catch (err) { | ||
| // ignore - will fail later if needed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we ignoring the error here?
src/Spago/Db.js
Outdated
| .prepare("SELECT * FROM package_sets WHERE compiler = ? ORDER BY date DESC LIMIT 1") | ||
| .get(compiler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we use positional arguments in a few places, we should use them everywhere, e.g.:
| .prepare("SELECT * FROM package_sets WHERE compiler = ? ORDER BY date DESC LIMIT 1") | |
| .get(compiler); | |
| .prepare("SELECT * FROM package_sets WHERE compiler = @compiler ORDER BY date DESC LIMIT 1") | |
| .get({ compiler }); |
src/Spago/Db.js
Outdated
| .all(); | ||
| return row; | ||
| } | ||
| return Promise.resolve().then(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing code is in Effect, and this database code is sync as well, why turn everything into Promises?
- Use Node.js native node:sqlite module (requires Node >= 22.5.0). - Refactor DB layer to use synchronous API and named parameters. - Add Node.js version check at startup. - Suppress ExperimentalWarning in dev and bundle entry points. - Address review comments from @f-f.
af35edb to
ee76757
Compare
- Use Node.js native node:sqlite module (requires Node >= 22.5.0). - Refactor DB layer to use synchronous API and named parameters. - Add Node.js version check at startup with helpful warning. - Scope ExperimentalWarning suppression to the database connection logic. - Update package.json engines field. - Update bin/index.dev.js shebang to suppress ExperimentalWarning. - Address review comments from @f-f.
ee76757 to
d394531
Compare
Replace better-sqlite3 with Node.js's built-in
node:sqlitemodule to avoid native compilation dependencies.Changes
@libsql/client(turso) with Node.js nativenode:sqlitemoduleBenefits
Testing
All tests pass: 235/239 (same as baseline - 4 pre-existing failures unrelated to SQLite changes)
Note
The
node:sqlitemodule is marked as experimental in Node.js, but it's stable enough for our use case. The warning is suppressed in the CLI entry point.