Berry: [Bug] Prettier is unable to load plugins in PNP environment

Created on 30 Sep 2020  Ā·  16Comments  Ā·  Source: yarnpkg/berry

  • [X] I'd be willing to implement a fix

Describe the bug

When using Prettier with plugins in a PNP environment, Prettier will not be able to find its plugins.

To Reproduce

We reproduced this on Discord with this repo:

https://github.com/oliversalzburg/prettier-plugin-pnp

Running yarn prettier src/index.ts will not remove the unused import, for which the prettier-plugin-organize-imports was installed.

Additional context

It was suggested that this is due to missing PNP functionality in the SDK wrapper. Enabling usePnpif in https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-pnpify/sources/generateSdk.ts#L119 should be a valid solution to the problem.

This should probably be enabled through a CLI flag in yarn pnpify to allow an adjusted SDK wrapper to be generated.

To actually fix the issue, I also need to supply the plugin search directory to Prettier manually. Otherwise it will search in a completely inapproriate location by default.

bug external bug

Most helpful comment

I'll see if we can release a new version of @yarnpkg/pnpify, in the meantime here is the updated version

#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire, createRequireFromPath} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../.pnp.js";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require prettier/index.js
    require(absPnpApiPath).setup();
  }

  let pnpifyResolution;
  try {
    pnpifyResolution = absRequire.resolve(`@yarnpkg/pnpify`);
  } catch (err) {}

  if (pnpifyResolution) {
    if (typeof global[`__yarnpkg_sdk_is_using_pnpify__`] === `undefined`) {
      Object.defineProperty(global, `__yarnpkg_sdk_is_using_pnpify__`, {configurable: true, value: true});

      process.env.NODE_OPTIONS += ` -r ${pnpifyResolution}`;

      // Apply PnPify to the current process
      absRequire(pnpifyResolution).patchFs();
    }
  }
}

// Defer to the real prettier/index.js your application uses
module.exports = absRequire(`prettier/index.js`);

All 16 comments

The merge was done in a branch (yarnpkg:larixer/prettier-pnpify) which does not exist anymore and was not done in master. When will this be present in @yarnpkg/pnpify?

@asfernandes After discussion we decided to enable pnpify runtime on a per-tool basis and not shift the decision to the users, because they don't know the tradeoffs involved. For prettier we will always enable pnpify runtime starting from the next @yarnpkg/pnpify version:
https://github.com/yarnpkg/berry/pull/1913

Hi folks! A Yarn 2 experimenter here 😁

It seems that I've ran @yarnpkg/pnpify with the discussed change (v 2.2.3), but my plugins still have not loaded. Any ideas what I should check? Here is the PR: https://github.com/kachkaev/njt/pull/29

It hasn't been released yet, but you can apply it manually by editing .yarn\sdks\prettier\index.js and changing it to

#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire, createRequireFromPath} = require(`module`);
const {resolve, dirname} = require(`path`);

const relPnpApiPath = "../../../.pnp.js";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require prettier/index.js
    require(absPnpApiPath).setup();
  }

  const pnpifyResolution = require.resolve(`@yarnpkg/pnpify`, {paths: [dirname(absPnpApiPath)]});
  if (typeof global[`__yarnpkg_sdk_is_using_pnpify__`] === `undefined`) {
    Object.defineProperty(global, `__yarnpkg_sdk_is_using_pnpify__`, {configurable: true, value: true});

    process.env.NODE_OPTIONS += ` -r ${pnpifyResolution}`;

    // Apply PnPify to the current process
    absRequire(pnpifyResolution).patchFs();
  }
}

// Defer to the real prettier/index.js your application uses
module.exports = absRequire(`prettier/index.js`);

Thanks for the snippet @merceyz! I might try it next weekend if the new version of pnpify plugin is not yet released. I’m not in the rush with

It is possible that Prettier might support config → plugins → require.resolve at some point. See https://github.com/prettier/prettier/issues/7073#issuecomment-711420129. I’m still new to Yarn 2, so happy to be corrected if my suggestion does not lead to a working solution. The end goal is to enable this chain: prettier → @my-company/prettier-config → some-prettier-plugin. Installing all plugins into the project is quite inconvenient – I’d like the config package to bring them on.

Turns out that config → plugins → require("some-plugin") is already supported by Prettier! This means that autodiscovery is not the only mechanism devs can rely on šŸŽ‰ Here is a short discussion: https://github.com/prettier/prettier/issues/7073#issuecomment-711954542

@asfernandes After discussion we decided to enable pnpify runtime on a per-tool basis and not shift the decision to the users, because they don't know the tradeoffs involved. For prettier we will always enable pnpify runtime starting from the next @yarnpkg/pnpify version:

1913

Is there an ETA for @yarnpkg/pnpify next version including this?

@asfernandes Until it's released you can apply it manually, see https://github.com/yarnpkg/berry/issues/1903#issuecomment-711432671

@asfernandes Until it's released you can apply it manually, see #1903 (comment)

Unofrtunately, prettier still does not work for me in vscode. See the logs:

