Перейти к основному содержимому

Установка пакетов данных: init и pack

Имена, города, регионы, компании и прочие списки — это пакеты данных. Они поставляются отдельно от движка, так что обновление библиотеки никогда не затирает ваши данные, а тяжёлые наборы не раздувают каждую установку. С пакетом из коробки едет разумный набор по умолчанию (например, топ-1000 имён); полные и дополнительные наборы докачиваются командой tdcv2 pack.

Весь процесс — это две команды:

  1. Один раз tdcv2 init — настроить, куда класть данные и какая локаль по умолчанию.
  2. tdcv2 pack add … — скачать те наборы, которые вам действительно нужны.

init идёт первым, потому что отвечает на вопрос, который pack решить не может: какая папка — ваша. Пакеты сознательно не лежат внутри установленной библиотеки: иначе каждое npm update, pip install -U или обновление зависимости стирало бы гигабайт данных, которые вы выбрали. init записывает папку, принадлежащую вашему проекту, и этот файл читают все реализации, поэтому пакет, скачанный один раз, находят все.

Пропустите init — и pack будет некуда класть данные; он об этом скажет, а не станет гадать:

tdcv2 pack list (конфига ещё нет)
tdcv2: no pack store configured — run `tdcv2 init` first
Те же команды на любом языке

init и pack есть в каждой реализации, а не только в Node. Команды, их вывод и файл конфигурации, который они пишут, одинаковы — это удерживает общая тестовая фикстура, по которой все пять сверяются с одними и теми же байтами. Отличается лишь то, как получить саму команду и как её написать:

Ваш языкКак получить командуКак вызвать
Node.jsникак — npx скачает самnpx tdcv2 pack add ru
Pythonpip install tdcv2tdcv2 pack add ru
Rustcargo install tdcv2tdcv2 pack add ru
C#dotnet tool install --global Tdcv2.Clitdcv2 pack add ru
Javaскачать tdcv2-0.1.7-cli.jar с Maven Centraljava -jar tdcv2-0.1.7-cli.jar pack add ru

Три из них кладут команду tdcv2 в PATH, и дальше читаются одинаково. Node не требует установки вообще — npx скачивает и запускает одним действием. Java выбивается потому, что у Maven нет аналога npm-овского bin: добавление библиотеки в проект не может положить команду в PATH, поэтому командная строка — это jar, который вы запускаете сами:

curl -LO https://repo1.maven.org/maven2/io/github/nickliapin/tdcv2/0.1.7/tdcv2-0.1.7-cli.jar
java -jar tdcv2-0.1.7-cli.jar pack add ru

Стоит завести алиас — alias tdcv2='java -jar /путь/к/tdcv2-0.1.7-cli.jar' — после этого все команды на этой странице читаются так же, как везде.

Проект, настроенный одной реализацией, готов для остальных четырёх — тот же конфиг, то же хранилище, тот же реестр. Поставить ru через Python и генерировать из него в Rust — это не особый случай, а обычный.

Примеры вывода ниже иллюстративные — точное число файлов, размеры и пути зависят от вашей машины и версии ядра, но общий вид сохраняется.

tdcv2 init — настроить проект

init пишет файл конфигурации, чтобы вам никогда не приходилось править JSON руками. В интерактивном терминале запускается короткий мастер (где хранить конфиг, куда качать пакеты, какая локаль по умолчанию). В скрипте или CI передавайте флаги, чтобы ничего не зависало на вопросе.

tdcv2 init # спросит и запишет
tdcv2 init
Wrote project config: /path/to/project/tdcv2.config.json
data packs → /path/to/project/tdcv2-packs
locale     → en

Next: run `tdcv2 pack` to download data packs into that folder.

Используйте один раз на проект, перед первым tdcv2 pack add. Каждый флаг ниже покрывает случай, где мастер только мешал бы.

--yes / -y — без вопросов

Пропускает все вопросы и принимает значения по умолчанию (проектный конфиг, ./tdcv2-packs, en). Это флаг для CI и скриптов, где отвечать мастеру некому.

tdcv2 init --yes
tdcv2 init --yes
Wrote project config: /path/to/project/tdcv2.config.json
data packs → /path/to/project/tdcv2-packs
locale     → en

