beemojs / beemo

🤖 Centralized configuration layer for dev tools. Beep boop.
https://beemo.dev
MIT License
143 stars 9 forks source link

Allow custom Drivers to be defined in the scope of the provider #144

Open niieani opened 3 years ago

niieani commented 3 years ago

Hi Miles! First of all, amazing work on the package, loving the work so far - thank you! 🙇

Since writing drivers isn't documented, after a lot of trial and error I've kinda reverse engineered how they work. I understand the limitation is that drivers need to be external packages. This is a huge pain, especially when trying out stuff.

It would be great if we could write Drivers locally scoped to the provider, the same way we can do it for Scripts, i.e. by creating a directory drivers under the provider root.

I've worked around this personally by manually loading the local driver in the bootstrap of my provider (src/index.ts):

export default async function bootstrap(tool: Tool) {
  const {vite} = tool.config.settings
  if (vite) {
    await tool.driverRegistry.load(
      require.resolve('../drivers/Vite.ts'),
      undefined,
      {tool},
    )
  }
}

Unfortunately that this means my consumer can't define the driver in the driver array like:

  drivers: ['eslint', 'jest', 'prettier', 'typescript', 'vite'],

But instead I need to provide the configuration options in the settings:

export default {
  module: '@niieani/beemo-build-tools',
  drivers: ['babel', 'eslint', 'jest', 'prettier', 'typescript'],
  settings: {
    vite: {},
  },
} as BeemoConfig

It would be great if this module-scoped driver resolution was supported out-of-the-box!

milesj commented 3 years ago

@niieani I agree, but I'm not sure what the config would look like for consumers. When configuring the drivers, it must be a file system path or a node module, and I'm not sure there's another option here (the plugin system is abstracted outside of Beemo).

This is a bit janky, but may work.

export default {
  module: '@niieani/beemo-build-tools',
  drivers: ['babel', 'eslint', 'jest', 'prettier', 'typescript', './node_modules/@niieani/beemo-build-tools/drivers/Vite.js'],
  settings: {
    vite: {},
  },
} as BeemoConfig

Or even easier with require.resolve.

export default {
  module: '@niieani/beemo-build-tools',
  drivers: ['babel', 'eslint', 'jest', 'prettier', 'typescript', require.resolve('@niieani/beemo-build-tools/drivers/Vite.js')],
  settings: {
    vite: {},
  },
} as BeemoConfig
niieani commented 3 years ago

Since module is literally the property above ('@niieani/beemo-build-tools'), couldn't Beemo itself try resolving it relative to it, aside from looking at installed node_modules?

milesj commented 3 years ago

@niieani I'd rather not. When fs paths are used, it's not apparent where they would resolve from. Cwd? Parent dir? Config module? Supplying absolute paths is typically the path of least resistance (require.resolve, path.join(__dirname), etc).

niieani commented 3 years ago

OK, gotcha. Thanks for the quick reply.

Aren't Scripts being loaded relative to the provider module already today? Couldn't Drivers just use the same resolution mechanisms?

https://github.com/beemojs/beemo/blob/665f37ba8d6b8555bc5c67bdca46702dc042688a/packages/core/src/routines/RunScriptRoutine.ts#L98-L110

If absolute path work today, then that's a fair enough workaround. Would be good to have it documented though.