Skip to content

Commit c6a3f9a

Browse files
committed
Re-organize the codes
1 parent 123117f commit c6a3f9a

14 files changed

Lines changed: 169 additions & 134 deletions

.mocharc.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
extension: ['ts', 'tsx'] # add tsx if you use react
22
spec: 'src/**/*.spec.ts'
33
require: 'ts-node/register'
4-
timeout: '3000'
5-
file:
6-
- 'src/pretest.ts'
4+
timeout: '3000'

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,20 @@ This is a Node.js library for [Dan](https://dan.com/) api.
66

77
```bash
88
npm install dan-api
9+
```
10+
11+
## Usage
12+
13+
```js
14+
const DanApi = require('dan-api');
15+
16+
const api = new DanApi({
17+
token: 'YOUR_TOKEN',
18+
timeout: 10000,
19+
sandbox: false,
20+
});
21+
22+
(async () => {
23+
console.log(await api.dp.search('dan'));
24+
})();
925
```

src/api/dp.spec.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/api/dp.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { request } from "../endpoint";
1+
import DanApi from "../constructor";
22

33
type BuyAmount = {
44
value: number;
@@ -39,7 +39,11 @@ type Domain = {
3939
}
4040

4141
// Search distribution network for domain
42-
export async function search(query: string) {
43-
const { results } = await request('/dp/demand/domains', 'GET', { query });
44-
return results as Domain[];
42+
export function dp(api: DanApi) {
43+
async function search(query: string) {
44+
const { results } = await api.endpoint.request('/dp/demand/domains', 'GET', { query });
45+
return results as Domain[];
46+
}
47+
48+
return { search };
4549
}

src/auth.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import axios from "axios";
2+
import DanApi from "./constructor";
3+
4+
type TokenResponse = {
5+
token: string;
6+
expires_at: number;
7+
};
8+
9+
export function auth(api: DanApi) {
10+
const tokenCache: Partial<TokenResponse> = {};
11+
12+
// Request a dan auth token, store it in cache
13+
// If the token is expired, request a new one
14+
async function token(): Promise<string> {
15+
if (tokenCache.token && tokenCache.expires_at && tokenCache.expires_at > Date.now()) {
16+
return tokenCache.token;
17+
}
18+
19+
const response = await axios.post(
20+
api.endpoint.url('/tokens'),
21+
{
22+
integrator_token: api.getIntegratorToken()
23+
},
24+
{
25+
timeout: api.getTimeOut(),
26+
}
27+
);
28+
29+
if (response.status !== 200) {
30+
throw new Error('Token error');
31+
}
32+
33+
const data: TokenResponse = response.data;
34+
35+
tokenCache.token = data.token;
36+
tokenCache.expires_at = data.expires_at;
37+
38+
return data.token;
39+
}
40+
41+
return { token };
42+
}

src/constructor.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { dp } from "./api/dp";
2+
import { auth } from "./auth";
3+
import { endpoint } from "./endpoint";
4+
5+
// Configuration for dan api
6+
export type DanConfig = {
7+
token?: string;
8+
sandbox: boolean;
9+
timeout?: number;
10+
};
11+
12+
// Dan api constructor
13+
export default class DanApi {
14+
private integratorToken: string;
15+
private sandbox: boolean;
16+
private timeout: number;
17+
18+
public endpoint: ReturnType<typeof endpoint>;
19+
public auth: ReturnType<typeof auth>;
20+
public dp: ReturnType<typeof dp>;
21+
22+
// Set the configuration
23+
constructor(config: DanConfig) {
24+
this.integratorToken = config.token || '';
25+
this.sandbox = config.sandbox;
26+
this.timeout = config.timeout || 3000;
27+
28+
this.endpoint = endpoint(this);
29+
this.auth = auth(this);
30+
this.dp = dp(this);
31+
}
32+
33+
// Get integrator token
34+
getIntegratorToken(): string {
35+
if (!this.integratorToken) {
36+
throw new Error('Integrator token not set');
37+
}
38+
39+
return this.integratorToken;
40+
}
41+
42+
// Get sandbox mode
43+
isSandbox(): boolean {
44+
return this.sandbox;
45+
}
46+
47+
// Get timeout
48+
getTimeOut(): number {
49+
return this.timeout;
50+
}
51+
}

src/endpoint.spec.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/endpoint.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
11
import axios, { Method } from "axios";
2-
import { getAuthToken } from "./token";
3-
import { getTimeOut, isSandbox } from "./init";
2+
import DanApi from "./constructor";
43

54
const endpoints = {
65
sandbox: 'https://sandbox.dan.com/api/integrator/v1',
76
production: 'https://dan.com/api/integrator/v1'
87
};
98

10-
// Get the url of the endpoint
11-
export function endpointUrl(path: string): string {
12-
return `${endpoints[isSandbox() ? 'sandbox' : 'production']}${path}`;
13-
}
9+
export function endpoint(api: DanApi) {
10+
// Get the url of the endpoint
11+
function url(path: string): string {
12+
return `${endpoints[api.isSandbox() ? 'sandbox' : 'production']}${path}`;
13+
}
14+
15+
// Request the endpoint
16+
async function request(path: string, method: Method, data?: any) {
17+
const response = await axios({
18+
method,
19+
url: url(path),
20+
data,
21+
timeout: api.getTimeOut(),
22+
headers: {
23+
Authorization: 'Bearer ' + (await api.auth.token())
24+
}
25+
});
1426

15-
// Request the endpoint
16-
export async function request(path: string, method: Method, data?: any) {
17-
const response = await axios({
18-
method,
19-
url: endpointUrl(path),
20-
data,
21-
timeout: getTimeOut(),
22-
headers: {
23-
Authorization: 'Bearer ' + (await getAuthToken())
27+
if (response.status !== 200) {
28+
throw new Error('Endpoint error');
2429
}
25-
});
2630

27-
if (response.status !== 200) {
28-
throw new Error('Endpoint error');
31+
return response.data;
2932
}
3033

31-
return response.data;
34+
return { url, request };
3235
}

src/index.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import DanApi from ".";
2+
import assert from "assert";
3+
import { describe } from "mocha";
4+
5+
const api = new DanApi({
6+
token: process.env.TOKEN,
7+
sandbox: true,
8+
});
9+
10+
describe("Endpoint", () => {
11+
it("should return the correct url", () => {
12+
assert.strictEqual(api.endpoint.url("/test"), "https://sandbox.dan.com/api/integrator/v1/test");
13+
});
14+
});
15+
16+
describe("Token", () => {
17+
it("should return the correct token", async () => {
18+
await api.auth.token();
19+
});
20+
});
21+
22+
describe("Distribution Network, Domains", () => {
23+
it("should return the correct domain", async () => {
24+
const domains = await api.dp.search("dan");
25+
assert.ok(domains.length > 0, 'No domains found');
26+
});
27+
});

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export { init as initDan } from './init'
1+
import DanApi from './constructor';
2+
export default DanApi;

0 commit comments

Comments
 (0)