mirror of
https://github.com/holidayapi/holidayapi-node.git
synced 2025-06-21 04:26:33 +00:00
Compare commits
22 commits
Author | SHA1 | Date | |
---|---|---|---|
e3a345347e | |||
c3be93e6c4 | |||
4cde62af13 | |||
250fb4b4e9 | |||
5a62ac8b5f | |||
046aadeea4 | |||
c3de7ff9bd | |||
7d37113bd3 | |||
2478cb47c3 | |||
|
0b58b614dc | ||
bbda365fe7 | |||
|
fa2f709f82 | ||
|
7f7d1af247 | ||
|
7b1b47ddc4 | ||
|
5fc9c31883 | ||
3eca80185c | |||
|
b3bbab4e6b | ||
|
790c6c8d02 | ||
2230488d14 | |||
07988d8c71 | |||
2edef851ca | |||
2e44b14a37 |
19 changed files with 5901 additions and 7895 deletions
|
@ -22,23 +22,37 @@
|
|||
"jest"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"vars": "all",
|
||||
"args": "after-used",
|
||||
"ignoreRestSiblings": false
|
||||
}
|
||||
],
|
||||
"import/extensions": [
|
||||
"error",
|
||||
"always",
|
||||
"ignorePackages",
|
||||
{
|
||||
"ts": "never",
|
||||
"tsx": "never"
|
||||
"ts": "never"
|
||||
}
|
||||
],
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": ["**/*.test.ts"]
|
||||
"devDependencies": [
|
||||
"**/*.test.ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"import/prefer-default-export": "off",
|
||||
"lines-between-class-members": "off",
|
||||
"lines-between-class-members": [
|
||||
"error",
|
||||
"always",
|
||||
{
|
||||
"exceptAfterSingleLine": true
|
||||
}
|
||||
],
|
||||
"no-unused-vars": "off"
|
||||
}
|
||||
}
|
||||
|
|
31
.github/workflows/test.yml
vendored
Normal file
31
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
name: Test
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
test:
|
||||
name: Test Node.js ${{ matrix.node-version }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ['18', '20', '22']
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Node.js Version
|
||||
run: node --version
|
||||
- name: NPM Version
|
||||
run: npm --version
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
- name: Run Linter
|
||||
run: npm run lint
|
||||
- name: Run Tests
|
||||
run: npm run test:coverage
|
||||
- name: Upload Coverage
|
||||
if: ${{ matrix.node-version == '20' }}
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
file: ./coverage/lcov.info
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
node_modules
|
||||
npm-debug.log*
|
||||
coverage/
|
||||
|
|
1
.nvmrc
Normal file
1
.nvmrc
Normal file
|
@ -0,0 +1 @@
|
|||
v20
|
|
@ -1,6 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 8
|
||||
- 10
|
||||
- 12
|
||||
- 13
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016, 2017, 2018, 2019, 2020 Gravity Boulevard, LLC
|
||||
Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Gravity Boulevard, LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
57
README.md
57
README.md
|
@ -2,43 +2,12 @@
|
|||
|
||||
[](https://github.com/holidayapi/holidayapi-node/blob/master/LICENSE)
|
||||

|
||||

|
||||
[](https://coveralls.io/github/holidayapi/holidayapi-node?branch=master)
|
||||
[](https://codecov.io/gh/holidayapi/holidayapi-node)
|
||||
|
||||
Official Node.js library for [Holiday API](https://holidayapi.com) providing
|
||||
quick and easy access to holiday information from applications written in
|
||||
server-side JavaScript.
|
||||
|
||||
## Migrating from 2.x
|
||||
|
||||
In an attempt to stay current with both our development and production
|
||||
dependencies, the decision was made to drop testing and advertised compatibility
|
||||
with Node.js versions that are outside of their maintenance window.
|
||||
|
||||
For the 3.x release, testing for Node.js 13.x was added while testing for Node.js
|
||||
7.x, 9.x and 11.x was dropped. Even though these older versions may still
|
||||
continue to work, they become harder to test against as our dependencies improve
|
||||
and drop support for those versions.
|
||||
|
||||
In the future, when compatibility changes, we will increment the major version
|
||||
number of the release as well as document the additions and deprecations in the
|
||||
release notes.
|
||||
|
||||
## Migrating from 1.x
|
||||
|
||||
Please note, version 2.x of this library is a full rewrite of the 1.x series in
|
||||
TypeScript. The interfacing to the library has been simplified and existing
|
||||
applications upgrading to 2.x will need to be updated.
|
||||
|
||||
| Version 1.x Syntax (Old) | Version 2.x Syntax (New) |
|
||||
|---------------------------------------------------|---------------------------------------------------|
|
||||
| `const HolidayAPI = require('node-holidayapi');` | `import { HolidayAPI } from 'holidayapi';` |
|
||||
| `const holidayApi = new HolidayAPI(key).v1;` | `const holidayApi = new HolidayAPI({ key });` |
|
||||
| `holidayApi.holidays(params, (err, data) => {});` | `holidayApi.holidays(params).then((data) => {});` |
|
||||
|
||||
Version 1.x of the library can still be found
|
||||
[here](https://github.com/joshtronic/node-holidayapi).
|
||||
|
||||
## Documentation
|
||||
|
||||
Full documentation of the Holiday API endpoints is available
|
||||
|
@ -269,3 +238,27 @@ holidayApi.holidays({
|
|||
year: 2019,
|
||||
});
|
||||
```
|
||||
|
||||
### Workday
|
||||
|
||||
#### Fetch workday 7 business days after a date
|
||||
|
||||
```javascript
|
||||
holidayApi.workday({
|
||||
country: 'US',
|
||||
start: '2019-07-01',
|
||||
days: 7,
|
||||
});
|
||||
```
|
||||
|
||||
### Workdays
|
||||
|
||||
#### Fetch number of workdays between two dates
|
||||
|
||||
```javascript
|
||||
holidayApi.workday({
|
||||
country: 'US',
|
||||
start: '2019-07-01',
|
||||
end: '2019-07-10',
|
||||
});
|
||||
```
|
||||
|
|
20
codecov.yml
Normal file
20
codecov.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
codecov:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
layout: "reach,diff,flags,tree"
|
||||
behavior: default
|
||||
require_changes: no
|
4
dist/holidayapi.d.ts
vendored
4
dist/holidayapi.d.ts
vendored
|
@ -1,4 +1,4 @@
|
|||
import { CountriesRequest, CountriesResponse, HolidaysResponse, HolidaysRequest, LanguagesRequest, LanguagesResponse } from './types';
|
||||
import { CountriesRequest, CountriesResponse, HolidaysRequest, HolidaysResponse, LanguagesRequest, LanguagesResponse, WorkdayRequest, WorkdayResponse, WorkdaysRequest, WorkdaysResponse } from './types';
|
||||
export declare class HolidayAPI {
|
||||
baseUrl: string;
|
||||
key: string;
|
||||
|
@ -11,4 +11,6 @@ export declare class HolidayAPI {
|
|||
countries(request?: CountriesRequest): Promise<CountriesResponse>;
|
||||
holidays(request?: HolidaysRequest): Promise<HolidaysResponse>;
|
||||
languages(request?: LanguagesRequest): Promise<LanguagesResponse>;
|
||||
workday(request?: WorkdayRequest): Promise<WorkdayResponse>;
|
||||
workdays(request?: WorkdaysRequest): Promise<WorkdaysResponse>;
|
||||
}
|
||||
|
|
40
dist/holidayapi.js
vendored
40
dist/holidayapi.js
vendored
|
@ -25,7 +25,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
|
@ -47,29 +47,29 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HolidayAPI = void 0;
|
||||
var node_fetch_1 = require("node-fetch");
|
||||
var url_1 = require("url");
|
||||
var HolidayAPI = (function () {
|
||||
function HolidayAPI(_a) {
|
||||
var key = _a.key, _b = _a.version, version = _b === void 0 ? 1 : _b;
|
||||
var getYours = 'get yours at HolidayAPI.com';
|
||||
var uuidRegExp = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/;
|
||||
if (!key) {
|
||||
throw new Error("Missing API key, " + getYours);
|
||||
throw new Error("Missing API key, ".concat(getYours));
|
||||
}
|
||||
if (!uuidRegExp.test(key)) {
|
||||
throw new Error("Invalid API key, " + getYours);
|
||||
throw new Error("Invalid API key, ".concat(getYours));
|
||||
}
|
||||
if (version !== 1) {
|
||||
throw new Error('Invalid version number, expected "1"');
|
||||
}
|
||||
this.baseUrl = "https://holidayapi.com/v" + version + "/";
|
||||
this.baseUrl = "https://holidayapi.com/v".concat(version, "/");
|
||||
this.key = key;
|
||||
}
|
||||
HolidayAPI.prototype.createUrl = function (endpoint, request) {
|
||||
var parameters = __assign({ key: this.key }, request);
|
||||
var url = new url_1.URL(endpoint, this.baseUrl);
|
||||
url.search = new url_1.URLSearchParams(parameters).toString();
|
||||
var url = new URL(endpoint, this.baseUrl);
|
||||
url.search = new URLSearchParams(parameters).toString();
|
||||
return url.toString();
|
||||
};
|
||||
HolidayAPI.prototype.request = function (endpoint, request) {
|
||||
|
@ -77,7 +77,7 @@ var HolidayAPI = (function () {
|
|||
var response, payload, err_1;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4, node_fetch_1.default(this.createUrl(endpoint, request))];
|
||||
case 0: return [4, (0, node_fetch_1.default)(this.createUrl(endpoint, request))];
|
||||
case 1:
|
||||
response = _a.sent();
|
||||
_a.label = 2;
|
||||
|
@ -108,18 +108,8 @@ var HolidayAPI = (function () {
|
|||
});
|
||||
};
|
||||
HolidayAPI.prototype.holidays = function (request) {
|
||||
if (request === void 0) { request = {}; }
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
if (!request.country) {
|
||||
throw new Error('Missing country');
|
||||
}
|
||||
else if (!request.year) {
|
||||
throw new Error('Missing year');
|
||||
}
|
||||
else if (request.previous && request.upcoming) {
|
||||
throw new Error('Previous and upcoming are mutually exclusive');
|
||||
}
|
||||
return [2, this.request('holidays', request)];
|
||||
});
|
||||
});
|
||||
|
@ -131,6 +121,20 @@ var HolidayAPI = (function () {
|
|||
});
|
||||
});
|
||||
};
|
||||
HolidayAPI.prototype.workday = function (request) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
return [2, this.request('workday', request)];
|
||||
});
|
||||
});
|
||||
};
|
||||
HolidayAPI.prototype.workdays = function (request) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
return [2, this.request('workdays', request)];
|
||||
});
|
||||
});
|
||||
};
|
||||
return HolidayAPI;
|
||||
}());
|
||||
exports.HolidayAPI = HolidayAPI;
|
||||
|
|
20
dist/index.js
vendored
20
dist/index.js
vendored
|
@ -1,6 +1,18 @@
|
|||
"use strict";
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__export(require("./holidayapi"));
|
||||
__exportStar(require("./types"), exports);
|
||||
__exportStar(require("./holidayapi"), exports);
|
||||
|
|
57
dist/types.d.ts
vendored
57
dist/types.d.ts
vendored
|
@ -1,16 +1,19 @@
|
|||
export declare type Endpoint = 'countries' | 'holidays' | 'languages';
|
||||
declare type Request = {
|
||||
format?: 'csv' | 'json' | 'php' | 'tsv' | 'yaml' | 'xml';
|
||||
export type Endpoint = 'countries' | 'holidays' | 'languages' | 'workday' | 'workdays';
|
||||
export type Weekday = {
|
||||
name: 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' | 'Sunday';
|
||||
numeric: 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
||||
};
|
||||
type Request = {
|
||||
format?: 'csv' | 'json' | 'php' | 'tsv' | 'xml' | 'yaml';
|
||||
key?: string;
|
||||
pretty?: boolean;
|
||||
search?: string;
|
||||
};
|
||||
export declare type Requests = CountriesRequest | HolidaysRequest | LanguagesRequest;
|
||||
export declare type CountriesRequest = Request & {
|
||||
export type CountriesRequest = Request & {
|
||||
country?: string;
|
||||
public?: boolean;
|
||||
};
|
||||
export declare type HolidaysRequest = Request & {
|
||||
export type HolidaysRequest = Request & {
|
||||
country?: string;
|
||||
day?: number;
|
||||
language?: string;
|
||||
|
@ -21,20 +24,29 @@ export declare type HolidaysRequest = Request & {
|
|||
upcoming?: boolean;
|
||||
year?: number;
|
||||
};
|
||||
export declare type LanguagesRequest = Request & {
|
||||
export type LanguagesRequest = Request & {
|
||||
language?: string;
|
||||
};
|
||||
export declare type Response = {
|
||||
export type WorkdayRequest = Request & {
|
||||
country?: string;
|
||||
start?: string;
|
||||
days?: number;
|
||||
};
|
||||
export type WorkdaysRequest = Request & {
|
||||
country?: string;
|
||||
start?: string;
|
||||
end?: string;
|
||||
};
|
||||
export type Response = {
|
||||
requests: {
|
||||
available: number;
|
||||
resets: Date;
|
||||
resets: string;
|
||||
used: number;
|
||||
};
|
||||
status: number;
|
||||
error?: string;
|
||||
};
|
||||
export declare type Responses = (CountriesResponse | HolidaysResponse | LanguagesResponse);
|
||||
export declare type CountriesResponse = Response & {
|
||||
export type CountriesResponse = Response & {
|
||||
countries?: {
|
||||
code: string;
|
||||
codes: {
|
||||
|
@ -50,23 +62,38 @@ export declare type CountriesResponse = Response & {
|
|||
languages: string[];
|
||||
name: string;
|
||||
}[];
|
||||
weekday: {
|
||||
date: Weekday;
|
||||
observed: Weekday;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
export declare type HolidaysResponse = Response & {
|
||||
export type HolidaysResponse = Response & {
|
||||
holidays?: {
|
||||
country: string;
|
||||
date: Date;
|
||||
date: string;
|
||||
name: string;
|
||||
observed: Date;
|
||||
observed: string;
|
||||
public: boolean;
|
||||
uuid: string;
|
||||
subdivisions?: string[];
|
||||
}[];
|
||||
};
|
||||
export declare type LanguagesResponse = Response & {
|
||||
export type LanguagesResponse = Response & {
|
||||
languages?: {
|
||||
code: string;
|
||||
name: string;
|
||||
}[];
|
||||
};
|
||||
export type WorkdayResponse = Response & {
|
||||
workday?: {
|
||||
date: string;
|
||||
weekday: Weekday;
|
||||
};
|
||||
};
|
||||
export type WorkdaysResponse = Response & {
|
||||
workdays?: number;
|
||||
};
|
||||
export type Requests = (CountriesRequest | HolidaysRequest | LanguagesRequest | WorkdayRequest | WorkdaysRequest);
|
||||
export type Responses = (CountriesResponse | HolidaysResponse | LanguagesResponse | WorkdayResponse | WorkdaysResponse);
|
||||
export {};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
};
|
||||
coverageReporters: ['lcov'],
|
||||
};
|
||||
|
|
12942
package-lock.json
generated
12942
package-lock.json
generated
File diff suppressed because it is too large
Load diff
38
package.json
38
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "holidayapi",
|
||||
"version": "3.2.0",
|
||||
"version": "7.1.0",
|
||||
"description": "Official Node.js library for Holiday API",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
@ -21,31 +21,31 @@
|
|||
},
|
||||
"homepage": "https://holidayapi.com",
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
"node": ">= 18.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^25.1.2",
|
||||
"@types/jest": "^29.5.6",
|
||||
"@types/nock": "^11.1.0",
|
||||
"@types/node": "^13.7.1",
|
||||
"@types/node-fetch": "^2.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "^2.19.2",
|
||||
"@typescript-eslint/parser": "^2.19.2",
|
||||
"coveralls": "^3.0.9",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-airbnb-base": "^14.0.0",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
"eslint-plugin-jest": "^23.7.0",
|
||||
"jest": "^25.1.0",
|
||||
"nock": "^12.0.2",
|
||||
"ts-jest": "^25.2.0",
|
||||
"typescript": "^3.7.5"
|
||||
"@types/node": "^22.2.0",
|
||||
"@types/node-fetch": "^2.6.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||
"@typescript-eslint/parser": "^6.9.0",
|
||||
"eslint": "^8.12.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jest": "^27.4.3",
|
||||
"jest": "^29.7.0",
|
||||
"nock": "^13.2.4",
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.0"
|
||||
"node-fetch": "^2.7.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"lint": "eslint --ext .js,.ts src/ tests/",
|
||||
"test": "jest --coverage --coverageReporters=text-lcov | coveralls"
|
||||
"lint": "eslint --ext .js,.ts src tests",
|
||||
"test": "jest",
|
||||
"test:coverage": "jest --coverage"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,20 @@
|
|||
*/
|
||||
|
||||
import fetch from 'node-fetch';
|
||||
import { URL, URLSearchParams } from 'url';
|
||||
import {
|
||||
CountriesRequest, CountriesResponse, Endpoint, HolidaysResponse,
|
||||
HolidaysRequest, LanguagesRequest, LanguagesResponse, Requests, Responses,
|
||||
CountriesRequest,
|
||||
CountriesResponse,
|
||||
Endpoint,
|
||||
HolidaysRequest,
|
||||
HolidaysResponse,
|
||||
LanguagesRequest,
|
||||
LanguagesResponse,
|
||||
Requests,
|
||||
Responses,
|
||||
WorkdayRequest,
|
||||
WorkdayResponse,
|
||||
WorkdaysRequest,
|
||||
WorkdaysResponse,
|
||||
} from './types';
|
||||
|
||||
export class HolidayAPI {
|
||||
|
@ -28,7 +38,6 @@ export class HolidayAPI {
|
|||
throw new Error(`Invalid API key, ${getYours}`);
|
||||
}
|
||||
|
||||
|
||||
if (version !== 1) {
|
||||
throw new Error('Invalid version number, expected "1"');
|
||||
}
|
||||
|
@ -46,7 +55,7 @@ export class HolidayAPI {
|
|||
|
||||
private async request(endpoint: Endpoint, request?: Requests): Promise<Responses> {
|
||||
const response = await fetch(this.createUrl(endpoint, request));
|
||||
let payload;
|
||||
let payload: any;
|
||||
|
||||
try {
|
||||
payload = await response.json();
|
||||
|
@ -65,19 +74,19 @@ export class HolidayAPI {
|
|||
return this.request('countries', request);
|
||||
}
|
||||
|
||||
async holidays(request: HolidaysRequest = {}): Promise<HolidaysResponse> {
|
||||
if (!request.country) {
|
||||
throw new Error('Missing country');
|
||||
} else if (!request.year) {
|
||||
throw new Error('Missing year');
|
||||
} else if (request.previous && request.upcoming) {
|
||||
throw new Error('Previous and upcoming are mutually exclusive');
|
||||
}
|
||||
|
||||
async holidays(request?: HolidaysRequest): Promise<HolidaysResponse> {
|
||||
return this.request('holidays', request);
|
||||
}
|
||||
|
||||
async languages(request?: LanguagesRequest): Promise<LanguagesResponse> {
|
||||
return this.request('languages', request);
|
||||
}
|
||||
|
||||
async workday(request?: WorkdayRequest): Promise<WorkdayResponse> {
|
||||
return this.request('workday', request);
|
||||
}
|
||||
|
||||
async workdays(request?: WorkdaysRequest): Promise<WorkdaysResponse> {
|
||||
return this.request('workdays', request);
|
||||
}
|
||||
}
|
||||
|
|
148
src/types.ts
148
src/types.ts
|
@ -5,86 +5,128 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export type Endpoint = 'countries' | 'holidays' | 'languages';
|
||||
export type Endpoint = 'countries' | 'holidays' | 'languages' | 'workday' | 'workdays';
|
||||
|
||||
type Request = {
|
||||
format?: 'csv' | 'json' | 'php' | 'tsv' | 'yaml' | 'xml',
|
||||
key?: string,
|
||||
pretty?: boolean,
|
||||
search?: string,
|
||||
export type Weekday = {
|
||||
name: 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' | 'Sunday';
|
||||
numeric: 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
||||
};
|
||||
|
||||
export type Requests = CountriesRequest | HolidaysRequest | LanguagesRequest;
|
||||
type Request = {
|
||||
format?: 'csv' | 'json' | 'php' | 'tsv' | 'xml' | 'yaml';
|
||||
key?: string;
|
||||
pretty?: boolean;
|
||||
search?: string;
|
||||
};
|
||||
|
||||
export type CountriesRequest = Request & {
|
||||
country?: string,
|
||||
public?: boolean,
|
||||
country?: string;
|
||||
public?: boolean;
|
||||
};
|
||||
|
||||
export type HolidaysRequest = Request & {
|
||||
country?: string,
|
||||
day?: number,
|
||||
language?: string,
|
||||
month?: number,
|
||||
previous?: boolean,
|
||||
public?: boolean,
|
||||
subdivisions?: boolean,
|
||||
upcoming?: boolean,
|
||||
year?: number,
|
||||
country?: string;
|
||||
day?: number;
|
||||
language?: string;
|
||||
month?: number;
|
||||
previous?: boolean;
|
||||
public?: boolean;
|
||||
subdivisions?: boolean;
|
||||
upcoming?: boolean;
|
||||
year?: number;
|
||||
};
|
||||
|
||||
export type LanguagesRequest = Request & {
|
||||
language?: string,
|
||||
language?: string;
|
||||
};
|
||||
|
||||
export type WorkdayRequest = Request & {
|
||||
country?: string;
|
||||
start?: string;
|
||||
days?: number;
|
||||
};
|
||||
|
||||
export type WorkdaysRequest = Request & {
|
||||
country?: string;
|
||||
start?: string;
|
||||
end?: string;
|
||||
};
|
||||
|
||||
export type Response = {
|
||||
requests: {
|
||||
available: number,
|
||||
resets: Date,
|
||||
used: number,
|
||||
},
|
||||
status: number,
|
||||
error?: string,
|
||||
available: number;
|
||||
resets: string;
|
||||
used: number;
|
||||
};
|
||||
status: number;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
export type Responses = (
|
||||
CountriesResponse | HolidaysResponse | LanguagesResponse
|
||||
);
|
||||
|
||||
export type CountriesResponse = Response & {
|
||||
countries?: {
|
||||
code: string,
|
||||
code: string;
|
||||
codes: {
|
||||
'alpha-2': string,
|
||||
'alpha-3': string,
|
||||
numeric: string,
|
||||
},
|
||||
flag: string,
|
||||
languages: string[],
|
||||
name: string,
|
||||
'alpha-2': string;
|
||||
'alpha-3': string;
|
||||
numeric: string;
|
||||
};
|
||||
flag: string;
|
||||
languages: string[];
|
||||
name: string;
|
||||
subdivisions: {
|
||||
code: string,
|
||||
languages: string[],
|
||||
name: string,
|
||||
}[],
|
||||
}[],
|
||||
code: string;
|
||||
languages: string[];
|
||||
name: string;
|
||||
}[];
|
||||
weekday: {
|
||||
date: Weekday;
|
||||
observed: Weekday;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
export type HolidaysResponse = Response & {
|
||||
holidays?: {
|
||||
country: string,
|
||||
date: Date,
|
||||
name: string,
|
||||
observed: Date,
|
||||
public: boolean,
|
||||
uuid: string,
|
||||
subdivisions?: string[],
|
||||
}[],
|
||||
country: string;
|
||||
date: string;
|
||||
name: string;
|
||||
observed: string;
|
||||
public: boolean;
|
||||
uuid: string;
|
||||
subdivisions?: string[];
|
||||
}[];
|
||||
};
|
||||
|
||||
export type LanguagesResponse = Response & {
|
||||
languages?: {
|
||||
code: string,
|
||||
name: string,
|
||||
}[],
|
||||
code: string;
|
||||
name: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export type WorkdayResponse = Response & {
|
||||
workday?: {
|
||||
date: string;
|
||||
weekday: Weekday;
|
||||
}
|
||||
};
|
||||
|
||||
export type WorkdaysResponse = Response & {
|
||||
workdays?: number;
|
||||
};
|
||||
|
||||
export type Requests = (
|
||||
| CountriesRequest
|
||||
| HolidaysRequest
|
||||
| LanguagesRequest
|
||||
| WorkdayRequest
|
||||
| WorkdaysRequest
|
||||
);
|
||||
|
||||
export type Responses = (
|
||||
| CountriesResponse
|
||||
| HolidaysResponse
|
||||
| LanguagesResponse
|
||||
| WorkdayResponse
|
||||
| WorkdaysResponse
|
||||
);
|
||||
|
|
|
@ -93,129 +93,6 @@ describe('holidayapi', () => {
|
|||
expect(await holidayapi.countries()).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should return only countries with public holidays', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
countries: [
|
||||
{
|
||||
code: 'ST',
|
||||
name: 'Sao Tome and Principe',
|
||||
languages: ['pt'],
|
||||
codes: {
|
||||
'alpha-2': 'ST',
|
||||
'alpha-3': 'STP',
|
||||
numeric: 678,
|
||||
},
|
||||
flag: 'https://www.countryflags.io/ST/flat/64.png',
|
||||
subdivisions: [
|
||||
{
|
||||
code: 'ST-P',
|
||||
name: 'Príncipe',
|
||||
languages: ['pt'],
|
||||
},
|
||||
{
|
||||
code: 'ST-S',
|
||||
name: 'São Tomé',
|
||||
languages: ['pt'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&public=true`).reply(200, expectedResponse);
|
||||
expect(await holidayapi.countries({
|
||||
public: true,
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should return one country', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
countries: [
|
||||
{
|
||||
code: 'ST',
|
||||
name: 'Sao Tome and Principe',
|
||||
languages: ['pt'],
|
||||
codes: {
|
||||
'alpha-2': 'ST',
|
||||
'alpha-3': 'STP',
|
||||
numeric: 678,
|
||||
},
|
||||
flag: 'https://www.countryflags.io/ST/flat/64.png',
|
||||
subdivisions: [
|
||||
{
|
||||
code: 'ST-P',
|
||||
name: 'Príncipe',
|
||||
languages: ['pt'],
|
||||
},
|
||||
{
|
||||
code: 'ST-S',
|
||||
name: 'São Tomé',
|
||||
languages: ['pt'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&country=ST`).reply(200, expectedResponse);
|
||||
expect(await holidayapi.countries({
|
||||
country: 'ST',
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should search countries', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
countries: [
|
||||
{
|
||||
code: 'ST',
|
||||
name: 'Sao Tome and Principe',
|
||||
languages: ['pt'],
|
||||
codes: {
|
||||
'alpha-2': 'ST',
|
||||
'alpha-3': 'STP',
|
||||
numeric: 678,
|
||||
},
|
||||
flag: 'https://www.countryflags.io/ST/flat/64.png',
|
||||
subdivisions: [
|
||||
{
|
||||
code: 'ST-P',
|
||||
name: 'Príncipe',
|
||||
languages: ['pt'],
|
||||
},
|
||||
{
|
||||
code: 'ST-S',
|
||||
name: 'São Tomé',
|
||||
languages: ['pt'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&search=Sao`).reply(200, expectedResponse);
|
||||
expect(await holidayapi.countries({
|
||||
search: 'Sao',
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should raise 4xx errors', async () => {
|
||||
const expectedResponse = {
|
||||
status: 429,
|
||||
|
@ -288,81 +165,6 @@ describe('holidayapi', () => {
|
|||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should search holidays', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
holidays: [
|
||||
{
|
||||
name: 'Independence Day',
|
||||
date: '2015-07-04',
|
||||
observed: '2015-07-03',
|
||||
public: true,
|
||||
country: 'US',
|
||||
uuid: '88268759-9b90-468c-804f-b729b8418e7c',
|
||||
weekday: {
|
||||
date: {
|
||||
name: 'Saturday',
|
||||
numeric: '6',
|
||||
},
|
||||
observed: {
|
||||
name: 'Friday',
|
||||
numeric: '5',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&country=US&year=2019&search=Independence`)
|
||||
.reply(200, expectedResponse);
|
||||
|
||||
expect(await holidayapi.holidays({
|
||||
country: 'US',
|
||||
year: 2019,
|
||||
search: 'Independence',
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should error when country is missing', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
try {
|
||||
await holidayapi.holidays();
|
||||
} catch (err) {
|
||||
expect(err.message).toMatch(/missing country/i);
|
||||
}
|
||||
});
|
||||
|
||||
it('should error when year is missing', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
try {
|
||||
await holidayapi.holidays({ country: 'US' });
|
||||
} catch (err) {
|
||||
expect(err.message).toMatch(/missing year/i);
|
||||
}
|
||||
});
|
||||
|
||||
it('should error when both previous and upcoming', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
try {
|
||||
await holidayapi.holidays({
|
||||
country: 'US',
|
||||
year: 2019,
|
||||
previous: true,
|
||||
upcoming: true,
|
||||
});
|
||||
} catch (err) {
|
||||
expect(err.message).toMatch(/previous and upcoming/i);
|
||||
}
|
||||
});
|
||||
|
||||
it('should raise 4xx errors', async () => {
|
||||
const expectedResponse = {
|
||||
status: 429,
|
||||
|
@ -431,54 +233,6 @@ describe('holidayapi', () => {
|
|||
expect(await holidayapi.languages()).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should return one language', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
languages: [
|
||||
{
|
||||
code: 'hi',
|
||||
name: 'Hindi',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&language=hi`).reply(200, expectedResponse);
|
||||
expect(await holidayapi.languages({
|
||||
language: 'hi',
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should search languages', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
languages: [
|
||||
{
|
||||
code: 'hi',
|
||||
name: 'Hindi',
|
||||
},
|
||||
{
|
||||
code: 'zh',
|
||||
name: 'Chinese (Simplified)',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&search=in`).reply(200, expectedResponse);
|
||||
expect(await holidayapi.languages({
|
||||
search: 'in',
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should raise 4xx errors', async () => {
|
||||
const expectedResponse = {
|
||||
status: 429,
|
||||
|
@ -506,5 +260,119 @@ describe('holidayapi', () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('/v1/workday', () => {
|
||||
const basePath = `/workday?key=${key}`;
|
||||
|
||||
it('should return workday', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
workday: [
|
||||
{
|
||||
date: '2019-07-16',
|
||||
weekday: {
|
||||
name: 'Tuesday',
|
||||
numeric: '2',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&country=US&start=2019-07-01&days=10`)
|
||||
.reply(200, expectedResponse);
|
||||
|
||||
expect(await holidayapi.workday({
|
||||
country: 'US',
|
||||
start: '2019-07-01',
|
||||
days: 10,
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should raise 4xx errors', async () => {
|
||||
const expectedResponse = {
|
||||
status: 429,
|
||||
error: 'Rate limit exceeded',
|
||||
};
|
||||
|
||||
expect.assertions(1);
|
||||
mockRequest.get(`${basePath}&country=US&start=2019-07-01&days=10`)
|
||||
.reply(429, expectedResponse);
|
||||
|
||||
try {
|
||||
await holidayapi.workday({ country: 'US', start: '2019-07-01', days: 10 });
|
||||
} catch (err) {
|
||||
expect(err.message).toMatch(/rate limit exceeded/i);
|
||||
}
|
||||
});
|
||||
|
||||
it('should raise 5xx errors', async () => {
|
||||
expect.assertions(1);
|
||||
mockRequest.get(`${basePath}&country=US&start=2019-07-01&days=10`).reply(500);
|
||||
|
||||
try {
|
||||
await holidayapi.workday({ country: 'US', start: '2019-07-01', days: 10 });
|
||||
} catch (err) {
|
||||
expect(err.message).toMatch(/internal server error/i);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('/v1/workdays', () => {
|
||||
const basePath = `/workdays?key=${key}`;
|
||||
|
||||
it('should return workdays', async () => {
|
||||
const expectedResponse = {
|
||||
status: 200,
|
||||
requests: {
|
||||
used: 1000,
|
||||
available: 9000,
|
||||
resets: '2019-10-01 00:00:00',
|
||||
},
|
||||
workdays: 7,
|
||||
};
|
||||
|
||||
mockRequest.get(`${basePath}&country=US&start=2019-07-01&end=2019-07-10`)
|
||||
.reply(200, expectedResponse);
|
||||
|
||||
expect(await holidayapi.workdays({
|
||||
country: 'US',
|
||||
start: '2019-07-01',
|
||||
end: '2019-07-10',
|
||||
})).toStrictEqual(expectedResponse);
|
||||
});
|
||||
|
||||
it('should raise 4xx errors', async () => {
|
||||
const expectedResponse = {
|
||||
status: 429,
|
||||
error: 'Rate limit exceeded',
|
||||
};
|
||||
|
||||
expect.assertions(1);
|
||||
mockRequest.get(`${basePath}&country=US&start=2019-07-01&end=2019-07-10`)
|
||||
.reply(429, expectedResponse);
|
||||
|
||||
try {
|
||||
await holidayapi.workdays({ country: 'US', start: '2019-07-01', end: '2019-07-10' });
|
||||
} catch (err) {
|
||||
expect(err.message).toMatch(/rate limit exceeded/i);
|
||||
}
|
||||
});
|
||||
|
||||
it('should raise 5xx errors', async () => {
|
||||
expect.assertions(1);
|
||||
mockRequest.get(`${basePath}&country=US&start=2019-07-01&end=2019-07-10`).reply(500);
|
||||
|
||||
try {
|
||||
await holidayapi.workdays({ country: 'US', start: '2019-07-01', end: '2019-07-10' });
|
||||
} catch (err) {
|
||||
expect(err.message).toMatch(/internal server error/i);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
"strict": true,
|
||||
"removeComments": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true
|
||||
"noUnusedParameters": true,
|
||||
"useUnknownInCatchVariables": false
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue