The error message "better-sqlite3 TypeError: o.default is not a constructor" indicates that

As part of my vscode extension development in typescript, webpack, and better-sqlite3, I am attempting to create a database within the

C:\Users\userName\AppData\Roaming\Code\User\globalStorage\
folder.

However, when executing the code, I encounter the following error:

TypeError: o.default is not a constructor

The code snippet causing this error is as follows:


import Database from 'better-sqlite3';
import * as fs from "fs";
import { DatabaseNames } from "./database-names.enum";
import { PersistenceRepository } from './persistence.repository';

export class BetterSqliteAdapter implements PersistenceRepository {

    private static instance: BetterSqliteAdapter | null = null;

    db: Database.Database | null = null;

    private constructor() { };

    public static getInstance() {
        if (!this.instance) {
            this.instance = new BetterSqliteAdapter();
        }
        return this.instance;
    }

    createDatabase(name: DatabaseNames, globalStoragePath: string): void {
        const dbPath = globalStoragePath + "\\" + name + ".db";
        console.log('dbPath :>> ', dbPath);
        if (!fs.existsSync(globalStoragePath)) {
            throw new Error('Extension folder don\'t exist');
        }
        if (!fs.existsSync(dbPath)) {
            try {
                this.db = new Database(dbPath);

            } catch (error) {
                console.log(`Error creating database: ${name}.db ...  error: ${error}`);
            }
        }
    }

This is the tsconfig.json:

{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES2020",
    "lib": ["ES2020", "DOM"],
    "sourceMap": true,
    "rootDir": "src",
    "strict": true ,
    "jsx": "react",
    "esModuleInterop": true
  }
}

I have also referred to this link (How to correctly and fully import BetterSqlite3's Database class in typescript?), but unfortunately, it did not resolve the issue.

Update:

The persistence.repository.ts:

import { DatabaseNames } from './database-names.enum';

export interface PersistenceRepository {

    /**
     * This method will check if a database with a specific name existe, if not, it will be created.
     * @param name name of the database to check if exist or create.
     */
    createDatabase(name: DatabaseNames, globalStoragePath: string): void;

}

Given that this involves developing a vscode extension, I typically launch it by pressing F5. Here is the launch.json configuration (it's the default launch.json from yo-code extension creator):

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Run Extension",
            "type": "extensionHost",
            "request": "launch",
            "args": [
                "--extensionDevelopmentPath=${workspaceFolder}"
            ],
            "outFiles": [
                "${workspaceFolder}/dist/**/*.js"
            ],
            "preLaunchTask": "${defaultBuildTask}"
        },
        {
            "name": "Extension Tests",
            "type": "extensionHost",
            "request": "launch",
            "args": [
                "--extensionDevelopmentPath=${workspaceFolder}",
                "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
            ],
            "outFiles": [
                "${workspaceFolder}/out/**/*.js",
                "${workspaceFolder}/dist/**/*.js"
            ],
            "preLaunchTask": "tasks: watch-tests"
        }
    ]
}

This is the tasks.json:

{
    "version": "2.0.0",
    "tasks": [
        {
            "type":"npm",
            "script": "watch",
            "problemMatcher": "$ts-webpack-watch",
            "isBackground": true,
            "presentation": {
                "reveal": "never",
                "group": "watchers"
            },
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "type": "npm",
            "script": "watch-tests","problemMatcher": "$tsc-watch",
            "isBackground": true,
            "presentation": {
                "reveal": "never",
                "group": "watchers"
            },
            "group": "build"
        },
        {
            "label": "tasks: watch-tests",
            "dependsOn": [
                "npm: watch",
                "npm: watch-tests"
            ],
            "problemMatcher": []
        }
    ]
}

Here are the script commands and dependencies from the package.json:

"scripts": {
    ...
  },
  "devDependencies": {
    ...
  },
  "dependencies": {
    ...
  }

Update 2:

After some troubleshooting steps, which included deleting node modules, uninstalling and re-installing better-sqlite3, I encountered the following error:

TypeError: Cannot read properties of undefined (reading 'indexOf')
.

Remarkably, removing the try / catch block prevents any errors from being thrown.

Update 3:

Following another attempt at deleting node modules, uninstalling better-sqlite3, and re-installing it AGAIN, I am back to encountering the initial error message.

Update 4:

To verify permissions and project configuration, I attempted to create a file directly using 'fs'. Surprisingly, it worked without issues. The modified code snippet is:

 createDatabase(name: DatabaseNames, globalStoragePath: string): void {
    ...
    fs.writeFileSync(dbPath, '');
    ...
}

Answer №1

After conducting extensive research, it has been determined that using a library for SQLite directly in the development of a vscode extension is currently not feasible. This limitation arises when working with local files as opposed to an in-memory database due to the requirement of different binaries for each operating system.

One potential workaround involves configuring the webpack.config.js file as follows:

    externals: {
      "better-sqlite3": "commonjs better-sqlite3",
    },

However, users will need to ensure that the necessary binaries are installed on their computers for this solution to work effectively.

Sources providing information on this topic:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Efficient management of pre-built assets in Vite

