npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nodejs-pkg-tools

v0.5.0

Published

JS pkg tools

Readme

🎲 JS pkg tools

Чтение, модификация и запись *.json файлов.

npm i -D nodejs-pkg-tools

Что делает этот пакет:

  • Чтение package.json или любого валидного json.
  • Включение/исключение свойств.
  • Переопределение свойств пользовательским модификатором.
  • Использование шаблона foo.*.bar с модификатором для доступа к нескольким свойствам одного уровня.
  • Запись файла в установленный путь.
  • Доступна обычная функция modify({json: '...'}).toValue() -> {...} без доступа к файловой системе.
  • Дополнительные функции очистки clearDir(...) и копирования каталога copyDir(...).

Использование

Скопируйте файл в другой каталог, изменив некоторые свойства и относительные пути всего уровня exports:{}.

const nodeRoot = rwModify({
  mode: 'over',
  exclude: ['devDependencies', 'private'],
  sample: {
    'version': '0.8.5-alpha'
    // Модифицируйте все пути одним выражением.
    'exports.*.*': makeModifier((value, key, path) => 
                   [true, true, value.replace('dist/', '')])
  }
}, './package.json', './dist/package.json')
  • Было
{
  "version": "0.8.4",
  ...
  "devDependencies": { ... },
  "private": true,
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  }
}
  • Стало
{
  "version": "0.8.5-alpha",
  ...
  "exports": {
    ".": {
      "import": "./index.js",
      "types": "./index.d.ts"
    }
  }
}

Обработка узлов

После создания дерева узлов(1), каждый node помечается флагом удалить/оставить, зависит от опции mode.

При удалении(2), например узла A, флаг удаления распространяется вниз по дереву, но не удаляет узлы. Пока узел явно не переопределен его можно восстановить.

На следующем этапе(3) можно сохранить ранее удаленный узел, например B. Сохранение распространяется в обе стороны - вверх до корневого node и вниз по дочерним узлам.

Когда на результирующем объекте вызывается toValue() или toJson(), дерево собирается сверху, отбрасывая узлы отмеченные флагом remove.

🧹 Пустые {}|[] фильтруются и не включаются в результат. Вот такое {foo:{bar:{box:[]}}} - преобразуется в такое {}.

Опции и формат пути

Путь к свойствам описывается строкой с разделителем ".". Звездочка "*" определяет любое свойство в структуре или массиве. В TypeScript путь имеет псевдоним type KeyPath = string.

"foo.bar"    <- Ok
"box.**"     <- Bad - Двойные ".." и "**" недопустимы.
"over..tor"  <- Bad
".game.oh."  <- Bad - В начале и конце нельзя ".". 
"well.be.*"  <- Ok  - Звездочки "*" можно.
"*.*.*.*.*"  <- Ok 👀

Этот пакет имеет три основных функции:

import { 
  type IRootNode, ... несколько разных типов,
  makeModifier, modify, rwModify 
} from 'nodejs-pkg-tools'

// Модификатор используемый в параметре Options.sample.
const marker = makeModifier(boolean | Modifier): ModifierMarker
// Модификация Json-строки или валидной структуры {}|[].
const nodeRoot = modify(options: Options): IRootNode
// Чтение и запись файла.
const rwNodeRoot = rwModify (options: Options, src?: string, dest?: string): IRootNode

Options: {json?|value?, mode?, space?, include?, exclude?, sample?}

Объект опций.

Options.mode: 'strict'(default)|'over'|'error'|'strict_error'|'over_error'

От выбранного режима зависит установка флагов по умолчанию и действие при ошибках:

  • "strict"(default) - Всем node устанавливается remove-флаг. Сохранить узел можно явной установкой пути в include или в модификаторе sample.
  • "over" - Поведение обратное "strict".
  • "error" - Любая ошибка, например невалидное значение, предотвращает дальнейшую обработку. Результат будет иметь nodeRoot.isFatalError:true. Ошибки не влияющие на результат, когда не существует пути exclude, игнорируются.

Параметр mode тестируется регулярным выражением и может быть установлен в любых вариациях, даже так error_2022_over.

Ошибки разбора Json или чтения файла, всегда являются фатальными и не возвращают ожидаемый результат. Функции не выбрасывают исключений, проверять наличие ошибок следует через интерфейс IRootNode. В случае isFatalError, текущий результат будет потерен и toJson() или toValue(), будут возвращать "" или null.

