yarnpkg / berry

📦🐈 Active development trunk for Yarn ⚒
https://yarnpkg.com
BSD 2-Clause "Simplified" License
7.35k stars 1.1k forks source link

[Bug] Unbound variable on `npm_package_config` #1339

Closed kevin-lindsay-1 closed 4 years ago

kevin-lindsay-1 commented 4 years ago

Describe the bug

package.json config variables are not being referenced when running scripts.

Any recommended workarounds/alternative config approaches?

To Reproduce

Add a variable in package.json under the key config.

{
  "config": {
    "port": 5000
  },
  "scripts": {
    "echo": "echo ${npm_package_config_port}" 
  }
}

Run script:

$ yarn echo
> Internal Error: Unbound variable "npm_package_config_port"

Environment if relevant (please complete the following information):

arcanis commented 4 years ago

We don't expose the package.json values anymore, and I'm not sure we'll want to add it back since I'm not a fan of leaking the manifest in the environment (it also led to some annoying issues with the environment size). You can however access this information:

echo $(node -p 'require("./package.json").config.port')
eric-burel commented 2 years ago

Hi, I think there are legitimate use cases for workspaces though, in order to tell whether we are in a monorepo or not. Except if Yarn can somehow provide a global variable to tell if a specific script is run in the context of a monorepo workspace or outside of it. This is useful when some workspaces are starter app, that you publish using git subtree for instance, you may want to have different behaviour on postinstall and currently it's hard to achieve.

This how I do currently:

"prebuild": "(test -f ../../packages/crud/package.json && rm -Rf ./node_modules/@vulcanjs && mkdir -p ./node_modules/@vulcanjs && cp -R ../../packages/* ./node_modules/@vulcanjs) || echo 'Not in the context of a monorepo, ok'",

I have to look for certain file out of my repo but I suspect some install environment might cringe on testing file outside of the app folder.

I've given a shot at using $PROJECT_CWD and check it against but I cannot succeed to have a script that works across environments..

Third attempt, this script is reusable and let me match against the directory name:

#! /usr/bin/node
function run() {
  if ((process.env.PROJECT_CWD || "").match(/vulcan-npm/)) {
    process.exit(0);
  } else {
    process.exit(1);
  }
}
run();

It's not very robust though, a config value inherited from the root package.json would be cleaner.

warlord987 commented 1 year ago

Hi, I think there are legitimate use cases for workspaces though, in order to tell whether we are in a monorepo or not. Except if Yarn can somehow provide a global variable to tell if a specific script is run in the context of a monorepo workspace or outside of it. This is useful when some workspaces are starter app, that you publish using git subtree for instance, you may want to have different behaviour on postinstall and currently it's hard to achieve.

This how I do currently:

"prebuild": "(test -f ../../packages/crud/package.json && rm -Rf ./node_modules/@vulcanjs && mkdir -p ./node_modules/@vulcanjs && cp -R ../../packages/* ./node_modules/@vulcanjs) || echo 'Not in the context of a monorepo, ok'",

I have to look for certain file out of my repo but I suspect some install environment might cringe on testing file outside of the app folder.

I've given a shot at using $PROJECT_CWD and check it against but I cannot succeed to have a script that works across environments..

Third attempt, this script is reusable and let me match against the directory name:

#! /usr/bin/node
function run() {
  if ((process.env.PROJECT_CWD || "").match(/vulcan-npm/)) {
    process.exit(0);
  } else {
    process.exit(1);
  }
}
run();

It's not very robust though, a config value inherited from the root package.json would be cleaner.

I have this use cases and the berry upgrade is breaking the existing behaviour.

NirvanaNrv commented 6 months ago

I started using a yarn plugin with

plugins:
  - ./script-env-plugin.cjs

in .yarnrc.yml

and in the script-env-plugin.cjs

const packageDotJson = require('./package.json')

const flatten = object => Object.entries(object).flatMap(([key, value]) =>
  typeof value !== 'object' ? (
    [[[key], value]]
  ) : flatten(value).map(([path, value]) => [[key, ...path], value]),
)

const prefix = ['npm', 'package', 'config']

module.exports = {
  name: 'script-env',
  factory: () => ({
    hooks: {
      setupScriptEnvironment: async (project, env, makePathWrapper) => {
        Object.assign(env, Object.fromEntries(flatten(packageDotJson.config).map(([path, value]) => [[...prefix, ...path].join('_'), value])))
      }
    },
  }),
};

and thus I am happy to not lose done work which relied on "npm_package_config_xxx", and gave me a break in my urge to go back to yarn v1.