I am currently developing a Vue application using Vite. Within the content folder, I have numerous files (ranging from 10 to 100) located as follows: content/block/paragraph.json content/block/theorem.json content/inliner/link.json ... My goal is to creat ...

Issues with type errors in authentication wrapper for getServerSideProps

While working on implementing an auth wrapper for getServerSideProps in Next.js, I encountered some type errors within the hook and on the pages that require it. Below is the code for the wrapper along with the TypeScript error messages. It's importan ...

Retrieve the svg file either from the DOM or the Object element

Is there a way for me to save or download a .svg file from the DOM? I have integrated my svg file into an Object element and am dynamically updating certain elements within the SVG and customizing it in my Angular 7 application. <object id="svg1" data= ...

The offline functionality of the Angular Progressive Web App(PWA) is experiencing difficulties

As per the official guidelines, I attempted to create a PWA that functions in offline mode using pure PWA without angular-cli. However, despite following the official instructions, I was unable to make it work offline. The document in question can be foun ...

What is the best way to determine if a local storage key is not present?

By applying the if condition below, I can determine whether or not the local storage key exists: this.data = localStorage.getItem('education'); if(this.data) { console.log("Exists"); } To check for its non-existence using an if conditi ...

Challenge when providing particular strings in Typescript

Something seems to be wrong with the str variable on line number 15. I would have expected the Typescript compiler to understand that str will only ever have the values 'foo' or 'bar' import { useEffect } from 'react' type Ty ...

Switch up the Angular base URL using ngx-translate

I successfully integrated ngx-translate into my Angular project. Now, I want to dynamically change the base href based on the language selected from the header menu. Currently, the URL appears as: "localhost:4200". However, upon launching the project, it ...

The mat-slide-toggle updates the values for all products, with each value being unique

In my app, I am using Material slide-toggle to control the activation status of products. However, I am facing the following issues: Whenever I toggle one product, it affects the values of all other products as well. The displayed value does not match t ...

Retrieve all articles from a user using the TypeORM - findAll function

Is there a way to retrieve all articles of a specific user using the TypeORM package? In Sequelize, I have the following function: async findAllByUser(userUuid: string, findOptions: object): Promise<Article[]> { return await Article.findAll< ...

Use Angular's super.ngOnDestroy method for handling cleanup/unsubscribing

When it comes to unsubscribing / cleaning up from observables in Angular components (using ngOnDestroy), there are multiple options available. Which option should be considered the most preferable and why? Also, is it a good practice to include super.ngOnD ...

Is it necessary to sanitize input fields manually in Angular 6?

Is it necessary for me to manually sanitize all user inputs, or does Angular handle this process automatically? In my login form, the data is sent to the server upon submission. Do I need to explicitly sanitize the data, or does Angular take care of sanit ...

Stop images from constantly refreshing upon each change of state - React

Within my component, I have incorporated an image in the following way: <div className="margin-10 flex-row-center"> <span> <img src={spinner} className="spinner" /> ...

Using ngFor to Filter Tables in Angular 5

Are you in the midst of implementing multiple data filters in an Angular Application that displays data using a Table and ngFor? You may have explored different methods such as using Pipe in Type Script, but discovered that it is not recommended accordin ...

Is there a way to access the value or key of a JSON property in an Angular template for rendering purposes?

Having trouble displaying the JSON values of certain properties on screen. Utilizing Angular Material table to showcase my JSON response. The code snippet below is responsible for rendering the JSON data: <mat-card-content class="dashboard-card-cont ...

Tips for enabling custom object properties in Chrome DevTools

In my typescript class, I am utilizing a Proxy to intercept and dispatch on get and set operations. The functionality is working smoothly and I have successfully enabled auto-completion in vscode for these properties. However, when I switch to the chrome d ...

Refreshing Form in Angular 2

When I remove a form control from my form, it causes the form to always be invalid. However, if I delete a character from another input field and then add the same character back in (to trigger a change event), the form becomes valid as expected. Is ther ...

Error: Unable to access the property of an undefined variable in Angular 4

Here is what I currently have in my code: <p *ngIf="model.something.satisfy"> Yes </p> <p *ngIf="!model.something.satisfy"> {{model.something.comments}} </p> The issue arises in the second line with the error message "Type ...

Vercel encountered issues with "validating code quality and type correctness" during deployment but was successful when performed locally

Running "next build" locally and "vercel build" both work smoothly. However, once deployed to vercel, the "Linting and checking validity of types" fails during the build process. It seems like TypeScript is stricter when building on vercel even with the sa ...

Guide on combining vendor CSS files in a React application using Webpack

Incorporating third-party libraries is an essential part of my project. For example, I have Mapbox GL installed via npm, which comes with CSS files needed for its functionality. The Mapbox GL CSS file can be found at mapbox-gl/dist/mapbox-gl.css in the no ...

What is the reason for a type narrowing check on a class property failing when it is assigned to an aliased variable?

Is there a way to restrict the type of property of a class in an aliased conditional expression? Short: I am trying to perform a type narrowing check within a class method, like this._end === null && this._head === null, but I need to assign the r ...