📌 Не устанавливайте error при преобразовании JS-объекта, где могут быть function, undefined и symbol. В этом случае невалидные значения игнорируются и ошибка не устанавливается, в том числе и для ошибок поиска путей. Список всех ошибок всегда доступен через IRootNode.errors:IErrors.

Больше информации в файле src/errors.ts.

Options.space: number>=0(default: 2)

Это значение будет передано в JSON.stringify(value, null, space).

Options.json?: string | Options.value?: JsonPrimitive|[]|{}

Строка Json или валидное значение. Объект содержащий function|Symbol|BigInt|undefined недопустим и вызовет ошибку, если установлено mode:'error'.

rwModify(opts, src?, dest?) можно использовать с любым вариантом источника данных в порядке приоритета src? || json? || value.

Options.include: KeyPath[]

Массив путей для включения. Этот массив устанавливает флаг сохранить_свойство в первую очередь.

Options.exclude: KeyPath[]

Применяется после Options.include.

Options.sample: {...}|[...][]

  • {[k in KeyPath]: ValidValue | ModifierMarker}
  • [KeyPath, ...][]
  • [string[], ...][]

Объект или массив позволяющий удалять/модифицировать/устанавливать новые свойства и их значения. В отличие от include/exclude, здесь нет определенного порядка действий. Свойства можно удалить, добавить, изменить и снова удалить.

import { type Sample, makeModifier, modify, rwModify } from 'nodejs-pkg-tools'

const sample: Sample = {
  // Отметим весь узел для удаления...
  "your.very": makeModifier(false),
  // ... и оставим вложенный узел - он все еще существует.
  "your.very.long": makeModifier(true)

  // Независимо от наличия свойства в целевом объекте,
  // оно будет создано. Глубина не имеет значение.
  // Путем всегда является ключ, а значением {foo: "bar"}.
  "your.very.long.path": {foo: "bar"},
  // Определять путь в виде вложенных структур нельзя.
  // Неясно: путь это или значение {very:...}.
  your: {very: {long: { path: {foo: "bar"}}}}
}

Несмотря на удобный формат {key: value}, объекты, имеющие целочисленные ключи, самовольно распоряжаются сортировкой. Точный порядок обработки можно определить массивом записей.

// Такое определение ...
const sample: Sample = [
  ["your.path.*", makeModifier((value, key, path) => {...})],
  ["engines.node", "^18.7.0"]
]
// ... эквивалентно
const sample: Sample = {
  "your.path.*": makeModifier((value, key, path) => {...}),
  "engines.node": "^18.7.0"
}

Формат определения KeyPath не позволяет указать точки "." и звездочки "*". Такие ключи передаются массивом.

const sample: Sample = [
  [["exports", "."], "newValue"],
  // Массив пути не обрабатывается и используется как есть.
  [["description", "bar**..box", "repo", ""], makeModifier(true)]
  // Имя свойства ->^^^^^^^^^^           ^^<- и это имя
]

Смешивать различные варианты Sample не допускается.

Modifier(value, key, []): boolean | [boolean, boolean, (Primitive|[]|{})]

Пользовательский обработчик принимает три аргумента:

  • value: (Primitive|[]|{}) - Значение запрашиваемого свойства.
  • key: (null|string|number) - Ключ или null, если это корень. Последний элемент в массиве path.
  • path: (string|number)[] - Путь от корня или пустой массив.

Функция должна возвратить один из вариантов:

  • boolean:
    • true - Игнорировать, свойство может быть удалено или сохранено в зависимости от текущих установок.
    • false - Прервать обработку и установить фатальную ошибку.
  • [boolean, boolean, (Primitive|[]|{})]:
    • [0]! - Если false свойство будет удалено, при этом остальные элементы игнорируются. При true оценивается элемент [1] и свойству устанавливается флаг сохранения.
    • [1]? - Действие. При true обновляем значение из [2], иначе оставляем оригинал.
    • [2]? - Любое валидное значения для переопределения текущего свойства, должно быть установлено если [0]:true и [1]:true.

📌 Обработчик должен устанавливаться через makeModifier(). Любое другой тип оценивается как значение для переопределения свойства.

Этот файл 📄 содержит все доступные интерфейсы с комментариями.