Skip to content

Repository files navigation

@unirate/svelte

Plain Svelte store integration for the UniRate currency exchange API.

createUniRate() gives you reactive readable stores — rate, rates, conversion, currencies, vatRates — each carrying { data, error, loading } with a refresh() method. Works with Svelte 4 and Svelte 5. Zero runtime dependencies (native fetch + svelte/store).

Framework-agnostic: this is the plain-Svelte-stores package. If you're on SvelteKit and want server load helpers, a geo hook, and an API-route proxy, use @unirate/sveltekit instead.

Install

npm install @unirate/svelte svelte

Quick start

# .env — get a free key at https://unirateapi.com
UNIRATE_API_KEY=your-api-key-here
<script>
  import { createUniRate } from '@unirate/svelte';

  const uni = createUniRate({ apiKey: import.meta.env.VITE_UNIRATE_API_KEY });

  const rate = uni.rate('USD', 'EUR');
  const price = uni.conversion('USD', 'EUR', 99.99);
  const codes = uni.currencies();
</script>

{#if $rate.loading}
  Loading…
{:else if $rate.error}
  {$rate.error.message}
{:else}
  <p>1 USD = {$rate.data} EUR</p>
{/if}

<button on:click={rate.refresh}>Refresh</button>

Never ship a real API key to the browser in production. Proxy UniRate through your own backend and point the client's baseUrl at your proxy, or fetch on the server and pass values down.

API

createUniRate(options)

Builds one UniRateClient and returns store constructors bound to it.

const uni = createUniRate({
  apiKey: 'your-key',      // required
  baseUrl?: string,        // default https://api.unirateapi.com
  fetch?: typeof fetch,    // inject a custom fetch (e.g. SvelteKit's load fetch)
  timeoutMs?: number,      // default 30000
  userAgent?: string,
});

Returns:

Member Returns Notes
uni.client UniRateClient The underlying imperative client.
uni.rate(from, to) QueryStore<number> Single exchange rate.
uni.rates(from) QueryStore<Record<string, number>> All rates for from.
uni.conversion(from, to, amount) QueryStore<number> amount of from in to.
uni.currencies() QueryStore<string[]> Supported currency codes.
uni.vatRates() QueryStore<VATRatesAll> All countries.
uni.vatRates(country) QueryStore<VATRateOne> One country (ISO-3166 alpha-2).

QueryStore<T>

A Svelte readable of:

interface QueryState<T> {
  data: T | undefined;      // settled value, or undefined until first success
  error: Error | undefined; // last error, or undefined while healthy
  loading: boolean;         // true until the first request settles; true again during refresh()
}

plus:

store.refresh(); // abort any in-flight request and re-fetch (no-op with no subscribers)

The request fires lazily on the first subscription and is torn down when the last subscriber leaves — the standard Svelte store lifecycle. An in-flight request is aborted whenever refresh() runs again or the store stops, so a stale response can never overwrite a newer one. During a refresh() the previously settled data stays put while loading flips to true.

Imperative client

Everything is also available directly on uni.client (or import UniRateClient and construct it yourself):

import { UniRateClient } from '@unirate/svelte/client';

const client = new UniRateClient({ apiKey: 'your-key' });
const rate = await client.getRate('USD', 'EUR');        // number
const map = await client.getRate('USD');                // Record<string, number>
const eur = await client.convert('EUR', 100, 'USD');    // number
const codes = await client.listCurrencies();            // string[]
const vat = await client.getVatRates('DE');             // { country, vat_data }

Historical/timeseries methods exist for parity but require a UniRate Pro subscription and return 403 (ProRequiredError) on the free tier.

Error handling

Errors are mapped to typed subclasses of UniRateError, surfaced through store.error (or thrown by the client):

HTTP Error
400 InvalidRequestError Invalid request parameters
401 AuthenticationError Missing or invalid API key
403 ProRequiredError Endpoint requires a Pro subscription
404 InvalidCurrencyError Currency not found or no data available
429 RateLimitError Rate limit exceeded
503 / other UniRateError carries .status and .body
network UniRateError wraps the underlying transport error
{#if $rate.error}
  {#if $rate.error.name === 'RateLimitError'}
    Slow down — try again in a moment.
  {:else}
    {$rate.error.message}
  {/if}
{/if}

Building

This package is pure TypeScript stores — there are no .svelte component files to compile — so it builds with plain tsc:

npm run build     # tsc -p tsconfig.build.json → dist/ (ESM + .d.ts)

Related

License

MIT © Unirate Team

About

Svelte store integration for the UniRate currency-exchange API — reactive rate/conversion/currencies/VAT stores. Zero runtime deps.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages