TryGhost / node-sqlite3

SQLite3 bindings for Node.js
BSD 3-Clause "New" or "Revised" License
6.23k stars 817 forks source link

Getting "Could not locate the bindings file" when trying to open DB in Angular 17 SSR project (ExpressJs) #1783

Open coltossoff opened 6 months ago

coltossoff commented 6 months ago

Issue Summary

I'm trying to add a Sqlite Db to the Express server part of my Angular SSR project. I installed sqlite3and @types/sqlite3 which seemed to work. But, when I try new Database('./sqlite.db') I get the below runtime errors after compiling. I'm not clear what I haven't installed or configured correctly. The application is running properly as soon as I remove this line.

tsconfig.json

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "ES2022",
    "module": "ES2022",
    "useDefineForClassFields": false,
    "esModuleInterop": true,
    "lib": [
      "ES2022",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  }
}

package.json

{
  "name": "test-prep",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "dev:ssr": "ng run testPrep:serve-ssr",
    "serve:ssr": "node dist/testPrep/server/main.js",
    "build:ssr": "ng build && ng run testPrep:server",
    "prerender": "ng run testPrep:prerender"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^17.3.6",
    "@angular/common": "^17.3.6",
    "@angular/compiler": "^17.3.6",
    "@angular/core": "^17.3.6",
    "@angular/forms": "^17.3.6",
    "@angular/platform-browser": "^17.3.6",
    "@angular/platform-browser-dynamic": "^17.3.6",
    "@angular/platform-server": "^17.3.6",
    "@angular/router": "^17.3.6",
    "@angular/ssr": "^17.3.6",
    "@types/sqlite3": "^3.1.11",
    "express": "^4.18.2",
    "rxjs": "~7.8.0",
    "sqlite3": "^5.1.7",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.3.6",
    "@angular/cli": "^17.3.6",
    "@angular/compiler-cli": "^17.3.6",
    "@types/express": "^4.17.17",
    "@types/jasmine": "~4.3.0",
    "@types/node": "^18.19.31",
    "browser-sync": "^3.0.0",
    "jasmine-core": "~4.6.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "typescript": "~5.3.3"
  }
}

server.ts

import 'zone.js/node';

import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import * as express from 'express';
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import AppServerModule from './src/main.server';
import { Database } from 'sqlite3';

// The Express app is exported so that it can be used by serverless Functions.
export async function app(): Promise<express.Express> {
  const server = express.default();
  const distFolder = join(process.cwd(), 'dist/testPrep/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html'))
    ? join(distFolder, 'index.original.html')
    : join(distFolder, 'index.html');

  const commonEngine = new CommonEngine();

  server.set('view engine', 'html');
  server.set('views', distFolder);

  new Database('./sqlite.db')
  // Example Express Rest API endpoints
  // server.get('/api/**', (req, res) => { });
  // Serve static files from /browser
  server.get('*.*', express.static(distFolder, {
    maxAge: '1y'
  }));

  // All regular routes use the Angular engine
  server.get('*', (req, res, next) => {
    const { protocol, originalUrl, baseUrl, headers } = req;

    commonEngine
      .render({
        bootstrap: AppServerModule,
        documentFilePath: indexHtml,
        url: `${protocol}://${headers.host}${originalUrl}`,
        publicPath: distFolder,
        providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
      })
      .then((html) => res.send(html))
      .catch((err) => next(err));
  });

  return server;
}

async function run(): Promise<void> {
  const port = process.env['PORT'] || 4000;

  // Start up the Node server
  const server = await app();
  server.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
  run();
}

export default AppServerModule;

Relevant logs or output

Compiled successfully.
./node_modules/bindings/bindings.js:135
  throw err;
  ^

Error: Could not locate the bindings file. Tried:
 → C:\repos\AngularSignalsDemo\build\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\build\Debug\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\build\Release\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\out\Debug\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\Debug\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\out\Release\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\Release\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\build\default\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\compiled\22.0.0\win32\x64\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\addon-build\release\install-root\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\addon-build\debug\install-root\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\addon-build\default\install-root\node_sqlite3.node
 → C:\repos\AngularSignalsDemo\lib\binding\node-v127-win32-x64\node_sqlite3.node
    at bindings (./node_modules/bindings/bindings.js:126:9)
    at Object.47 (./node_modules/sqlite3/lib/sqlite3-binding.js:1:37)
    at __webpack_require__ (./webpack/bootstrap:19:1)
    at Object.815 (./node_modules/sqlite3/lib/sqlite3.js:2:17)
    at __webpack_require__ (./webpack/bootstrap:19:1)
    at 69787 (C:\repos\AngularSignalsDemo\dist\testPrep\server\main.js:32:65)
    at __webpack_require__ (./webpack/bootstrap:19:1)
    at <anonymous> (./webpack/bootstrap:36:1)
    at Function.__webpack_require__.O (./webpack/runtime/chunk%20loaded:23:1)
    at __webpack_require__.x (./webpack/bootstrap:37:1) {
  tries: [
    'C:\\repos\\AngularSignalsDemo\\build\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\build\\Debug\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\build\\Release\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\out\\Debug\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\Debug\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\out\\Release\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\Release\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\build\\default\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\compiled\\22.0.0\\win32\\x64\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\addon-build\\release\\install-root\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\addon-build\\debug\\install-root\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\addon-build\\default\\install-root\\node_sqlite3.node',
    'C:\\repos\\AngularSignalsDemo\\lib\\binding\\node-v127-win32-x64\\node_sqlite3.node'
  ]
}

Node.js v22.0.0
A server error has occurred.
node exited with 1 code.

Version

5.1.7

Node.js Version

22.0.0

How did you install the library?

Windows 11, Angular SSR 17.3.6, Express 4.18.2

matissoz commented 4 months ago

This worked for me

npm install sqlite3
ls node_modules/sqlite3 # folder `build` does not exist, hence the error messages about missing bindings
cd node_modules/sqlite3
npm run rebuild 
ls build # now exists 🥳
cd ../..

Here is the original answer

Jim-Elijah commented 1 month ago

In my case when I run vscode extension development host, although node_modules/sqlite3/build/Release/*.node exists, error occured like this: Could not locate the bindings file. Tried: → /home/USERNAME/project/build/node_sqlite3.node → /home/USERNAME/project/build/Debug/node_sqlite3.node → ...

I just copy node_sqlite3.node to build, and it is solved. Since webpack is used to pack vscode extension, so I use copy-webpack-plugin to do the copy job. Snippet like below:

 plugins: [
    new CopyWebpackPlugin({
      patterns: [
        { from: path.resolve(__dirname, "node_modules/sqlite3/build/Release/node_sqlite3.node"), to: path.resolve(__dirname, "build/node_sqlite3.node") }
      ]
    })
  ],