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

@grit-npm/grit-utils

v0.3.8

Published

Collection of handy utils for use in JavaScript and OpenLayers projects.

Downloads

20

Readme

grit-utils

License: MIT ESM Ready

A collection of handy utility functions for JavaScript and OpenLayers projects.


Features

  • Geometry helpers for working with OpenLayers layers and features
  • Styling utilities to generate custom polygon styles
  • Marker placement functions for additional polygon highlighting
  • General utilities like a modern, Vuex-compatible debounce function
  • Fully ESM-based build with optimized Rollup output
  • Tree-shakable — only import what you need

Installation

npm install grit-utils
# or
yarn add grit-utils
# or
pnpm add grit-utils

Usage

Example: Add a feature to a layer

import { addFeatureToLayer } from "@grit-npm/grit-utils";

// Assuming you have a Vector layer with a source:
addFeatureToLayer(myVectorLayer, myFeature);

Example: Generate a polygon style

import { generatePolygonStyle } from "@grit-npm/grit-utils";

const customStyle = generatePolygonStyle({
  stroke: { color: 'red', width: 2, lineDash: [4, 4] },
  fill:   { color: 'rgba(255,0,0,0.5)' }
})

Example: Placing additional Polygon Marker

import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Feature from "ol/Feature";
import { Polygon } from "ol/geom";
import { placingAdditionalPolygonMarker } from "@grit-npm/grit-utils";
import mapMarker from "./mapMarker";
import store from "./store";

const vectorLayer = new VectorLayer({ source: new VectorSource() })
map.addLayer(vectorLayer)

const squareFeature = new Feature(new Polygon([[
  [0, 0],
  [100, 0],
  [100, 100],
  [0, 100],
  [0, 0]
]]))

placingAdditionalPolygonMarker(
  vectorLayer,
  mapMarker,
  store,
  "HighlightFkz",
  [squareFeature],
  defaultStyleObject,
  true
)

Example: Placing additional Polygon Marker by Geometry

import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Polygon } from "ol/geom";
import { placingAdditionalPolygonMarkerByGeom } from "@grit-npm/grit-utils";
import mapMarker from "./mapMarker";
import store from "./store";

const vectorLayer = new VectorLayer({ source: new VectorSource() })
map.addLayer(vectorLayer)

const square = new Polygon([[
  [0, 0],
  [100, 0],
  [100, 100],
  [0, 100],
  [0, 0]
]])

placingAdditionalPolygonMarkerByGeom(
  vectorLayer,
  mapMarker,
  store,
  "HighlightFkz",
  square,
  defaultStyleObject,
  false, // not clicked
  true   // use additional style
)

Example: Remove Feature from Layer

import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Feature from "ol/Feature";
import { Polygon } from "ol/geom";
import { removeFeatureFromLayer } from "@grit-npm/grit-utils";

// 1. Create a vector layer and add it to your map
const layer = new VectorLayer({
  source: new VectorSource(),
});
map.addLayer(layer)

// 2. Create a simple polygon feature
const square = new Polygon([[
  [0, 0],
  [10, 0],
  [10, 10],
  [0, 10],
  [0, 0]
]])
const feature = new Feature(square);

// 3. Add the feature to the layer
layer.getSource().addFeature(feature);

// 4. Remove the feature from the layer
removeFeatureFromLayer(layer, feature);

Example: Change active module in menu

import { changeModule } from "@grit-npm/grit-utils";
import store from "./store";

await changeModule(store, "measure", "mainMenu");

Example: Debounce any function (supports Vuex dispatch)

import { debounce } from "@grit-npm/grit-utils";

// Normal function debounce
const debouncedResize = debounce(onResize);

window.addEventListener("resize", debouncedResize);

// Vuex dispatch debounce
await debounce.dispatch(
  store,
  "Modules/Module/FETCH_URL",
  { id },
  { root: true },
  500,
);

Example: Get module properties from store configuration

import { getModuleProps } from "@grit-npm/grit-utils";
import store from "./store";

// Get configuration for a specific module
const moduleConfig = getModuleProps(store, "measure");
// Returns: { name: 'Measure', type: 'measure', ...otherProps }

// For modules not found in config, returns default structure
const unknownConfig = getModuleProps(store, "unknownModule");
// Returns: { name: 'UnknownModule', type: 'unknownModule' }

Example: Determine the menu side of a module

import { getModuleSide } from "@grit-npm/grit-utils";
import store from "./store";

const side = getModuleSide(store, "legend");
// => "mainMenu"

// Optional: limit the inspected sides
const custom = getModuleSide(store, "measure", { sides: ["secondaryMenu"] });

Example: Wait until a Vuex module is ready

import { waitForModule } from "@grit-npm/grit-utils";
import store from "./store";

// Resolve when module exists and has at least one key
const measure = await waitForModule(store, "measure");

// Wait for specific state and resolve a derived value directly
const layerList = await waitForModule(store, "layers", {
  predicate: (m) => Array.isArray(m?.list) && m.list.length > 0,
  selector: (m) => m.list,
});

// Add a timeout so calls don’t wait indefinitely
await waitForModule(store, "topics", { timeout: 10000 });

Example: Check whether a module is active (with GFI handling)

import { isGfiModuleActive } from "@grit-npm/grit-utils";
import store from "./store";

// Consider module active if it’s the current component or if GFI is open and matches selectors
const isActive = isGfiModuleActive(store, "measure", ["#my-gfi", ".gfi-panel"]);

// With explicit flag and custom side name
const active = isGfiModuleActive(store, "buffer", [], { flag: this.isActive, side: "mainMenu" });

Example: Highlight FKZ by querying WFS around a coordinate

import { handleFkzHighlighting } from "@grit-npm/grit-utils";
import store from "./store";

const coordinate = [565000, 5934000]; // EPSG:25832 [x, y]
const request = {
  url: "https://example.org/wfs",
  typename: "my:typename",
  storedQueryId: "STORED_QUERY_ID",
  outputFormat: "application/json",
}

await handleFkzHighlighting(
  store,
  coordinate,
  request,
  (data) => {
    // Use response payload for highlighting
    // e.g., parse features and update your map
  }
)

Type Definitions

  • JSDoc‑driven types are generated automatically after each build.
  • The build runs Rollup and then tsc in declaration‑only mode, emitting .d.ts files to dist.
  • We don’t use TypeScript for source — the TS step only reads JSDoc and writes definitions.

Commands

  • Generate types manually: npm run types
  • Build (JS + types): npm run build

Notes

  • JS type checking is disabled for generation (checkJs: false) to keep the process non‑blocking.
  • Editors pick up types via package.json types and per‑module exports entries.

Development

  • Install deps: npm ci
  • Build library: npm run build
  • Local pack test: npm pack
  • Lint/format (Biome): npx biome check . and npx biome format --write .
  • Lint ignores generated files under dist/**.

Automation

  • Rollup inputs are discovered automatically; any new src/**/*.js (except src/index.js) is included in the build.
  • Package exports are synced automatically before each build (prebuild):
    • For every src/<path>.js, an export entry is generated:
      • key: "./<path>"
      • import: "./dist/<path>.js"
      • types: "./dist/<path>.d.ts"
  • You can run the sync directly: node scripts/sync-exports.js.

Requirements

  • Node.js: 16, 18, or 20 LTS recommended.
  • Peer dependencies (not bundled):
    • ol 9.2.4
    • @masterportal/masterportalapi 2.40.0
    • axios, i18next, i18next-vue when using related helpers

Engine note

  • Using Node 22 may show an EBADENGINE warning from @masterportal/masterportalapi (it declares support for 16/18/20). It’s a warning only; use Node 20 LTS to silence it if desired.