dotalias
dotalias copied to clipboard
Programmatic Interface
Would be great to have a programmatic interface to integrate into other projects.
I'd like to use it with projen.
Hey, @moltar. That's an interesting idea. Do you have some imaginary API in mind that we could expose to help you implement this?
Internally, this library just maps a single declaration file to multiple sources (jest, webpack, etc.). All mapping functions can be described as:
function map(config: AliasConfig): any
But as I understand, you want to use some sort of API so that dotailas
would know about your custom mapping and then expose you the result?
I've looked at projen, and it looks like higher-level tooling. You should be able to use dotalias
with any frameworks/project generators without issues, as dotalias
exposes you configs to insert into the individual tools right away.
Do you have some imaginary API in mind that we could expose to help you implement this?
The original API is almost fine, I think.
The only issue is that it will throw if it can't find the source paths.
https://github.com/open-draft/dotalias/blob/45d6f438cf908d8ab058e1b2fcc969f16db93061/src/index.ts#L10-L12
So, maybe alias
can be a fn that accepts paths, or defaults to discovering them.
alias({ foo: '../foo' }).jest
alias({ foo: '../foo' }).WebpackPlugin
// ...
I've looked at projen, and it looks like higher-level tooling. You should be able to use dotalias with any frameworks/project generators without issues, as dotalias exposes you configs to insert into the individual tools right away.
Right, almost there.
The only thing is that projen does not commit the config files to the filesystem, until all configs are synth'ed in memory.
We can access the config in memory (tsconfig
object) during synth, and I could pass it to alias
. But currently alias
assumes that it will read the files from the filesystem.
I am proposing that alias
should be able to accept existing path config as a parameter without reading anything from disk.
Thanks for the examples! It's much more clear now.
I think we can create a new config
API which would act as you've described:
- Accept an explicit configuration of paths;
- Produce the
alias
-compatible API, exposing the generated configurations for Jest, webpack, etc.
import { config } from 'dotalias'
const alias = config({
server: '../packages/server/'
})
alias.jest
alias.WebpackPlugin
It's important we keep the actual usage identical to the one you get with using alias
that reads the paths from the configuration files in the file system.
One question I have is how should the config
behave if there is a .alias
configuration file in your project? Should it merge two configs, giving the one you pass to config()
the priority? Should it replace the config?
IMO in programmatic use case everything should be explicit without any side effects, e.g. no reading from disk.
Yeap, in favor with you on that 👍
Nice, I think we have the API worked out. Would you be interested in opening a pull request with the draft implementation? I could use your help with this.
Certainly can try.
One thing I am not sure of, is how to handle this part:
https://github.com/open-draft/dotalias/blob/45d6f438cf908d8ab058e1b2fcc969f16db93061/src/index.ts#L10-L12
Since this is in the global scope, this will always throw in the programmatic use case, and it's kind of impossible to hide it now, since index exports alias
that is already resolved.
We can start by moving what's currently in index.ts
to alias.ts
. The index module will then point to both alias
and new configure
:
src/
index.ts
alias.ts
configure.ts
This won't solve the global-scope configuration check just yet. We have two options:
Make alias
a function, so that reading configuration happens when it's invoked.
Pros:
- Encapsulated configuration reading/handling and related errors;
Cons:
- A breaking change;
- Loses a singleton nature; configured will be read everytime you call
alias()
.
Use a Proxy around the alias
object.
This only retain the current API but still requires some sort of memorization of the configuration so we don't read it multiple times.
Expose alias
as an explicit import.
As in:
import { alias } from 'dotalias/alias'
This can also be
dotalias/runtime
or similar.
This way we scope the config reading to that explicit import, instead of exporting alias
from the root-level index.ts
.
Actually, I think this may be a good solution for config
:
import { config } from 'dotalias/config'
config({ ... })
I'd recommend this option. The config
module can be built separately and required to be imported directly, circumventing all the logic from alias
.
What do you think?
Sure, I was considering all these options too, but wasn't sure if breaking change was an option.
Not a huge fan of:
import { config } from 'dotalias/config'
But I think that might be the best option in this case.
Similar patterns exist already, e.g. see:dotenv/config
.
Another thought...
Might be beneficial to expose programmatic API for each converter independently.
The downside is to that approach is that it exposes (right now) internal API, and then makes it harder to move away from it later.
But the benefit is that if you only need one converter, then you don't need to call all other converters to get the full alias object back.
Thoughts?
So basically make toJest
and other converters public?
Yeah.
Because, for example, for our use case, we have no use for Webpack, so it's just extra CPU cycles to create an instance.
Then I suppose it's a replacement for config()
, is that correct?
I can see both APIs being useful but I'd start with the one that immediately covers your use case.
I'm all hands for the following thing:
import { toRollup, toJest } from 'alias/config'
const config = { foo: '../bar/foo' }
const aliasOptions = toRollup(config)
const jestMapperOptions = toJest(config)
Would that be the functionality you're looking for?
By the way, I don't think there's particular trouble exporting the internal converters. I'd pretty much like to do so if it helps people achieve their goals. Converters are not complex and implement the same call signature.
import { toRollup, toJest } from 'alias/config'
Yup, that's what we are looking for!