package.json
Файл манифеста пакета. Он содержит все метаданные пакета, включая зависимости, заголовок, автора и т.д. Это стандарт для всех основных пакетных менеджеров Node.JS, включая pnpm.
engines
Вы можете указать версию Node и pnpm, на которой работает ваш программный продукт:
{
    "engines": {
        "node": ">=10",
        "pnpm": ">=3"
    }
}
Во время локальной разработки pnpm всегда выдает сообщение об ошибке, если его версия не совпадает с версией, указанной в поле engines.
Если только пользователь не установил флаг конфигурации engine-strict (см. .npmrc), это поле носит исключительно рекомендательный характер и будет выдавать предупреждения только тогда, когда ваш пакет установлен как зависимость.
dependenciesMeta
Additional meta information used for dependencies declared inside dependencies, optionalDependencies, and devDependencies.
dependenciesMeta.*.injected
If this is set to true for a local dependency, the package will be hard linked to the virtual store (node_modules/.pnpm) and symlinked from the virtual store to the modules directory.
If this is set to false or not set for a local dependency, the package will be symlinked directly from its location in the workspace to the module directory.
For instance, the following package.json in a workspace will create a symlink to button in the node_modules directory of card:
{
  "name": "card",
  "dependencies": {
    "button": "workspace:1.0.0"
  }
}
But what if button has react in its peer dependencies? If all projects in the monorepo use the same version of react, then no problem. But what if button is required by card that uses react@16 and form with react@17? Without using inject, you'd have to choose a single version of react and install it as dev dependency of button. But using the injected field you can inject button to a package, and button will be installed with the react version of that package.
So this will be the package.json of card:
{
  "name": "card",
  "dependencies": {
    "button": "workspace:1.0.0",
    "react": "16"
  },
  "dependenciesMeta": {
    "button": {
      "injected": true
    }
  }
}
button will be hard linked into the dependencies of card, and react@16 will be symlinked to the dependencies of card/node_modules/button.
And this will be the package.json of form:
{
  "name": "form",
  "dependencies": {
    "button": "workspace:1.0.0",
    "react": "17"
  },
  "dependenciesMeta": {
    "button": {
      "injected": true
    }
  }
}
button will be hard linked into the dependencies of form, and react@17 will be symlinked to the dependencies of form/node_modules/button.
In contrast to normal dependencies, injected ones are not symlinked to the destination folder, so they are not updated automatically, e.g. after running the build script. To update the hard linked folder contents to the latest state of the dependency package folder, call pnpm i again.
Note that the button package must have any lifecycle script that runs on install in order for pnpm to detect the changes and update it. For example, the package can be rebuilt on install: "prepare": "pnpm run build". Any script would work, even a simple unrelated command without side effects, like this: "prepare": "pnpm root".
peerDependenciesMeta
This field lists some extra information related to the dependencies listed in the peerDependencies field.
peerDependenciesMeta.*.optional
If this is set to true, the selected peer dependency will be marked as optional by the package manager. Therefore, the consumer omitting it will no longer be reported as an error.
For example:
{
    "peerDependencies": {
        "foo": "1"
    },
    "peerDependenciesMeta": {
        "foo": {
            "optional": true
        },
        "bar": {
            "optional": true
        }
    }
}
Note that even though bar was not specified in peerDependencies, it is marked as optional. pnpm will therefore assume that any version of bar is fine. However, foo is optional, but only to the required version specification.
publishConfig
It is possible to override some fields in the manifest before the package is packed. The following fields may be overridden:
To override a field, add the publish version of the field to publishConfig.
For instance, the following package.json:
{
    "name": "foo",
    "version": "1.0.0",
    "main": "src/index.ts",
    "publishConfig": {
        "main": "lib/index.js",
        "typings": "lib/index.d.ts"
    }
}
Will be published as:
{
    "name": "foo",
    "version": "1.0.0",
    "main": "lib/index.js",
    "typings": "lib/index.d.ts"
}