@helvaddress/sdk
v0.1.0
Published
Official JavaScript/TypeScript SDK for HelvAddress Swiss address autocomplete API
Maintainers
Readme
@helvaddress/sdk
Official JavaScript/TypeScript SDK for the HelvAddress Swiss address autocomplete API.
Features
- 🏔️ Swiss address autocomplete powered by official GWR/RegBL data
- 🔒 Confidential — queries are sent via POST body, never exposed in URL logs
- 🧩 Decoupled architecture — headless API client + optional UI widget
- 📦 Tree-shakable ESM & CJS builds with full TypeScript types
- 🎨 Customizable UI with built-in styles or bring-your-own CSS
- ⌨️ Full keyboard navigation & accessibility (ARIA)
- 🪶 Zero dependencies — just the native
fetchAPI
Installation
yarn add @helvaddress/sdkQuick Start
Option 1: UI Widget (drop-in autocomplete)
<div id="address-input"></div>import { HelvAddressAutocomplete } from '@helvaddress/sdk';
const widget = new HelvAddressAutocomplete({
apiKey: 'your-jwt-token',
container: '#address-input',
maxSuggestions: 5,
value: 'object',
onSelect: (value, address) => {
console.log('Selected address:', address);
console.log('EGAID:', address.id);
},
});Option 2: Headless Client (for custom UI / Node.js)
import { HelvAddressClient } from '@helvaddress/sdk';
const client = new HelvAddressClient({ apiKey: 'your-jwt-token' });
const results = await client.autocomplete({
query: 'Bahnhofstrasse Zürich',
limit: 5,
});
console.log(results.content);
// [{ id: 100001234, streetName: 'Bahnhofstrasse', houseNumber: '1', zip4: 8001, ... }]Architecture
The SDK is split into two independent layers:
┌─────────────────────────────────────────────┐
│ HelvAddressAutocomplete │ ← UI layer (DOM)
│ (textbox + dropdown + keyboard navigation) │
├─────────────────────────────────────────────┤
│ HelvAddressClient │ ← Core layer (headless)
│ (API calls, auth, error handling) │
└─────────────────────────────────────────────┘HelvAddressClient— Pure API client with zero DOM dependencies. Use it in Node.js, React, Vue, Svelte, or any framework.HelvAddressAutocomplete— Vanilla JS UI widget that uses the client internally. Drop it into any HTML page.
Widget Options
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | required | JWT bearer token |
| container | HTMLElement \| string | required | DOM element or CSS selector |
| value | 'id' \| 'object' \| 'formatted' | 'object' | What onSelect returns |
| maxSuggestions | number (1–20) | 5 | Max dropdown items |
| threshold | number (0–1) | 0.3 | Min relevance score |
| minChars | number | 2 | Min chars before querying |
| debounceMs | number | 250 | Debounce delay (ms) |
| placeholder | string | 'Search Swiss address...' | Input placeholder |
| className | string | — | Extra CSS class on root |
| noStyle | boolean | false | Disable built-in styles |
| entityStatus | 'REAL' \| 'PLANNED' \| 'OUTDATED' | 'REAL' | Address status filter |
| addressCategories | AddressCategory[] | — | Category filter |
| renderSuggestion | (addr) => string | — | Custom suggestion HTML |
| formatValue | (addr) => string | — | Custom input display |
Callbacks
| Callback | Signature | Description |
|---|---|---|
| onSelect | (value, address) => void | User selects an address |
| onResults | (results) => void | New results received |
| onError | (error) => void | API error occurred |
| onChange | (query) => void | Input value changed |
| onFocus | () => void | Input focused |
| onBlur | () => void | Input blurred |
| onOpen | (open) => void | Dropdown opened/closed |
| onClear | () => void | Input cleared |
Widget Methods
widget.setValue('Bahnhofstrasse 1'); // Set input value
widget.getValue(); // Get current value
widget.clear(); // Clear input & close
widget.open(); // Open dropdown
widget.close(); // Close dropdown
widget.focus(); // Focus input
widget.getInputElement(); // Get <input> DOM element
widget.destroy(); // Remove & clean upSelection Value Types
Control what onSelect receives with the value option:
// value: 'id' → returns EGAID number
onSelect: (id: number) => { ... }
// value: 'object' → returns full AddressResult
onSelect: (address: AddressResult) => {
console.log(address.streetName, address.zip4);
}
// value: 'formatted' → returns formatted string
onSelect: (formatted: string) => {
// "Bahnhofstrasse 1, 8001 Zürich"
}Custom Styling
Disable built-in styles and use your own CSS:
const widget = new HelvAddressAutocomplete({
apiKey: 'your-token',
container: '#input',
noStyle: true,
});All elements use BEM-style class names prefixed with ha-autocomplete:
| Class | Element |
|---|---|
| .ha-autocomplete | Root container |
| .ha-autocomplete-input | Text input |
| .ha-autocomplete-dropdown | Dropdown panel |
| .ha-autocomplete-option | Single suggestion |
| .ha-autocomplete-option--active | Highlighted suggestion |
| .ha-autocomplete-clear | Clear button |
| .ha-autocomplete-empty | "No results" message |
| .ha-autocomplete-loading | Loading indicator |
| .ha-autocomplete-error | Error message |
AddressResult Type
interface AddressResult {
id: number; // EGAID (unique building entrance ID)
streetName: string; // Official street name
houseNumber: string; // Building number
zip4: number; // 4-digit postal code (PLZ/NPA)
zipa: number; // Additional postal digits (00–99)
locality: string; // Postal locality name
municipality: string; // Political municipality
score: number; // Relevance score (0.0–1.0)
}Error Handling
import { HelvAddressClient, HelvAddressError } from '@helvaddress/sdk';
try {
const results = await client.autocomplete({ query: 'test' });
} catch (err) {
if (err instanceof HelvAddressError) {
console.error(`API Error ${err.status}: ${err.message}`);
console.error('Details:', err.apiError?.validationErrors);
}
}Browser Support
Works in all modern browsers with native fetch support (Chrome, Firefox, Safari, Edge).
For older browsers, provide a fetch polyfill:
import fetch from 'cross-fetch';
const client = new HelvAddressClient({
apiKey: 'token',
fetch,
});Development
yarn install # Install dependencies
yarn build # Build ESM + CJS
yarn test # Run tests
yarn typecheck # Type checking
yarn dev # Watch modeLicense
MIT © HelvAddress
