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

danskadresseapi-sdk

v4.0.1

Published

Officiel JavaScript/TypeScript SDK for DanskAdresseAPI — drop-in DAWA replacement. Taler DAWA-fladen (/dawa) med BBR, statistik og batch som udvidelser, replikering-iterator, webhook-verify og React hooks.

Readme

danskadresseapi-sdk

Officiel JavaScript/TypeScript SDK for DanskAdresseAPI.

SDK'et taler DAWA-fladen (/dawa): samme stier, parametre og svarformer som det officielle DAWA, som lukker 1. oktober 2026. Svarene er DAWA's egne rene arrays og objekter. Oven på det giver SDK'et adgang til de udvidelser DAWA aldrig har haft: BBR, statistik, batch-opslag og struktureret validering.

v4 — DAWA-fladen som standard. Opgraderer du fra v3, så læs Opgradering fra v3.

Installation

bun add danskadresseapi-sdk
# eller: npm install danskadresseapi-sdk

Quick start

import { Addr } from 'danskadresseapi-sdk';

const addr = new Addr({ apiKey: process.env.ADDR_KEY! });

// Autocomplete — trinvis som DAWA: vejnavn → husnr → etage/dør
const forslag = await addr.autocomplete({ q: 'Nørrebrog', fuzzy: true });

// Reverse geocoding — x er længdegrad, y er breddegrad
const adresse = await addr.reverse({ x: 12.5571, y: 55.6883 });

// Datavask — rens én ustruktureret adressetekst
const vask = await addr.datavask({ betegnelse: 'Nørrebrogade 1, 2200 København N' });
// → { kategori: 'A' | 'B' | 'C', resultater: [...] }

// Adresse + BBR i ét kald
const medBbr = await addr.adgangsadresser.byId('0a3f5089-b3a7-32b8-e044-0003ba298018', { include: 'bbr' });

⚠️ x og y. DAWA's rækkefølge er x = længdegrad, y = breddegrad — omvendt af den lat/lon, mange er vant til. SDK'et kaster en AddrError med err.type === 'koordinater_ombyttet', hvis du sender dem byttet om, i stedet for at give dig en adresse i Østersøen. (Udvidelserne på /v1 — batch, geo — bruger fortsat lat/lon, se nedenfor.)

DAWA-fladen

// Adresser og adgangsadresser — rene arrays, DAWA's parameternavne
await addr.adresser.search({ vejnavn: 'Rentemestervej', husnr: '8', postnr: '2400', etage: '2' });
await addr.adresser.byId('0a3f50a0-4661-32b8-e044-0003ba298018', { struktur: 'mini' });
await addr.adgangsadresser.search({ q: 'Sivmosevænget 3', per_side: 10 });

// DAGI — hvert tema har liste, opslag og reverse
await addr.dagi.politikreds('1470');
await addr.dagi.sogne({ per_side: 50 });
await addr.dagi.reverse('sogne', { x: 12.53, y: 55.70 });
await addr.dagi.lookup({ x: 12.53, y: 55.70 }); // alle inddelinger for punktet

// Postnumre og vejnavne
await addr.postnumre.byNr('2400');
await addr.vejnavne.search({ q: 'sivmosvænget', fuzzy: true });

// Reference-data
await addr.reference.vejstykke('101', '5804');
await addr.reference.jordstykke('330452', '10y');
await addr.reference.jordstykker({ ejerlavkode: '330452' }); // filter påkrævet — se nedenfor
await addr.reference.bebyggelser({ type: 'by', kommunekode: '0101' });

// Geo — DAWA's cirkel- og polygon-filtre
await addr.geo.indenForRadius({ x: 12.55, y: 55.68, radiusM: 500 });
await addr.geo.indenForBbox({ vest: 12.5, syd: 55.6, oest: 12.6, nord: 55.7 });
await addr.geo.naermeste({ x: 12.55, y: 55.68 });

Jordstykker kræver et filter. Et ufiltreret opslag over samtlige matrikler i landet timer ud. Parameteren hedder ejerlavkode uden s — med s ignoreres den, og kaldet bliver ufiltreret.

Trinvis autocomplete

DAWA's autocomplete arbejder i trin. Vælger brugeren et vejnavn-forslag, skal søgningen fortsætte med forslagets tekst — og næste kald skal have startfra: 'adgangsadresse', ellers kommer vejnavnene igen for navne, der findes i mange byer (fx «Strøget»):

const trin1 = await addr.autocomplete({ q: 'Strøget', fuzzy: true });
// → [{ type: 'vejnavn', tekst: 'Strøget ', forslagstekst: 'Strøget', … }, …]

const trin2 = await addr.autocomplete({ q: trin1[0].tekst, startfra: 'adgangsadresse', fuzzy: true });
// → [{ type: 'adgangsadresse', forslagstekst: 'Strøget 1, 7280 Sønder Felding', … }, …]

Vis forslagstekst til brugeren. tekst kan indeholde DAWA's pladsholder for etage og dør ("Rentemestervej 2, , 2400 København NV").

Udvidelser

Det DAWA aldrig har haft, ligger i egne navnerum:

// BBR — bygninger og enheder
await addr.bbr.bygninger.list({ adgangsadresseid: '0a3f5089-b3a7-32b8-e044-0003ba298018' });
await addr.bbr.bygninger.byId('1422c24d-20c0-4bb4-b5ec-1b6d3165db54');

