Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No documentation around custom resolvers #7014

Closed
jakesylvestre opened this issue Oct 18, 2018 · 11 comments
Closed

No documentation around custom resolvers #7014

jakesylvestre opened this issue Oct 18, 2018 · 11 comments

Comments

@jakesylvestre
Copy link

jakesylvestre commented Oct 18, 2018

tracking: adonisjs/discussion/issues/65

Aside from the description on #6132 (which doesn't give many usage details), there's also no documentation on the .flowconfig webpage. I do see in the changelog it says:

Allow custom module resolvers (experimental, only works with the haste resolver system).

But I'd at least like to see an implementation example in the PR. I know there have been a few variants of "custom resolver" requests including #2939, #293.

So I'm using a framework adonisjs/adonis-framework . The framework operates similarly to @laravel/@symfony in that you have an IoC container and allows for dependency injection. The IoC is a package called adonis-fold. Real world use looks something like this:

'use strict'

const Redis = use('Redis')
const User = use('App/Models/User')

class UsersController {

  async index () {
    const cachedUsers = await Redis.get('users')
    if (cachedUsers) {
      return JSON.parse(cachedUsers)
    }

    const users = await User.all()
    await Redis.set('users', JSON.stringify(users))
    return users
  }
}

use() is a global that hits the IoC container which binds the namespace 'Redis' to something like this:

const Redis = require('./Redis')
const { ioc } = require('@adonisjs/fold')

ioc.bind('My/Redis', function (app) {
  const Config = app.use('Adonis/Src/Config')
  return new Redis(Config)
})

The use() keyword can be used to load any of the providers in adonis which are loaded as an array when the application boots. Essentially, we want a way to create a custom resolver as is described here but for flow. The project is also trying to get setup on typescript so the issues do overlap quite a bit.

For reference this is the code for the use method:

  use (namespace) {
    if (this._hasFake(namespace)) {
      return this._resolveFake(namespace)
    }

    if (this._isBinding(namespace)) {
      return this._resolveBinding(namespace)
    }

    if (this._isAlias(namespace)) {
      return this.use(this._aliases[namespace])
    }

    if (this._isAutoloadedPath(namespace)) {
      return this._resolveAutoloadedPath(namespace)
    }

    return this._require(namespace)
  }

How can I resolve this?

@jakesylvestre jakesylvestre changed the title No documentation around #6132 custom resolvers No documentation around custom resolvers Oct 18, 2018
@arcanis
Copy link

arcanis commented Oct 18, 2018

The custom resolver option takes the path to a long-running binary that Flow starts and communicates with using a line-by-line stdin/stdout formatted with JSON. An implementation can be found in the PnP resolver used by Yarn:

https://github.com/yarnpkg/yarn/blob/master/src/util/generate-pnp-map-api.tpl.js#L832-L849

@villesau
Copy link
Contributor

villesau commented Oct 18, 2018

@arcanis Wow this is pretty cool! Does it mean that we could validate e.g css modules with custom resolver? Or at least that the css class names are present?

@arcanis
Copy link

arcanis commented Oct 18, 2018

No, it's just a resolver (it just tells Flow which file to load when file X makes a require(Y) call), it doesn't allow you to do this kind of complicated logic (yet, at least) 🙂

@villesau
Copy link
Contributor

Oh ok, thanks! Do you think that it would be difficult to implement? I see that this could have huge potential to build full blown plugin system to flow!

@arcanis
Copy link

arcanis commented Oct 18, 2018

It'll doable but difficult. The main issue tho it's that it'll likely involve some architectural changes in the way Flow loads its files, which means that we first have to reach a consensus on what's the best way to do it (and if we want to do it!).

@jakesylvestre
Copy link
Author

@arcanis thanks, that should work for our use case. As far as actually passing something like https://github.com/yarnpkg/yarn/blob/master/src/util/generate-pnp-map-api.tpl.js#L832-L849 to flow, how is that done would that use the flow config?

Yeah, I think that @villesau is right here- this is a prerequisite to a system that can process files like css modules and definitely a good idea.

@villesau
Copy link
Contributor

villesau commented Oct 18, 2018

@jakesyl I played around a bit with the solution, this is the minimum setup to get started:

.flowconfig:

[options]
module.system=haste
module.resolver=./test.js

And here is my hacky test.js which didn't do anything meaningful but managed to return message path-to-file? to flow:

#!/usr/bin/env node
const StringDecoder = require('string_decoder');
let buffer = '';
const decoder = new StringDecoder.StringDecoder();

process.stdin.on('data', chunk => {
  buffer += decoder.write(chunk);

  do {
    const index = buffer.indexOf('\n');
    if (index === -1) {
      break;
    }
    const line = buffer.slice(0, index);
    buffer = buffer.slice(index + 1);
    // success format (i think)
    process.stdout.write(`${JSON.stringify([null, 'path-to-file?'])}\n`);
    // error format (i think):
    // process.stdout.write(
    //   `${JSON.stringify([
    //     {
    //       code: 'what should I put here?',
    //       message: 'this message appears somewhere?',
    //       data: {
    //         request: 'not sure what to put here',
    //         issuer: 'or here',
    //         realIssuer: 'and here',
    //       },
    //     },
    //     null,
    //   ])}\n`,
    // );
  } while (true);
});

Important part is #!/usr/bin/env node as it allows flow to just run it.

This is what flow gives you in stdin: ["util","/path-to/flow-typed/cli/src/lib/stubUtils.js"], util being module name and path being path to file

@jakesylvestre
Copy link
Author

Thanks! Going to play around with this a little bit.

@villesau
Copy link
Contributor

@jakesyl here is even better example: https://github.com/facebook/flow/pull/6132/files#diff-146f2d34133e80d0efbc6c7b6e6e7bcf

@STRML
Copy link
Contributor

STRML commented Jan 27, 2020

Unfortunately 87820b8 (part of 0.110) deleted module.resolver under the dubious guise of "security holes" (which is a bit of an odd rationale when we're talking about a package ecosystem with "postinstall" scripts). This means Yarn Berry / PnP won't be supported in Flow for the foreseeable future.

@gkz
Copy link
Member

gkz commented Oct 4, 2021

Since the feature was deleted due to a security issue that was reported to us, as mentioned above, we can close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants