npm publish — удаление скриптов из package.json?

Перед публикацией моего скрипта у меня есть несколько скриптов в package.json для компиляции coffeescript, typescript и команд только для разработчиков, которые не имеют смысла после публикации.

Мне было интересно, есть ли процедура удаления определенных скриптов в package.json? Учитывая, что при публикации вашего пакета он также публикует package.json.

Можно ли удалить скрипты перед публикацией пакета?

Как только я публикую свой сценарий, я удаляю множество исходных файлов typescript и coffeescript (поскольку они были скомпилированы), поэтому сценарий, который у меня есть для сборки, не имеет смысла для опубликованного пакета.

Возможно ли это? Или я должен думать о другом?


person Martin    schedule 15.02.2018    source источник


Ответы (2)


Краткий ответ.

"Можно ли удалить скрипты перед публикацией пакета?"

npm не включает встроенную функцию удаления скриптов из package.json.


Длинный ответ с решением.

"Возможно ли это? Или мне следует подумать о другом способе?"

Существует несколько встроенных функций, известных как Пре- и пост-хуки, которые можно использовать для удовлетворения ваших требований, хотя и довольно нестандартным образом. Соответствующие хуки prepublish и postpublish описаны в документации следующим образом;

prepublish: Запустить ДО того, как пакет будет упакован и опубликован, а также на локальном npm install без каких-либо аргументов...

postpublish: запускать ПОСЛЕ публикации пакета.

Синопсис решения:

  1. Используйте prepublish скрипт в своих проектах package.json для вызова пользовательского скрипта nodejs. Этот скрипт nodejs выполняет следующие действия:

    • Reads the original package.json data and caches it.
    • Удаляет определенные скрипты/ключи из раздела scripts файла package.json.
    • Записывает измененные данные обратно в исходный package.json.
  2. Используйте postpublish скрипт в своих проектах package.json для вызова другого пользовательского скрипта nodejs. Этот вторичный скрипт nodejs выполняет следующие действия:

    • Reverts the content of package.json back to it's original state.

Примеры кода/суть.

  1. Следующий скрипт nodejs будет выполнять задачи, упомянутые в первом пункте выше. Назовем его cleanse-pkg.js.

    cleanse-pkg.js

    const fs = require('fs');
    const path = require('path');
    
    // Define absolute paths for original pkg and temporary pkg.
    const ORIG_PKG_PATH = path.resolve(__dirname, '../package.json');
    const CACHED_PKG_PATH = path.resolve(__dirname, '../../cached-package.json');
    
    // Obtain original `package.json` contents.
    const pkgData = require(ORIG_PKG_PATH);
    
    if (process.argv.length <= 2) {
      throw new Error('Missing npm scripts key/name argument(s)');
    }
    
    // Get list of arguments passed to script.
    const scriptsToRemove = process.argv[2].split(',');
    const devDepsToRemove = process.argv[3] ? process.argv[3].split(',') : [];
    
    // Write/cache the original `package.json` data to `cached-package.json` file.
    fs.writeFile(CACHED_PKG_PATH, JSON.stringify(pkgData), function (err) {
      if (err) throw err;
    });
    
    // Remove the specified named scripts from the scripts section.
    scriptsToRemove.forEach(function (scriptName) {
      delete pkgData.scripts[scriptName];
    });
    
    // Remove the specified named pkgs from the devDependencies section.
    devDepsToRemove.forEach(function (pkgName) {
      delete pkgData.devDependencies[pkgName];
    });
    
    // Overwrite original `package.json` with new data (i.e. minus the specific data).
    fs.writeFile(ORIG_PKG_PATH, JSON.stringify(pkgData, null, 2), function (err) {
      if (err) throw err;
    });
    
  2. Следующий вторичный скрипт nodejs выполнит задачу, упомянутую во втором пункте выше. Назовем его restore-pkg.js.

    restore-pkg.js

    const fs = require('fs');
    const path = require('path');
    
    // Define absolute paths for original pkg and temporary pkg.
    const ORIG_PKG_PATH = path.resolve(__dirname, '../package.json');
    const CACHED_PKG_PATH = path.resolve(__dirname, '../../cached-package.json');
    
    // Obtain original/cached contents from `cached-package.json`.
    const pkgData = JSON.stringify(require(CACHED_PKG_PATH), null, 2) + '\n';
    
    // Write data from `cached-package.json` back to original `package.json`.
    fs.writeFile(ORIG_PKG_PATH, pkgData, function (err) {
      if (err) throw err;
    });
    
    // Delete the temporary `cached-package.json` file.
    fs.unlink(CACHED_PKG_PATH, function (err) {
      if (err) throw err;
    });
    

Реализация и использование.

  1. Скрипты prepublish и postpublish определены в проектах package.json следующим образом:

    Надуманный оригинальный package.json

    {
      ...
      "scripts": {
        "keep": ... ,
        "a": ... ,
        "b": ... ,
        "prepublish": "node .scripts/cleanse-pkg \"a,b,prepublish,postpublish\"",
        "postpublish": "node .scripts/restore-pkg"
      },
      ...
    }
    
    • Обратите внимание на часть \"a,b,prepublish,postpublish\" в сценарии prepublish. Это определяет аргумент для передачи в cleanse-pkg.js (т. е. в нем перечислены имена каждого сценария, который необходимо удалить перед публикацией). Каждый именованный скрипт, подлежащий удалению, должен быть; предоставляется как одна строка, разделяется запятыми и не должен содержать пробелов.

    • И cleanse-pkg.js, и restore-pkg.js находятся в скрытой папке с именем .scripts, которая сама находится на верхнем уровне каталога проектов (то есть на том же уровне, что и проекты package.json). Оба скрипта nodejs можно перемещать по желанию, а пути к ним при необходимости переопределять в соответствующем npm-script .

  2. Учитывая надуманное package.json выше, фактическое содержимое package.json в итоговом опубликованном tar-архиве будет следующим:

    Результирующий/опубликованный package.json

    {
      ...
      "scripts": {
        "keep": ...
      },
      ...
    }
    

Пакеты в разделе devDependencies.

Возможно, в разделе devDependencies ваших проектов package.json есть пакеты, которые вы также хотите удалить из опубликованного package.json.

(Примечание. Все пакеты, перечисленные в разделе devDependencies, не загружаются при хотя пользователь устанавливает через npm-реестр).

Однако, возможно, вы все равно захотите их удалить. Если это требование, то cleanse-pkg.js также принимает необязательный второй аргумент. Этот аргумент аналогичен первому аргументу, согласно которому каждый именованный пакет, подлежащий удалению из раздела devDependencies, должен быть; предоставляется как одна строка, разделяется запятыми и не должен содержать пробелов.

  1. Предположим, что исходный package.json на этот раз выглядит следующим образом:

    Надуманный оригинальный package.json

    {
      ...
      "scripts": {
        "keep": ... ,
        "a": ... ,
        "b": ... ,
        "prepublish": "node .scripts/cleanse-pkg \"a,b,prepublish,postpublish\" \"x,z\"",
        "postpublish": "node .scripts/restore-pkg"
      },
      "devDependencies": {
        "x": "^1.0.2",
        "y": "^0.8.1",
        "z": "^0.8.1"
      },
      ...
    }
    
    • Note the additional second \"x,z\" argument added to the prepublish script to specify which packages to omit from the devDependecies section.
  2. На этот раз, учитывая надуманное package.json выше, фактическое содержимое package.json в итоговом опубликованном tar-архиве будет следующим:

    Результирующий/опубликованный package.json

    {
      ...
      "scripts": {
        "keep": ...
      },
      "devDependencies": {
        "y": "^0.8.1"
      },
      ...
    }
    

Бег

В этом решении предполагается, что npm publish будет запущен с использованием одного из следующих методов:

  1. Из каталога проекта без каких-либо аргументов. Например. npm publish.
  2. Указав путь к своим проектам package.json. Например. npm publish path/to/package.json.

Это не сработает, если указать URL-адрес или путь к сжатому tar-архиву, содержащему одну папку с файлом package.json внутри.


Дополнительные примечания

  1. Чтобы предотвратить публикацию обоих служебных скриптов nodejs (cleanse-pkg.js и restore-pkg.js), их следует добавить в ваши проекты .npmignore. Учитывая расположение обоих этих файлов, описанное выше, вы можете добавить запись .scripts в .npmignore.

  2. Оба служебных скрипта nodejs, cleanse-pkg.js и restore-pkg.js, определяют:

    • An absolute path to the original package.json file.
    • Абсолютный путь, куда должен быть записан временный файл cached-package.json. В настоящее время он сохраняется на один уровень выше/вне каталога проекта, чтобы избежать его публикации).

    Если вы решите сохранить cleanse-pkg.js и restore-pkg.js в месте, отличном от описанного выше, пути в следующем фрагменте кода необходимо будет переопределить по мере необходимости в обоих файлах.

    const ORIG_PKG_PATH = path.resolve(__dirname, '../package.json');
    const CACHED_PKG_PATH = path.resolve(__dirname, '../../cached-package.json');
    
person RobC    schedule 16.02.2018
comment
В вашем примере не должен ли скрипт postpublish вообще не запускаться, поскольку он удален из сценариев package.json во время prepublish? - person Matei Radu; 14.10.2018
comment
@MateiRadu - Хороший вопрос. На момент публикации ответ pkg.json был прочитан один раз, а скрипты pre и postpublish были кэшированы раньше, т.е. до запуска prepublish и publish. Однако, глядя на эту фиксацию (которая более поздняя, ​​чем публикация), я подозреваю, что возможно это уже не так. Похоже, что npm теперь читает pkg.json на каждом этапе процесса publish. Попробуйте запустить npm publish --dry-run (т.е. включите --dry-run опции) и проверьте результаты. Было бы здорово, если бы вы подтвердили здесь в комментариях. - person RobC; 14.10.2018
comment
Я могу подтвердить, что для каждого хука package.json читается снова, поэтому этот подход больше не работает. На данный момент мое единственное решение — использовать npm pack для создания tar-архива и скрипт postpack, который редактирует package.json внутри созданного tar-архива, чтобы исходный pkg не изменялся. - person Matei Radu; 14.10.2018
comment
не знаю, может ли это помочь, но это мой текущий postpack скрипт. - person Matei Radu; 14.10.2018

Вы также можете рассмотреть этот пакет. https://www.npmjs.com/package/clean-publish

В частности, они предоставляют инструмент для работы только с packakge.json.

$ npm run clear-package-json package.json -o package/package.json --fields scripts name
# or
$ npm run clear-package-json package.json > package/package.json
# or
$ cat package.json | npm run clear-package-json
# `fields` also will be getted from config file

Кажется, он делает именно то, что вы просите, но и многое другое. Это кажется очень настраиваемым.


Обновить

Вот пакет, который я создал, который делает то, что вы просите, но значительно по-другому.

https://www.npmjs.com/package/clean-package

$ clean-package --remove scripts
person roydukkey    schedule 07.08.2020