--global / -g — один конфиг на все проекты

Пишет конфиг в домашнюю область (~/.config/tdcv2), а не в текущую папку. Пригодится, когда вы хотите одно общее хранилище данных, из которого читают все проекты на машине, вместо папки tdcv2-packs в каждом репозитории.

tdcv2 init --global
tdcv2 init --global
Wrote global config: /Users/you/.config/tdcv2/config.json
data packs → /Users/you/.config/tdcv2/packs
locale     → en

--force / -f — перезаписать существующий конфиг

По умолчанию init отказывается затирать конфиг, который уже есть. Передайте --force, когда вы намеренно хотите его сбросить — например, чтобы сменить папку пакетов или начать с чистого листа.

tdcv2 init (конфиг уже существует)
Config already exists: /path/to/project/tdcv2.config.json
Nothing written. Re-run with --force to overwrite.

--locale <loc> — выбрать локаль по умолчанию

Задаёт значение locale в конфиге, чтобы не указывать локаль при каждой генерации. en — встроенное значение по умолчанию; передайте другой код, чтобы сделать его локалью проекта.

tdcv2 init --yes --locale ru

--data-path <dir> — выбрать папку пакетов

Задаёт, куда pack add качает данные (это packStore, см. ниже). Укажите общий диск или путь вне репозитория, когда не хотите, чтобы пакеты лежали рядом с исходниками.

tdcv2 init --yes --data-path ../shared-tdc-packs

Файл tdcv2.config.json

init пишет вот такой небольшой файл:

{
"packStore": "./tdcv2-packs",
"locale": "ru"
}
  • packStore — куда pack качает пакеты. Каждый набор ложится в эту одну папку, а первый pack add прописывает саму папку в dataPaths. Как она устроена, описано в разделе «Внутри хранилища пакетов» ниже.
  • locale — локаль по умолчанию (задаётся флагом --locale, см. выше).
  • dataPaths — папки, которые движок реально сканирует в поисках пакетов. pack add вписывает туда хранилище за вас, а вы можете дописать сюда свои папки, чтобы указать движку на пакеты, написанные вами самими.

Конфиг ищется обходом вверх от текущей папки (так же, как инструменты находят tsconfig.json). Когда одно и то же определено в нескольких источниках, приоритет идёт от низшего к высшему:

встроенные пакеты < общий конфиг (~/.config/tdcv2) < проектный tdcv2.config.json < флаг --data-path

Пути внутри файла разрешаются относительно самого файла, а не относительно текущей рабочей папки — так что конфиг может переезжать вместе со своим проектом.

tdcv2 pack — скачать и удалить наборы

Без аргументов в терминале pack открывает меню выбора, а не вываливает на вас каталог. 108 наборов на экран не помещаются, поэтому их листают так, как они устроены:

  • Всё или выбрать нужное — первый вопрос, до всего остального.
  • Языки — одним списком; страны — через континент, с карты.
  • / ищет из любого места: наберите braz, и Бразилия уже здесь, с пометкой континента.
  • space отмечает, а на континенте берёт весь континент сразу.
  • backspace, esc или — шаг назад с любого экрана.
  • Обзор перечисляет корзину и её общий размер; space убирает то, что вы передумали брать, enter применяет. До этого не качается ничего.

Карта показывает, что уже набрано: континент под курсором подсвечивается, а каждая выбранная страна зажигает искру там, где она и находится. m переключает между голыми береговыми линиями и залитой сушей.

Меню выбора во всех реализациях одно и то же, а как его рисовать, решает терминал: полублоки и цвет там, где они есть, ASCII и простой контур там, где их нет (старая консоль Windows, пайп, NO_COLOR). Меню в Java и Rust требует stty и поэтому работает только на Unix; в Windows они вместо этого печатают список — Node, Python и C# так делать не приходится, потому что их среды читают нажатие клавиши сами.

В скрипте — и вообще там, где терминала нет, — управляйте им подкомандами:

tdcv2 pack list # что есть в реестре
tdcv2 pack add ru common # скачать и подключить
tdcv2 pack remove common # удалить

Любая подкоманда принимает ещё и --registry <базовый-url> — он направляет pack на другой каталог вместо публичного. По умолчанию берётся собственный реестр проекта:

tdcv2 pack list --registry https://packs.example.internal/tdc
tdcv2 pack add ru --registry=https://packs.example.internal/tdc

Пригодится для зеркала внутри компании или копии в изолированном контуре. URL здесь базовый — пути к индексу и архивам pack добавляет сам, — а хвостовой слеш игнорируется. Проверка sha256 при этом остаётся: зеркало, отдающее изменённые байты, не установится ровно так же, как не установился бы публичный реестр.

pack list — посмотреть каталог

Печатает реестр и помечает то, что уже установлено, с размером загрузки каждого набора.

tdcv2 pack list
Available data packs:

common Common (locale-agnostic) (0.0 MB)
Generators bound to neither a language nor a country: uuid,
hashes, ISBN/ISSN, GTIN/UPC/EAN, card PANs, MRZ, IPv4/IPv6/MAC,
semver, and more.

ru ✓ installed Russian (language) (0.1 MB)
Content bound to the Russian language: given names, gendered
surnames and patronymics, gender words, months and weekdays,
colors, country names. Shared by every Russian-speaking locale.

…

yemen Yemen (country) (0.0 MB)
Data specific to Yemen: docs, education, finance, geo, holiday,
phone, sport.

Install with: tdcv2 pack add <id>

Описания переносятся по ширине вашего окна, так что список остаётся списком, каким бы узким ни был терминал. В пайпе или при перенаправлении окна для замера нет, и все пять реализаций берут 80 колонок — поэтому сохранённый листинг выходит одним и тем же файлом, какая бы из них его ни писала.

В каталоге сегодня 108 наборов: common, десять языков и 97 стран. Языка или страны, которых в списке нет, ещё не доделали: запись в каталоге — это обещание, что каждый адрес под ней разрешается, поэтому папка с одним файлом такой записи не получает.

Пригодится, чтобы проверить, что нужно адресу перед генерацией, и подтвердить, что набор встал после pack add.

pack add <id…> — скачать и зарегистрировать

pack add качает zip набора, сверяет его sha256 (подменённая или битая загрузка не установится), распаковывает его в хранилище пакетов и прописывает это хранилище в конфиг, так что данные сразу доступны по своим адресам через точку — без отдельного шага подключения.

tdcv2 pack add ru
tdcv2 pack add ru
Installed ru: 355 files → /path/to/project/tdcv2-packs/ru
registered ./tdcv2-packs in /path/to/project/tdcv2.config.json

Хранилище прописывается один раз, при первой установке. Следующие наборы ложатся в ту же папку и сообщают already registered.

Можно установить несколько наборов за один вызов — tdcv2 pack add common ru russia — это обычный способ собрать локаль (см. раздел «Пакеты осевые» ниже).

pack remove <id…> — удалить и отменить регистрацию

pack remove удаляет ровно те пути, которые принёс этот набор, и ничего рядом с ними. Папка, опустевшая после удаления, уходит следом.

tdcv2 pack remove russia
tdcv2 pack remove russia
Removed russia (/path/to/project/tdcv2-packs/countries/russia)

Хранилище остаётся в dataPaths, пока в нём что-то лежит: одна эта запись обслуживает все наборы сразу. Уберите последний набор — уйдёт и запись:

tdcv2 pack remove common ru
Removed common (/path/to/project/tdcv2-packs/common)
Removed ru (/path/to/project/tdcv2-packs/ru)
store now empty — unregistered /path/to/project/tdcv2-packs from /path/to/project/tdcv2.config.json

Удаление набора безопасно: встроенный набор по умолчанию (см. раздел «Встроенный набор по умолчанию против докачки») по этим адресам возвращается сам собой.

Внутри хранилища пакетов

Каждый набор распаковывается в одну папку, которую называет packStore. Язык ложится под своим кодом, страна — в countries/, а common — под своим именем:

tdcv2-packs/
├── .tdcv2-installed.json
├── common/…
├── ru/…
└── countries/russia/…

Эта папка — единственный корень сканирования, поэтому в конфиге одна запись dataPaths, сколько бы наборов вы ни поставили:

{
"packStore": "./tdcv2-packs",
"locale": "ru",
"dataPaths": ["./tdcv2-packs"]
}

