npm package: @jl225vf/exr
Description: Fetches exchange rates from the Norges Bank API and provides clean, developer-friendly data structures.
Author: Julia Lind
Latest version: 4.0.7

# Norges Bank Exchange Rate API Adapter

## About

This package is a school project.  
The package provides tools for fetching exchange rates and for recalculating amounts between different currencies, utilizing the public API provided by Norges Bank (Norway national bank).  

To use the package in your projects install with:  

```bash
npm install @jl225vf/exr   

```


This module provides the classes CurrencyConverter, RateFetcher and QuoteConverter.  Additionally the package also procides the two utility classes: 
- DeepCloner class that makes a deep clone of any object including deep cloning of any nested elements. Note that custom classes are converted to plain objects, and that their private attributes and private methods will not be copied and thus not exist on the new object.
- TypeChecker that checks if a value is of certain type

---------------------

To use the RateFetcher pass an array with currencies you wish to fetch rates for to the method setCurrencies().  The RateFetcher provids the following methods:
- fetchByDate() with optional count parameter that determines the number of observations prior to and including the specified date.  If the date is not a bank date, the rates will be fetched from the nearest bankdate perceeding the specified date.  
- fetchLatest() with optional parameter count that fetches the latest rates  
- fetchByPeriod() that fetches the rates between and including the two specified dates
- getAvailableCurrencies() that returns an array with currency objects containing currency codes and currency names, sorted alphabetically by currency code (id):

 

Example 1:  

Fetch exchange rates on 2023-01-01.

```js
import { RateFetcher } from "@jl225vf/exr"

const fetcher = new RateFetcher()

const currencies = await fetcher.getAvailableCurrencies()
console.log(currencies)
//[
//  { id: 'AUD', name: 'Australian dollar' },
//  { id: 'BDT', name: 'Bangladeshi taka' },
//  { id: 'BGN', name: 'Bulgarian lev' },
//  { id: 'BRL', name: 'Brazilian real' },
//  ...
//  { id: 'ZAR', name: 'South African rand' }
//]


const params = {
    currencies: ["USD", "EUR", "GBP"],
    date: '2023-01-01'
}
const rates = await fetcher.fetchByDate(params)

console.log(rates) // {
                   //    USD: { '2022-12-30': 9.8573 },
                   //    GBP: { '2022-12-30': 11.8541 },
                   //    EUR: { '2022-12-30': 10.5138 }
                   // }

```

Example 2:  

Fetch exchange rates between 2023-01-01 and 2023-01-12.

```js
import { RateFetcher } from "@jl225vf/exr"


const fetcher = new RateFetcher()
const params = {
    currencies: ['EUR', 'SEK']
    from: '2023-01-01',
    to: '2023-01-12'
}
const rates = await fetcher.fetchByPeriod(params)

console.log(rates) // {
                   //   EUR: {
                   //     '2023-01-02': 10.5135,
                   //     '2023-01-03': 10.528,
                   //     '2023-01-04': 10.738,
                   //     '2023-01-05': 10.7248,
                   //     '2023-01-06': 10.807,
                   //     '2023-01-09': 10.6108,
                   //     '2023-01-10': 10.6785,
                   //     '2023-01-11': 10.738,
                   //     '2023-01-12': 10.7228
                   //   },
                   //   SEK: {
                   //     '2023-01-02': 0.9415,
                   //     '2023-01-03': 0.9448,
                   //     '2023-01-04': 0.9617,
                   //     '2023-01-05': 0.9589,
                   //     '2023-01-06': 0.9599,
                   //     '2023-01-09': 0.9477,
                   //     '2023-01-10': 0.9538,
                   //     '2023-01-11': 0.9521,
                   //     '2023-01-12': 0.9512
                   //   }
                   // }

```


  
The CurrencyConverter can be used to covert an amount from any currency to one or more other currencies using the latest available exchange rate.  To use the CurrencyConverter you must first set the fromCurrency using setBaseCurrency() method and the target currencies by passing an array with target currencies to the setTargetCurrencies() method. Then pass the amount you wish to convert to the convert() method. To reset the CurrencyConverter use the clear() method.
  

Example 3:  

Coverting 350 SEK to EUR and PLN.

```js
import { CurrencyConverter } from "@jl225vf/exr"

const converter = new CurrencyCoverter()

converter.setBaseCurrency('SEK')
converter.setTargetCurrencies(['EUR', 'PLN'])

const coverted = await converter.convert(350)

console.log(converted['EUR']) // 31.61561201
console.log(converted['PLN']) // 134.7786382

``` 

The QuoteConverter converts a period of stock quotes from NOK to selected currencies.  
To use the QuoteConverter set the currencies you wish to convert using setTargetCurrencies() method and then pass the quotes object to the convert() method. Quotes must be an object where keys are dates in the format "YYYY-MM-DD" and values are the quotes in NOK.  

Example 4:

```js
import { QuoteConverter } from "@jl225vf/exr"

const converter = new QuoteCoverter()

converter.setTargetCurrencies(['EUR', 'PLN'])

const quotes = {
    "2025-01-10": 332.4,
    "2025-01-09": 334.8,
    "2025-01-08": 332,
    "2025-01-07": 334.8,
    "2025-01-06": 331,
    "2025-01-03": 332,
    "2025-01-02": 334.4
}

const coverted = await converter.convert(quotes)

console.log(converted) // {
                       //   '2025-01-10': { NOK: 332.4, EUR: 28.27, PLN: 120.61 },
                       //   '2025-01-09': { NOK: 334.8, EUR: 28.47, PLN: 121.63 },
                       //   '2025-01-08': { NOK: 332, EUR: 28.28, PLN: 120.96 },
                       //   '2025-01-07': { NOK: 334.8, EUR: 28.52, PLN: 121.45 },
                       //   '2025-01-06': { NOK: 331, EUR: 28.27, PLN: 120.19 },
                       //   '2025-01-03': { NOK: 332, EUR: 28.34, PLN: 121.1 },
                       //   '2025-01-02': { NOK: 334.4, EUR: 28.54, PLN: 122.01 }
                       // }


``` 

Example 5:  

```js
import { Cloner } from "@jl225vf/exr"

const cloner = new Cloner()

const original = {
    someNr: 5,
    someObj: {
        someOtherNr: 4,
        anArr: [5, 6, 8]
    },
    name: 'Original'
}

const copy = cloner.deepClone(original)
console.log(original === copy) // false
console.log(original.someObj === copy.someObj) // false
console.log(original.someObj.anArr === original.someObj.anArr) // false
console.log(original.someNr === copy.someNr) // true
console.log(original.someObj.anArr[1] === original.someObj.anArr[1]) // true
```

## Testing

Current code has 100% coverage, latest test report available under https://github.com/JuliaLind/1DV610-L2/actions/workflows/ci.yml .  

## Contribute  

1. **Fork** this repository to your GitHub account.
2. **Clone your fork** (replace `<your-username>`):

```bash
git clone git@github.com:<your-username>/1DV610-L2.git
cd 1DV610-L2
```
3. **Install**
```bash
npm install
```

4. **Create a branch**

```bash
git checkout -b feat/short-description
```

5. **Test and lint**

Make sure to fix any linting errors. Please add/adjust tests for any change you make to the code.

6. **Opening a Pull Request**

Push your branch:

```bash
git push -u origin <branch-name>
```
  
Open a PR against main and include:  
  
What problem it solves / why the change is needed.  
  
What changed (before/after, screenshots if relevant).  
  
How to test (commands, sample input/output).  
  
**PR checklist**  
  
1. Tests pass (npm test)  

2. Lint passes (npm run lint)

3. README/docs updated if behavior or API changed