Error: Cannot find module '@yarnpkg/pnpify'
Require stack:
- /home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.yarn/sdks/prettier/internal.js
Require stack:
- /home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.yarn/sdks/prettier/index.js
- /home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js
- /snap/code/48/usr/share/code/resources/app/out/vs/loader.js
- /snap/code/48/usr/share/code/resources/app/out/bootstrap-amd.js
- /snap/code/48/usr/share/code/resources/app/out/bootstrap-fork.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:844:17)
    at Function.external_module_.Module._resolveFilename (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.pnp.js:12954:46)
    at callNativeResolution (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.pnp.js:13363:36)
    at resolveToUnqualified (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.pnp.js:13569:24)
    at resolveRequest (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.pnp.js:13821:29)
    at Object.resolveRequest (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.pnp.js:13899:26)
    at Function.external_module_.Module._resolveFilename (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.pnp.js:13003:34)
    at Function.r.resolve (/snap/code/48/usr/share/code/resources/app/out/vs/loader.js:17:406)
    at Object.<anonymous> (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.yarn/sdks/prettier/index.js:18:36)
    at Module.i._compile (/snap/code/48/usr/share/code/resources/app/out/vs/loader.js:17:571)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1051:10)
    at Module.load (internal/modules/cjs/loader.js:862:32)
    at Module._load (internal/modules/cjs/loader.js:774:14)
    at Module._load (electron/js2c/asar.js:769:28)
    at t._load (/snap/code/48/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1057:776)
    at i._load (/snap/code/48/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1027:486)
    at n._load (/snap/code/48/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1023:767)
    at Function.external_module_.Module._load (/home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.pnp.js:12862:36)
    at Module.require (internal/modules/cjs/loader.js:899:19)
    at r (/snap/code/48/usr/share/code/resources/app/out/vs/loader.js:17:346)
    at t.ModuleResolver.loadNodeModule (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:30610)
    at t.ModuleResolver.requireLocalPkg (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:29738)
    at t.ModuleResolver.getPrettierInstance (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:28424)
    at t.LanguageResolver.getSupportLanguages (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:26531)
    at t.LanguageResolver.getSupportedFileExtensions (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:26367)
    at t.default.selectors (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:56123)
    at t.default.registerFormatter (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:55092)
    at t.activate (/home/asfernandes/.vscode/extensions/esbenp.prettier-vscode-5.7.1/dist/extension.js:1:22370)
    at Function._callActivateOptional (/snap/code/48/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:927:841)
    at Function._callActivate (/snap/code/48/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:927:492)
    at /snap/code/48/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:925:841
    at processTicksAndRejections (internal/process/task_queues.js:94:5)
    at async Promise.all (index 0)

The file /home/asfernandes/projects/github/node-fb/node-firebird-drivers.git/.yarn/sdks/prettier/internal.js does not exist.

You're missing @yarnpkg/pnpify as a dependency

You're missing @yarnpkg/pnpify as a dependency

I've it installed as described in the docs (as dependency - not devDependency)!

My project uses workspaces and to be sure, I've installed it in the root and all sub packages.

Please open a seperate issue with a reproduction

It hasn't been released yet, but you can apply it manually by editing .yarn\sdks\prettier\index.js and changing it to

#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire, createRequireFromPath} = require(`module`);
const {resolve, dirname} = require(`path`);

const relPnpApiPath = "../../../.pnp.js";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require prettier/index.js
    require(absPnpApiPath).setup();
  }

  const pnpifyResolution = require.resolve(`@yarnpkg/pnpify`, {paths: [dirname(absPnpApiPath)]});
  if (typeof global[`__yarnpkg_sdk_is_using_pnpify__`] === `undefined`) {
    Object.defineProperty(global, `__yarnpkg_sdk_is_using_pnpify__`, {configurable: true, value: true});

    process.env.NODE_OPTIONS += ` -r ${pnpifyResolution}`;

    // Apply PnPify to the current process
    absRequire(pnpifyResolution).patchFs();
  }
}

// Defer to the real prettier/index.js your application uses
module.exports = absRequire(`prettier/index.js`);

This is what my .yarn\sdks\prettier\index.js already looks like on the current version. I have @yarnpkg/pnpify installed as a dependency too.

Should we wait for new @yarnpkg/pnpify version or can you post a manual .yarn/sdks/prettier/index.js version so we can test?

I'll see if we can release a new version of @yarnpkg/pnpify, in the meantime here is the updated version

#!/usr/bin/env node

const {existsSync} = require(`fs`);
const {createRequire, createRequireFromPath} = require(`module`);
const {resolve} = require(`path`);

const relPnpApiPath = "../../../.pnp.js";

const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);

if (existsSync(absPnpApiPath)) {
  if (!process.versions.pnp) {
    // Setup the environment to be able to require prettier/index.js
    require(absPnpApiPath).setup();
  }

  let pnpifyResolution;
  try {
    pnpifyResolution = absRequire.resolve(`@yarnpkg/pnpify`);
  } catch (err) {}

  if (pnpifyResolution) {
    if (typeof global[`__yarnpkg_sdk_is_using_pnpify__`] === `undefined`) {
      Object.defineProperty(global, `__yarnpkg_sdk_is_using_pnpify__`, {configurable: true, value: true});

      process.env.NODE_OPTIONS += ` -r ${pnpifyResolution}`;

      // Apply PnPify to the current process
      absRequire(pnpifyResolution).patchFs();
    }
  }
}

// Defer to the real prettier/index.js your application uses
module.exports = absRequire(`prettier/index.js`);

nice, looks like @yarnpkg/pnpify doesn't have to be installed when using this .yarn/sdks/prettier/index.js

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mike-Dax picture Mike-Dax  Ā·  3Comments

kiprasmel picture kiprasmel  Ā·  3Comments

chrisands picture chrisands  Ā·  3Comments

danreg picture danreg  Ā·  3Comments

juanpicado picture juanpicado  Ā·  4Comments