.tdcv2-installed.json — служебный учёт самого хранилища, править его руками не нужно. По каждому набору там записаны пути, которыми он владеет, число принесённых файлов, sha256, по которому сверялась загрузка, и версия, если реестр её публикует. Именно из этого файла pack remove узнаёт, что удалять, а pack list — что пометить как ✓ installed.

Хранилище от предыдущей версии

Прежние версии распаковывали каждый набор в <store>/<id>/packs/… и давали ему отдельную запись в dataPaths. На диске это давало три почти одинаковых уровня, а в конфиге — по записи на набор: сотня пакетов стран означала сотню записей.

Первая же команда tdcv2 pack — любая из них — переносит такое хранилище к раскладке выше, прямо на месте. Скачивать заново ничего не нужно. Сообщение уходит в stderr:

tdcv2 pack list (хранилище в старой раскладке)
tdcv2: pack store "/path/to/project/tdcv2-packs" used the old per-bundle layout; moved it to the flat one.
ru: ru/packs → ru (355 files)
russia: russia/packs → countries/russia (18 files)
dropped 2 per-bundle dataPaths entries
registered ./tdcv2-packs instead

Все перемещения планируются до того, как что-то сдвинется. Если путь в новой раскладке уже занят, перенос отклоняется целиком, а конфликты называются поимённо — вместо того чтобы оставить хранилище наполовину в одной раскладке, наполовину в другой.

Пакеты осевые

Пакеты организованы по одной оси — язык, страна или локаль-независимый набор common — и они компонуются. Данные для России по-русски — это не один монолитный пакет, а три слоя друг на друге:

tdcv2 pack add common ru russia
tdcv2 pack add common ru russia
Installed common: 145 files → /path/to/project/tdcv2-packs/common
registered ./tdcv2-packs in /path/to/project/tdcv2.config.json
Installed ru: 355 files → /path/to/project/tdcv2-packs/ru
already registered in /path/to/project/tdcv2.config.json
Installed russia: 18 files → /path/to/project/tdcv2-packs/countries/russia
already registered in /path/to/project/tdcv2.config.json

В хранилище остаются три папки под одной записью dataPaths, которая покрывает их все, — см. раздел «Внутри хранилища пакетов» выше.

Это не причуда формата файлов — так отражается, что язык и страна действительно независимы. Русский язык общий для России, Беларуси и Казахстана, поэтому он качается один раз как ru; а данные, специфичные для страны (регионы России, телефонные коды), лежат в russia. Смешивайте и сочетайте, чтобы собрать любую нужную локаль.

Встроенный набор по умолчанию против докачки

Встроенный набор по умолчанию (едет внутри пакета) — это самый нижний слой, и он всегда на месте. Скачанный набор кладётся сверху и затеняет те же адреса, ничего не удаляя под собой. Отсюда два следствия:

  • ставите полный набор → он перекрывает дефолтный по этим адресам;
  • pack remove → дефолтный сам возвращается. Дыры в данных не будет.

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

Откуда берётся базовый слой

Этот базовый слой ищется тремя вопросами по порядку — одними и теми же, в одном и том же порядке, во всех пяти реализациях:

ПорядокГдеКогда отвечает
1TDCV2_PACKS, если это папкаВы её задали — значит, она главнее всего остального
2Чекаут исходников TDCТолько если сам TDC собран из исходников
3Набор внутри установленного пакетаОбычный случай — именно так работает установленный пакет

Шаг 2 нужен тем, кто работает над самим TDC: внутри чекаута все пять реализаций читают data/packs из репозитория, то есть видят одну копию данных, а не пять, которые могут разъехаться. Для установленного пакета этот шаг сработать не может, и он намеренно не соглашается на любую папку с именем data/packs — папка должна быть узнаваемо репозиторием TDC, чтобы ваша собственная папка с таким же именем случайно не подхватилась.

TDCV2_PACKS — это способ указать всем пяти реализациям на одну папку, ничего не правя в конфигах:

TDCV2_PACKS=/srv/shared-packs tdcv2 users.tdc

Всё, что называют tdcv2.config.json и --data-path, кладётся поверх этого ответа, а не вместо него.

Смотрите также