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

tf-transport-north-layers

v0.1.2

Published

Layer requests, styles, tooltips and filters for Transport North public roads map.

Readme

tf-transport-north-layers

Описание слоев дорог, участков дорожных мероприятий и гарантийных дефектов для публичной карты портала "Транспорт Севера".

Пакет превращает правила слоев цифрового двойника в переносимый JavaScript API:

  • строит payload для запросов /api/v1/vl/data;
  • хранит публичные справочники классификаций дорог и статусов мероприятий;
  • возвращает минимальные zoom-пороги, с которых имеет смысл запускать запросы;
  • вычисляет стили линий по GeoJSON feature и текущему zoom;
  • возвращает модель tooltip, готовую для отображения вызывающим приложением;
  • фильтрует участки мероприятий по выбранным годам.

Пакет не выполняет HTTP-запросы, не создает слои карты и не зависит от Vue, Deck.gl, TMap или другого UI-фреймворка. Вызывающее приложение само отправляет запросы, хранит полученные GeoJSON features и решает, как именно их отрисовывать.

Установка

npm install tf-transport-north-layers

Для локальной разработки в монорепозитории пакет может подключаться через file::

{
  "dependencies": {
    "tf-transport-north-layers": "file:packages/tf-transport-north-layers"
  }
}

Требования

  • Runtime с поддержкой ES modules.
  • Доступ к backend endpoint /api/v1/vl/data.
  • Ответ /vl/data должен быть GeoJSON FeatureCollection, где данные объектов лежат в feature.properties, включая вложенные объекты Inner.

Быстрый пример

import { ROAD_CLASSIFICATION, buildRoadsVlDataRequest, getRoadMinZoom, getRoadStyle, getRoadTooltip } from "tf-transport-north-layers"

async function loadFederalRoads({ bbox, zoom, http }) {
  const classification = ROAD_CLASSIFICATION.FEDERAL

  if (zoom < getRoadMinZoom(classification)) {
    return []
  }

  const payload = buildRoadsVlDataRequest({ bbox, classification })
  const response = await http.post("/api/v1/vl/data", payload)

  return response.data.features.map(feature => ({
    feature,
    style: getRoadStyle(feature, zoom),
    tooltip: getRoadTooltip(feature)
  }))
}

Общая модель работы

  1. Получить текущий bbox карты и текущий zoom.
  2. Сформировать набор запросов через build*VlDataRequest.
  3. Проверить zoom через соответствующий get*MinZoom или константу *_MIN_ZOOM.
  4. Отправить подходящие запросы в /api/v1/vl/data.
  5. Для каждой feature вызвать style-функцию.
  6. Если style-функция вернула null, feature не должна отрисовываться на текущем zoom.
  7. Для интерактивных слоев вызвать tooltip-функцию и передать результат в UI.

BBox

Все билдеры принимают bbox и передают его в:

{
  Filters: {
    Bounded: true,
    BoundingBox: bbox
  }
}

Формат bbox должен соответствовать формату, который backend /vl/data ожидает в Filters.BoundingBox.

Пакет не нормализует координаты и не преобразует CRS. Это ответственность вызывающего приложения.

Дороги

ROAD_CLASSIFICATION

import { ROAD_CLASSIFICATION } from "tf-transport-north-layers"

| Ключ | Значение | Описание | | ---------- | -------- | ------------- | | FEDERAL | 1 | Федеральные | | REGIONAL | 2 | Региональные | | LOCAL | 3 | Муниципальные |

buildRoadsVlDataRequest

buildRoadsVlDataRequest({ bbox, classification })

Создает payload для запроса дорожных осей RoadPart.

Параметры:

| Параметр | Тип | Описание | | ---------------- | -------- | ------------------------------------------ | | bbox | any | Bounding box в формате backend /vl/data. | | classification | number | Одно из значений ROAD_CLASSIFICATION. |

Важно: функция строит один запрос для одной классификации. Пакет намеренно не объединяет классификации в один payload, потому что backend /vl/data не обязан поддерживать массивы в фильтрах вида Value: [1, 2, 3].

Запрашиваемые данные включают поля, необходимые для:

  • отрисовки геометрии;
  • определения классификации дороги;
  • tooltip дороги: код, название, владелец, значение дороги, протяженность.

ROAD_MIN_ZOOM_BY_CLASSIFICATION

import { ROAD_MIN_ZOOM_BY_CLASSIFICATION } from "tf-transport-north-layers"

Минимальные zoom-пороги для запуска запросов дорог.

| Классификация | minZoom | | ------------------------------ | ------- | | ROAD_CLASSIFICATION.FEDERAL | 3 | | ROAD_CLASSIFICATION.REGIONAL | 3 | | ROAD_CLASSIFICATION.LOCAL | 13 |

getRoadMinZoom

getRoadMinZoom(classification)

Возвращает минимальный zoom для указанной классификации дороги.

Это основной способ получить zoom-порог для road-request. Например, муниципальные дороги начинают запрашиваться только с zoom >= 13.

Если классификация неизвестна, возвращает 0.

getRoadStyle

getRoadStyle(feature, zoom)

Возвращает стиль дороги для текущего zoom или null, если дорога на этом zoom не должна отрисовываться.

Формат результата:

{
  classification: 1,
  renderFuncName: "Line",
  styles: [
    {
      role: "main",
      color: "#F8A305",
      width: 4,
      opacity: 0,
      dashArray: "0",
      paneIndex: 2
    }
  ]
}

styles всегда является массивом. Это важно для совместимости с объектами, которым нужны несколько линий поверх друг друга: основная линия и подложка.

getRoadTooltip

getRoadTooltip(feature)

Возвращает модель tooltip для дороги или null, если в feature нет полезных данных.

Формат результата:

{
  data: [
    { value: "Дорога", class: "t-table__header" },
    { label: "Код", value: "А-123" },
    { label: "Название", value: "..." },
    { label: "Владелец", value: "..." },
    { label: "Значение дороги", value: "Федеральная" },
    { label: "Протяженность", value: "12.3 км" }
  ]
}

Tooltip дороги содержит только публично полезные поля:

  • код;
  • название;
  • владелец;
  • значение дороги;
  • протяженность.

Участки мероприятий

ROAD_ACTIVITY_STATUS

import { ROAD_ACTIVITY_STATUS } from "tf-transport-north-layers"

| Ключ | Значение | Описание | | ------------- | -------- | ----------- | | PLANNED | 3 | Планируется | | IN_PROGRESS | 4 | Реализуется | | COMPLETED | 5 | Завершено |

buildRoadActivitySectorsVlDataRequest

buildRoadActivitySectorsVlDataRequest({ bbox, status })

Создает payload для запроса участков дорожных мероприятий. Запрос соответствует материализованному слою ЦД: исходный слой RoadActivityPart с materialized: true превращается в объект /vl/data RoadActivityPartMaterialized.

Параметры:

| Параметр | Тип | Описание | | -------- | -------- | ------------------------------------------ | | bbox | any | Bounding box в формате backend /vl/data. | | status | number | Одно из значений ROAD_ACTIVITY_STATUS. |

Функция строит один запрос для одного статуса. Пакет намеренно не объединяет статусы в один payload, потому что backend /vl/data не обязан поддерживать массивы в фильтрах вида ActivityState: [3, 4, 5].

Запрашиваемые данные включают поля, необходимые для:

  • отрисовки геометрии;
  • определения статуса, года и классификации дороги;
  • tooltip мероприятия и участка.

ROAD_ACTIVITY_SECTOR_MIN_ZOOM_BY_STATUS

import { ROAD_ACTIVITY_SECTOR_MIN_ZOOM_BY_STATUS } from "tf-transport-north-layers"

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

| Статус | minZoom | | ---------------------------------- | ------- | | ROAD_ACTIVITY_STATUS.PLANNED | 6 | | ROAD_ACTIVITY_STATUS.IN_PROGRESS | 6 | | ROAD_ACTIVITY_STATUS.COMPLETED | 6 |

getRoadActivitySectorMinZoom

getRoadActivitySectorMinZoom(status)

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

Если статус неизвестен, возвращает 0.

filterRoadActivitySectors

filterRoadActivitySectors(features, { years })

Фильтрует features участков мероприятий по годам.

Параметры:

| Параметр | Тип | Описание | | ---------- | ---------- | ------------------------------------------------------------ | | features | Array | GeoJSON features, полученные из /vl/data. | | years | number[] | Разрешенные годы. Если массив пустой, фильтр не применяется. |

Для завершенных мероприятий год берется из EndDate.

Для планируемых и реализуемых мероприятий год берется из StartDate.

getRoadActivitySectorStyle

getRoadActivitySectorStyle(feature, zoom)