// Flere opslag i én forespørgsel (Pro+) — hver linje/id afregnes som ét kald
await addr.bbr.bygninger.batch(['id1', 'id2']);
await addr.batch.datavask(['Nørrebrogade 1, 2200 København N', 'Strøget 12, 1160 København K']);
await addr.batch.reverse([{ lat: 55.6761, lon: 12.5683 }]);
await addr.batch.dagi([{ lat: 55.6761, lon: 12.5683 }, { postnr: '8000' }]);

// Struktureret validering — siger hvilket felt der er galt
await addr.validate({ vejnavn: 'Nørrebrogade', husnr: '1', postnr: '2200' });

// Afstand mellem to punkter
await addr.geo.distance({ from: { lat: 55.68, lon: 12.55 }, to: { id: '0a3f5089-b3a7-32b8-e044-0003ba298018' } });

// Statistik
await addr.stats.totals();
await addr.stats.kommuner({ limit: 10 });

Streaming-iteratorer

// Iterér ALLE matchende adresser (side/per_side håndteres for dig)
for await (const adresse of addr.adresser.all({ kommunekode: '0101' })) {
  process(adresse);
}

// Replikering — event-stream (kræver Enterprise)
let cursor = 0;
for await (const event of addr.replikering.adresser.iterate({ cursor })) {
  applyEvent(event);
  cursor = event.sekvensnummer; // gem cursor lokalt for resume
}

Webhook-verify

Separat sub-export så React-bundlere ikke fanger Node-crypto:

import { verifyWebhook } from 'danskadresseapi-sdk/webhooks';

export async function POST(req: Request) {
  const raw = await req.text();
  const sig = req.headers.get('x-addr-signature') ?? '';
  if (!verifyWebhook(raw, sig, process.env.WEBHOOK_SECRET!)) {
    return new Response('Invalid signature', { status: 401 });
  }
  // ...behandl event
}

Algoritmen er HMAC-SHA256 over ${unix_t}.${rawBody} med endpoint-secret. Replay-protection: 5 min default tolerance (override via { toleranceSeconds }).

React hooks

import { useAutocomplete } from 'danskadresseapi-sdk/react';
import { Addr } from 'danskadresseapi-sdk';

const addr = new Addr({ apiKey: process.env.NEXT_PUBLIC_ADDR_KEY! });

export function AddressInput() {
  const [q, setQ] = useState('');
  const [efterVejnavn, setEfterVejnavn] = useState(false);
  const { results, loading, error } = useAutocomplete(q, {
    client: addr,
    per_side: 6,
    startfra: efterVejnavn ? 'adgangsadresse' : undefined,
  });

  return (
    <>
      <input value={q} onChange={(e) => { setEfterVejnavn(false); setQ(e.target.value); }} />
      {loading && <span>Søger...</span>}
      {error && <span>{error.message}</span>}
      <ul>
        {results.map((r, i) => (
          <li key={i} onClick={() => {
            if (r.type === 'vejnavn') { setEfterVejnavn(true); setQ(r.tekst); }
          }}>{r.forslagstekst}</li>
        ))}
      </ul>
    </>
  );
}

Konfiguration

new Addr({
  apiKey: 'sk_live_…',
  baseUrl: 'https://api.danskadresseapi.dk',  // default
  timeoutMs: 10_000,                          // default
  retries: 1,                                 // 5xx/netværk auto-retries
  userAgentSuffix: 'my-app/1.0.0',            // tilføjes efter "danskadresseapi-sdk/X.Y.Z"
});

Errors

import { Addr, AddrError } from 'danskadresseapi-sdk';

try {
  await addr.adresser.byId('0a3f50a0-0000-0000-0000-000000000000');
} catch (err) {
  if (err instanceof AddrError) {
    console.log(err.type, err.status, err.requestId, err.details);
    // DAWA-fladen:  'ResourceNotFoundError' | 'ResourcePathFormatError' | 'QueryParameterFormatError' | …
    // Udvidelserne: 'unauthorized' | 'forbidden' | 'rate_limited' | …
    // SDK'et selv:  'koordinater_ombyttet'
  }
}

Opgradering fra v3

v4 skifter adresseopslagene fra /v1 til /dawa. Det er et brud: svarformen er DAWA's, og flere parametre har skiftet navn.

| v3 | v4 | |---|---| | autocomplete({ q, limit }) | autocomplete({ q, per_side, fuzzy }) — trinvis, se ovenfor | | reverse({ lat, lon }) | reverse({ x: lon, y: lat }) | | adresser.search(...) → { count, results } | → rent array; paginér med side/per_side | | datavask() (POST) | datavask() (GET, samme parametre) | | dagi.lookup({ lat, lon }) | dagi.lookup({ x, y }) — adgangsadressens svar har alle inddelinger | | dagi.lookupBatch(points) | batch.dagi(lookups) — v3-kaldet sendte en forkert body og fejlede altid | | geo.indenForRadius({ lat, lon, radiusM }) | geo.indenForRadius({ x, y, radiusM }) | | geo.indenForBbox({ syd, vest, nord, oest }) | uændret navngivning, nu som DAWA-polygon | | geo.naermeste({ lat, lon, limit }) | geo.naermeste({ x, y }) — én adresse | | reference.jordstykker() | reference.jordstykker({ ejerlavkode }) — filter påkrævet | | reference.stormodtagere() | fjernet — findes hverken hos os eller i DAWA | | bbr, stats, validate, geo.distance | uændret (udvidelser) |

Dine eksisterende /v1-kald virker fortsat — API'et er uændret. v4 er kun et skifte i, hvad SDK'et kalder.

License

MIT