skip to Main Content

I have this class (AppProvider.js):

import Provider from '../../node_modules/hydro/src/Provider.js'

export default class extends Provider {

    booting() {
        console.log('AppProvider booting')
    }

    booted() {
        console.log('AppProvider booted')
    }

}

which extends this class (Provider.js):

export default class {

    booting() {
        console.log('Provider booting')
    }

    booting() {
        console.log('Provider booting')
    }

}

I am adding this class as a config value (appConfig.js):

import AppProvider from '../providers/AppProvider.js'

export default {

    providers: [
        AppProvider,
    ],

    database: {
        host: 'prodhost',
    },

}

when i run the app, I get this when i console.log the config:

{
  providers: [ [class default extends default] ],
  database: { host: 'prodhost' }
}

in my package i have the following exports:

export { default as App } from './src/App.js'
export { default as Provider } from './src/Provider.js'

i try and change the import to point to the exact same class, but using the package export rather than via the file path:

import { Provider } from 'hydro'

export default class extends Provider {

    booting() {
        console.log('AppProvider booting')
    }

    booted() {
        console.log('AppProvider booted')
    }

}

and this gives me the following error:

export default class extends Provider {
                             ^
ReferenceError: Cannot access 'Provider' before initialization

so changing this:

import Provider from '../../node_modules/hydro/src/Provider.js'

to this:

import { Provider } from 'hydro'

is causing an error for some reason?

2

Answers


  1. If you look at the Node docs for Mandatory file extensions you will see that:

    A file extension must be provided when using the import keyword to resolve relative or absolute specifiers. Directory indexes (e.g. ‘./startup/index.js’) must also be fully specified.

    The context and evaluation of your import statements is very important. In Node.js Design Patterns (2020), Chapter 2 The Module System they give a very good explanation of how import and export work. I recommend.

    I believe your exact issue may be because of the absence of an exports field:

    Bare specifiers like ‘some-package’ or ‘some-package/shuffle’. They can refer to the main entry point of a package by the package name, or a specific feature module within a package prefixed by the package name as per the examples respectively. Including the file extension is only necessary for packages without an "exports" field.

    You try to add "type": "module" in your node_modules/hydro/src/Provider.js package.json file which will tell node to load it as an ESM module. This may allow you to use the import { Provider } from 'hydro' syntax.

    Login or Signup to reply.
  2. The error you are encountering, "Cannot access ‘Provider’ before initialization," is occurring because of a circular dependency issue in your code. Circular dependencies happen when two or more modules depend on each other, creating a loop that can lead to initialization problems.

    In your code, you have two classes: Provider and AppProvider. AppProvider extends Provider, and Provider is imported from both the local file path and the package export. This creates a circular dependency because Provider is trying to import AppProvider, and AppProvider is trying to import Provider.

    To resolve this issue, you should refactor your code to eliminate the circular dependency. Here’s one possible solution:

    1. Remove the import of Provider from AppProvider.js
    // AppProvider.js
    export default class extends Provider {
      booting() {
        console.log('AppProvider booting');
      }
    
      booted() {
        console.log('AppProvider booted');
      }
    }
    1. Instead of extending Provider directly in AppProvider.js, import it in your appConfig.js and pass it as a dependency to AppProvider:
    // appConfig.js
    import { Provider } from 'hydro';
    import AppProvider from '../providers/AppProvider.js';
    
    export default {
      providers: [AppProvider(Provider)], // Pass Provider as a dependency
      database: {
        host: 'prodhost',
      },
    };
    1. Modify AppProvider.js to accept Provider as a dependency:
    Modify AppProvider.js to accept Provider as a dependency:

    By passing Provider as a dependency to AppProvider, you break the circular dependency, and your code should work as expected.

    This approach ensures that the Provider class is initialized before being used by AppProvider, resolving the "Cannot access ‘Provider’ before initialization" error.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search