Возвращает стиль участка мероприятия для текущего zoom или null, если участок на этом zoom не должен отрисовываться.

Формат результата:

{
  renderFuncName: "Line",
  styles: [
    {
      role: "extra",
      color: "#656565",
      width: 6,
      opacity: 1,
      dashArray: "0",
      paneIndex: 4
    },
    {
      role: "main",
      color: "#30B92F",
      width: 4,
      opacity: 1,
      dashArray: "0",
      paneIndex: 15
    }
  ]
}

У мероприятий часто есть две линии:

  • extra - подложка или обводка;
  • main - основная линия.

Вызывающий код должен отрисовать все элементы массива styles, сохранив paneIndex или аналогичный порядок наложения.

getRoadActivitySectorTooltip

getRoadActivitySectorTooltip(feature)

Возвращает модель tooltip для участка мероприятия или null.

Tooltip может содержать секции:

  • Мероприятие;
  • Участок;
  • Гарантия, если feature относится к гарантийному объекту.

Пример:

{
  data: [
    { value: "Мероприятие", class: "t-table__header" },
    { label: "Название", value: "..." },
    { label: "Статус", value: "Реализуется" },
    { label: "Период", value: "01.05.2026 - 30.09.2026" },
    { label: "Заказчик", value: "..." },
    { label: "Подрядчик", value: "..." },
    { value: "Участок", class: "t-table__header" },
    { label: "Линейные координаты", value: "12+345 - 13+210" },
    { label: "Протяженность", value: "865 м" }
  ]
}

Гарантийные дефекты

Гарантийные дефекты запрашиваются отдельно от участков мероприятий, потому что используют отдельный Inner.GuaranteeID, собственные правила отображения и вложенный дефектный участок дороги.

Payload повторяет устройство исходного слоя ЦД:

  • основной объект: RoadActivityPartMaterialized;
  • гарантийный паспорт: Inner.GuaranteeID;
  • дефектный участок дороги: Inner.PartID.Inner.ID;
  • тип дефектного участка: RoadPartSector с AttrObjectTypeID: 1001266.

buildRoadGuaranteeDefectsVlDataRequest

buildRoadGuaranteeDefectsVlDataRequest({ bbox })

Создает payload для запроса гарантийных дефектов.

Параметры:

| Параметр | Тип | Описание | | -------- | ----- | ------------------------------------------ | | bbox | any | Bounding box в формате backend /vl/data. |

ROAD_GUARANTEE_DEFECTS_MIN_ZOOM

import { ROAD_GUARANTEE_DEFECTS_MIN_ZOOM } from "tf-transport-north-layers"

Минимальный zoom для запуска запроса гарантийных дефектов: 8.

getRoadGuaranteeDefectStyle

getRoadGuaranteeDefectStyle(feature, zoom)

Возвращает стиль гарантийного дефекта для текущего zoom либо null.

Гарантийные участки отрисовываются с zoom >= 8.

getRoadGuaranteeDefectTooltip

getRoadGuaranteeDefectTooltip(feature)

Tooltip использует те же секции, что и участок мероприятия, при наличии гарантийных данных добавляет секцию Гарантия, а при наличии вложенного дефектного участка добавляет секции Дефект и Дорога.

Полный пример формирования requests

import {
  ROAD_ACTIVITY_STATUS,
  ROAD_CLASSIFICATION,
  ROAD_GUARANTEE_DEFECTS_MIN_ZOOM,
  buildRoadActivitySectorsVlDataRequest,
  buildRoadGuaranteeDefectsVlDataRequest,
  buildRoadsVlDataRequest,
  getRoadActivitySectorMinZoom,
  getRoadMinZoom
} from "tf-transport-north-layers"

function buildRequests({ bbox, zoom }) {
  const requests = []

  for (const classification of [ROAD_CLASSIFICATION.FEDERAL, ROAD_CLASSIFICATION.REGIONAL, ROAD_CLASSIFICATION.LOCAL]) {
    requests.push({
      type: "road",
      minZoom: getRoadMinZoom(classification),
      request: buildRoadsVlDataRequest({ bbox, classification })
    })
  }

  for (const status of [ROAD_ACTIVITY_STATUS.PLANNED, ROAD_ACTIVITY_STATUS.IN_PROGRESS, ROAD_ACTIVITY_STATUS.COMPLETED]) {
    requests.push({
      type: "activity",
      minZoom: getRoadActivitySectorMinZoom(status),
      request: buildRoadActivitySectorsVlDataRequest({ bbox, status })
    })
  }

  requests.push({
    type: "guaranteeDefect",
    minZoom: ROAD_GUARANTEE_DEFECTS_MIN_ZOOM,
    request: buildRoadGuaranteeDefectsVlDataRequest({ bbox })
  })

  return requests.filter(item => zoom >= item.minZoom)
}

Полный пример отрисовочной подготовки

import {
  filterRoadActivitySectors,
  getRoadActivitySectorStyle,
  getRoadActivitySectorTooltip,
  getRoadGuaranteeDefectStyle,
  getRoadGuaranteeDefectTooltip,
  getRoadStyle,
  getRoadTooltip
} from "tf-transport-north-layers"

function toRenderableFeatures({ roads, activitySectors, guaranteeDefects, years, zoom }) {
  return [
    ...roads.map(feature => ({
      feature,
      style: getRoadStyle(feature, zoom),
      tooltip: getRoadTooltip(feature)
    })),
    ...filterRoadActivitySectors(activitySectors, { years }).map(feature => ({
      feature,
      style: getRoadActivitySectorStyle(feature, zoom),
      tooltip: getRoadActivitySectorTooltip(feature)
    })),
    ...guaranteeDefects.map(feature => ({
      feature,
      style: getRoadGuaranteeDefectStyle(feature, zoom),
      tooltip: getRoadGuaranteeDefectTooltip(feature)
    }))
  ].filter(item => item.style)
}

Формат стиля

Style-функции возвращают объект:

{
  renderFuncName: "Line",
  styles: LineStyle[]
}

LineStyle:

| Поле | Тип | Описание | | ----------- | -------- | ------------------------------------------------------ | | role | string | Роль линии: main или extra. | | color | string | Цвет линии в hex-формате. | | width | number | Толщина линии. | | opacity | number | Прозрачность от 0 до 1. | | dashArray | string | Паттерн пунктирной линии, например "5, 5" или "0". | | paneIndex | number | Порядок наложения линий. |

Вызывающий код не должен предполагать, что стиль всегда один. Нужно отрисовывать каждый элемент массива styles.

Формат tooltip

Tooltip-функции возвращают:

{
  data: TooltipRow[]
}

TooltipRow:

| Поле | Тип | Описание | | ------- | -------- | ---------------------------------------------------------------- | | value | string | Значение строки или заголовок секции. | | label | string | Подпись значения. Может отсутствовать у заголовков. | | class | string | CSS-класс строки. Для заголовков используется t-table__header. |

Пакет не рендерит tooltip. Он только возвращает модель данных, чтобы вызывающий код мог использовать свой компонент tooltip.

Экспортируемый API

export {
  ROAD_CLASSIFICATION,
  ROAD_MIN_ZOOM_BY_CLASSIFICATION,
  buildRoadsVlDataRequest,
  getRoadMinZoom,
  getRoadStyle,
  getRoadTooltip,
  ROAD_ACTIVITY_STATUS,
  ROAD_ACTIVITY_SECTOR_MIN_ZOOM_BY_STATUS,
  ROAD_GUARANTEE_DEFECTS_MIN_ZOOM,
  buildRoadActivitySectorsVlDataRequest,
  buildRoadGuaranteeDefectsVlDataRequest,
  filterRoadActivitySectors,
  getRoadActivitySectorMinZoom,
  getRoadActivitySectorStyle,
  getRoadActivitySectorTooltip,
  getRoadGuaranteeDefectStyle,
  getRoadGuaranteeDefectTooltip
}

Ограничения и договоренности

  • Пакет не объединяет разные классификации дорог в один запрос.
  • Пакет не объединяет разные статусы мероприятий в один запрос.
  • Пакет не предполагает поддержку массивов в фильтрах /vl/data.
  • Пакет не делает нормализацию feature properties.
  • Пакет ожидает вложенность данных через properties.Inner.
  • Пакет не хранит состояние карты, bbox, zoom, выбранные фильтры и результаты запросов.
  • Пакет не управляет отменой HTTP-запросов и busy-индикаторами.
  • Пакет не выполняет локализацию UI, но возвращает русские подписи tooltip, соответствующие текущему порталу.

Проверка перед публикацией

Минимальный набор проверок:

node --check src/index.js
node --check src/roads.js
node --check src/roadActivitySectors.js
node --check src/helpers.js

Для проекта, который подключает пакет через file:, также стоит запускать сборку приложения-потребителя.