theauthapi 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +15 -0
- package/.prettierrc.json +1 -0
- package/jest.config.js +5 -0
- package/jest.setup.ts +0 -0
- package/package.json +34 -29
- package/src/endpoints/ApiKeys/ApiKeys.ts +68 -0
- package/src/endpoints/ApiKeys/ApiKeysInterface.ts +11 -0
- package/src/endpoints/Projects/Projects.ts +62 -0
- package/src/endpoints/Projects/ProjectsInterface.ts +9 -0
- package/src/index.ts +103 -0
- package/src/libraryMeta.ts +1 -0
- package/src/services/ApiRequest/ApiCall.ts +7 -0
- package/src/services/ApiRequest/ApiRequest.ts +132 -0
- package/src/services/ApiRequest/ApiRequestError.ts +7 -0
- package/src/services/ApiRequest/HttpMethod.ts +7 -0
- package/src/tests/endpoints/apiKeys.spec.ts +102 -0
- package/src/tests/endpoints/projects.spec.ts +105 -0
- package/src/tests/index.spec.ts +35 -0
- package/src/tests/testServer/middleware/middleware.ts +17 -0
- package/src/tests/testServer/routes/apiKeys.ts +89 -0
- package/src/tests/testServer/routes/auth.ts +24 -0
- package/src/tests/testServer/routes/projects.ts +87 -0
- package/src/tests/testServer/server.ts +16 -0
- package/src/types/index.ts +59 -0
- package/src/util/index.ts +7 -0
- package/tsconfig.json +102 -0
- package/index.js +0 -182
- package/test.js +0 -113
package/.eslintrc.js
ADDED
package/.prettierrc.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/jest.config.js
ADDED
package/jest.setup.ts
ADDED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theauthapi",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Client library for TheAuthAPI.com",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"test": "standard && nyc ava",
|
|
11
|
-
"report-coverage": "nyc report --reporter=lcov > coverage.lcov && codecov",
|
|
8
|
+
"test": "jest --runInBand",
|
|
9
|
+
"test:coverage": "jest --coverage --runInBand",
|
|
12
10
|
"np": "np --no-publish",
|
|
13
11
|
"release": "yarn run np",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"test-mocha": "ava mocha"
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"prepublish": "npm run build"
|
|
17
14
|
},
|
|
18
15
|
"repository": {
|
|
19
16
|
"type": "git",
|
|
@@ -29,31 +26,39 @@
|
|
|
29
26
|
"assert": "^2.0.0",
|
|
30
27
|
"axios": "^0.21.4",
|
|
31
28
|
"axios-retry": "^3.1.9",
|
|
32
|
-
"core-js": "^3.17.3",
|
|
33
29
|
"lodash.isstring": "^4.0.1",
|
|
30
|
+
"lodash.omit": "^4.5.0",
|
|
34
31
|
"ms": "^2.1.3",
|
|
35
|
-
"node-cache": "^5.1.2",
|
|
36
|
-
"regenerator-runtime": "^0.13.9",
|
|
37
32
|
"remove-trailing-slash": "^0.1.1"
|
|
38
33
|
},
|
|
39
34
|
"devDependencies": {
|
|
40
|
-
"
|
|
41
|
-
"basic-auth": "^
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
35
|
+
"@size-limit/preset-small-lib": "^7.0.8",
|
|
36
|
+
"@types/basic-auth": "^1.1.3",
|
|
37
|
+
"@types/express": "^4.17.13",
|
|
38
|
+
"@types/jest": "^27.4.1",
|
|
39
|
+
"@types/lodash.isstring": "^4.0.6",
|
|
40
|
+
"@types/lodash.omit": "^4.5.6",
|
|
41
|
+
"@types/ms": "^0.7.31",
|
|
42
|
+
"@types/node": "^17.0.23",
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
|
44
|
+
"@typescript-eslint/parser": "^5.17.0",
|
|
45
|
+
"body-parser": "^1.20.0",
|
|
46
|
+
"eslint": "^7.14.0",
|
|
47
|
+
"eslint-config-prettier": "^8.5.0",
|
|
47
48
|
"express": "^4.15.2",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"nyc": "^14.1.1",
|
|
51
|
-
"pify": "^4.0.1",
|
|
52
|
-
"sinon": "^7.3.2",
|
|
53
|
-
"sinon-chai": "^3.7.0",
|
|
49
|
+
"jest": "^27.5.1",
|
|
50
|
+
"prettier": "2.6.2",
|
|
54
51
|
"size-limit": "^4.11.0",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
52
|
+
"ts-jest": "^27.1.4",
|
|
53
|
+
"ts-node": "^10.7.0",
|
|
54
|
+
"typescript": "^4.6.3"
|
|
55
|
+
},
|
|
56
|
+
"ava": {
|
|
57
|
+
"extensions": [
|
|
58
|
+
"ts"
|
|
59
|
+
],
|
|
60
|
+
"require": [
|
|
61
|
+
"ts-node/register"
|
|
62
|
+
]
|
|
58
63
|
}
|
|
59
64
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { HttpMethod } from "../../services/ApiRequest/HttpMethod";
|
|
2
|
+
import omit from "lodash.omit";
|
|
3
|
+
import ApiRequest from "../../services/ApiRequest/ApiRequest";
|
|
4
|
+
import {ApiKey, ApiKeyInput, UpdateApiKeyInput} from "../../types";
|
|
5
|
+
import { validateString } from "../../util";
|
|
6
|
+
import ApiKeysInterface from "./ApiKeysInterface";
|
|
7
|
+
|
|
8
|
+
class ApiKeys implements ApiKeysInterface {
|
|
9
|
+
api: ApiRequest;
|
|
10
|
+
|
|
11
|
+
constructor(apiService: ApiRequest) {
|
|
12
|
+
this.api = apiService;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async authenticateKey(apikey: string) {
|
|
16
|
+
validateString("apikey", apikey);
|
|
17
|
+
return await this.api.request<ApiKey>(
|
|
18
|
+
HttpMethod.GET,
|
|
19
|
+
`/api-keys/${apikey}`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async getKeys(projectId: string) {
|
|
24
|
+
validateString("projectId", projectId);
|
|
25
|
+
return await this.api.request<ApiKey[]>(
|
|
26
|
+
HttpMethod.GET,
|
|
27
|
+
`/api-keys/?projectId=${projectId}`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async createKey(apiKey: ApiKeyInput) {
|
|
32
|
+
// validate string properties only
|
|
33
|
+
for (const [key, value] of Object.entries(
|
|
34
|
+
omit(apiKey, ["customMetaData", "rateLimitConfigs"])
|
|
35
|
+
)) {
|
|
36
|
+
validateString(key, value);
|
|
37
|
+
}
|
|
38
|
+
return await this.api.request<ApiKey>(
|
|
39
|
+
HttpMethod.POST,
|
|
40
|
+
"/api-keys",
|
|
41
|
+
apiKey
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async updateKey(apiKey: string, updateTo: UpdateApiKeyInput) {
|
|
46
|
+
validateString("apiKey", apiKey);
|
|
47
|
+
for (const [key, value] of Object.entries(
|
|
48
|
+
omit(updateTo, "customMetaData")
|
|
49
|
+
)) {
|
|
50
|
+
validateString(key, value);
|
|
51
|
+
}
|
|
52
|
+
return await this.api.request<ApiKey>(
|
|
53
|
+
HttpMethod.PATCH,
|
|
54
|
+
`/api-keys/${apiKey}`,
|
|
55
|
+
updateTo
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async deleteKey(apiKey: string) {
|
|
60
|
+
validateString("apiKey", apiKey);
|
|
61
|
+
return await this.api.request<boolean>(
|
|
62
|
+
HttpMethod.DELETE,
|
|
63
|
+
`/api-keys/${apiKey}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export = ApiKeys;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ApiKey, ApiKeyInput, UpdateApiKeyInput } from "../../types";
|
|
2
|
+
|
|
3
|
+
interface ApiKeysInterface {
|
|
4
|
+
authenticateKey(apiKey: string): Promise<ApiKey>;
|
|
5
|
+
getKeys(projectId: string): Promise<ApiKey[]>;
|
|
6
|
+
createKey(apiKey: ApiKeyInput): Promise<ApiKey>;
|
|
7
|
+
updateKey(apiKey: string, updateTo: UpdateApiKeyInput): Promise<ApiKey>;
|
|
8
|
+
deleteKey(apiKey: string): Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export = ApiKeysInterface;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import ApiRequest from "../../services/ApiRequest/ApiRequest";
|
|
2
|
+
import { Project, UpdateProjectInput } from "../../types";
|
|
3
|
+
import { HttpMethod } from "../../services/ApiRequest/HttpMethod";
|
|
4
|
+
import { validateString } from "../../util";
|
|
5
|
+
import { ProjectsInterface } from "./ProjectsInterface";
|
|
6
|
+
|
|
7
|
+
class Projects implements ProjectsInterface {
|
|
8
|
+
api: ApiRequest;
|
|
9
|
+
endpoint: string;
|
|
10
|
+
|
|
11
|
+
constructor(apiService: ApiRequest) {
|
|
12
|
+
this.api = apiService;
|
|
13
|
+
this.endpoint = "/projects";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async getProjects(accountId: string): Promise<Project[]> {
|
|
17
|
+
validateString("accountId", accountId);
|
|
18
|
+
return await this.api.request<Project[]>(
|
|
19
|
+
HttpMethod.GET,
|
|
20
|
+
`${this.endpoint}?accountId=${accountId}`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async getProject(projectId: string): Promise<Project> {
|
|
25
|
+
validateString("projectId", projectId);
|
|
26
|
+
return await this.api.request<Project>(
|
|
27
|
+
HttpMethod.GET,
|
|
28
|
+
`${this.endpoint}/${projectId}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async deleteProject(projectId: string): Promise<boolean> {
|
|
33
|
+
validateString("projectId", projectId);
|
|
34
|
+
return await this.api.request<boolean>(
|
|
35
|
+
HttpMethod.DELETE,
|
|
36
|
+
`${this.endpoint}/${projectId}`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async createProject(name: string, accountId: string): Promise<Project> {
|
|
41
|
+
validateString("name", name);
|
|
42
|
+
validateString("accountId", accountId);
|
|
43
|
+
return await this.api.request<Project>(HttpMethod.POST, this.endpoint, {
|
|
44
|
+
name,
|
|
45
|
+
accountId,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async updateProject(
|
|
50
|
+
projectId: string,
|
|
51
|
+
updateTo: UpdateProjectInput
|
|
52
|
+
): Promise<Project> {
|
|
53
|
+
validateString("projectId", projectId);
|
|
54
|
+
return this.api.request<Project>(
|
|
55
|
+
HttpMethod.PATCH,
|
|
56
|
+
`${this.endpoint}/${projectId}`,
|
|
57
|
+
updateTo
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default Projects;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {Project, UpdateProjectInput} from "../../types";
|
|
2
|
+
|
|
3
|
+
export interface ProjectsInterface {
|
|
4
|
+
getProjects(accountId: string): Promise<Project[]>;
|
|
5
|
+
getProject(projectId: string): Promise<Project>;
|
|
6
|
+
deleteProject(projectId: string): Promise<boolean>;
|
|
7
|
+
createProject(name: string, accountId: string): Promise<Project>;
|
|
8
|
+
updateProject(name: string, updateTo: UpdateProjectInput): Promise<Project>;
|
|
9
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import removeSlash from "remove-trailing-slash";
|
|
3
|
+
|
|
4
|
+
import ApiRequest from "./services/ApiRequest/ApiRequest";
|
|
5
|
+
import { validateString } from "./util";
|
|
6
|
+
import ApiKeys from "./endpoints/ApiKeys/ApiKeys";
|
|
7
|
+
import { HttpMethod } from "./services/ApiRequest/HttpMethod";
|
|
8
|
+
import Projects from "./endpoints/Projects/Projects";
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
11
|
+
const noop = () => {};
|
|
12
|
+
|
|
13
|
+
type Options = {
|
|
14
|
+
host?: string;
|
|
15
|
+
timeout?: string | number;
|
|
16
|
+
cacheTTL?: number;
|
|
17
|
+
enable?: boolean;
|
|
18
|
+
retryCount?: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
class TheAuthAPI {
|
|
22
|
+
queue: [];
|
|
23
|
+
accessKey: string;
|
|
24
|
+
host: string;
|
|
25
|
+
timeout: number | string | undefined;
|
|
26
|
+
cacheTTL: number;
|
|
27
|
+
api: ApiRequest;
|
|
28
|
+
apiKeys: ApiKeys;
|
|
29
|
+
projects: Projects;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Initialize a new `Analytics` with your Segment project's `writeKey` and an
|
|
33
|
+
* optional dictionary of `options`.
|
|
34
|
+
*
|
|
35
|
+
* @param {String} accessKey
|
|
36
|
+
* @param {Object} [options] (optional)
|
|
37
|
+
* @property {Number} flushAt (default: 20)
|
|
38
|
+
* @property {Number} flushInterval (default: 10000)
|
|
39
|
+
* @property {String} host (default: 'https://api.segment.io')
|
|
40
|
+
* @property {Boolean} enable (default: true)
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
constructor(accessKey: string, options?: Options) {
|
|
44
|
+
assert(accessKey, "You must pass your project's write key.");
|
|
45
|
+
this.queue = [];
|
|
46
|
+
this.accessKey = accessKey;
|
|
47
|
+
this.host = removeSlash(options?.host || "https://api.theauthapi.com");
|
|
48
|
+
this.timeout = options?.timeout;
|
|
49
|
+
this.cacheTTL = options?.cacheTTL ?? 60;
|
|
50
|
+
this.api = new ApiRequest({
|
|
51
|
+
accessKey: this.accessKey,
|
|
52
|
+
host: this.host,
|
|
53
|
+
});
|
|
54
|
+
this.apiKeys = new ApiKeys(this.api);
|
|
55
|
+
this.projects = new Projects(this.api);
|
|
56
|
+
|
|
57
|
+
Object.defineProperty(this, "enable", {
|
|
58
|
+
configurable: false,
|
|
59
|
+
writable: false,
|
|
60
|
+
enumerable: true,
|
|
61
|
+
value: typeof options?.enable === "boolean" ? options.enable : true,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
@deprecated
|
|
67
|
+
*/
|
|
68
|
+
async authenticateAPIKey(
|
|
69
|
+
key: string,
|
|
70
|
+
callback?: (err: any, data: any) => any
|
|
71
|
+
) {
|
|
72
|
+
validateString("key", key);
|
|
73
|
+
|
|
74
|
+
const cb = callback || noop;
|
|
75
|
+
const done = (err: any) => {
|
|
76
|
+
cb(err, data);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const data = {
|
|
80
|
+
credentials: { api_key: key },
|
|
81
|
+
timestamp: new Date().getTime(),
|
|
82
|
+
sentAt: new Date().getTime(),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const key = await this.api.request(
|
|
87
|
+
HttpMethod.POST,
|
|
88
|
+
"/auth/authenticate",
|
|
89
|
+
data
|
|
90
|
+
);
|
|
91
|
+
done(key);
|
|
92
|
+
return key;
|
|
93
|
+
} catch (err: any) {
|
|
94
|
+
if (err.response) {
|
|
95
|
+
const error = new Error(err.response.statusText);
|
|
96
|
+
return done(error);
|
|
97
|
+
}
|
|
98
|
+
done(err);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default TheAuthAPI;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const version = "1.0.1";
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { version } from "../../libraryMeta";
|
|
3
|
+
import { HttpMethod } from "./HttpMethod";
|
|
4
|
+
import ApiCall from "./ApiCall";
|
|
5
|
+
import ApiRequestError from "./ApiRequestError";
|
|
6
|
+
import axiosRetry from "axios-retry";
|
|
7
|
+
import ms from "ms";
|
|
8
|
+
|
|
9
|
+
type Config = {
|
|
10
|
+
host: string;
|
|
11
|
+
accessKey: string;
|
|
12
|
+
headers?: object;
|
|
13
|
+
retryCount?: number;
|
|
14
|
+
timeout?: number | string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
class ApiRequest implements ApiCall {
|
|
18
|
+
host: string;
|
|
19
|
+
headers: object;
|
|
20
|
+
accessKey: string;
|
|
21
|
+
timeout: number;
|
|
22
|
+
retryCount: number;
|
|
23
|
+
|
|
24
|
+
constructor(config: Config) {
|
|
25
|
+
const { host, accessKey, headers, retryCount, timeout } = config;
|
|
26
|
+
this.host = host;
|
|
27
|
+
this.accessKey = accessKey;
|
|
28
|
+
this.headers = this._generateDefaultHeaders();
|
|
29
|
+
this.timeout = timeout ? (typeof timeout === "string" ? ms(timeout) : timeout) : 0;
|
|
30
|
+
this.retryCount = retryCount ?? 3;
|
|
31
|
+
|
|
32
|
+
if (headers) {
|
|
33
|
+
this.headers = { ...this.headers, headers };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this._init();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_init() {
|
|
40
|
+
const isoDateFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d*)?(?:[-+]\d{2}:?\d{2}|Z)?$/
|
|
41
|
+
function isIsoDateString(value: any): boolean {
|
|
42
|
+
return value && typeof value === "string" && isoDateFormat.test(value);
|
|
43
|
+
}
|
|
44
|
+
function handleDates(body: any) {
|
|
45
|
+
if (body === null || body === undefined || typeof body !== "object"){
|
|
46
|
+
return body;
|
|
47
|
+
}
|
|
48
|
+
for (const key of Object.keys(body)) {
|
|
49
|
+
const value = body[key];
|
|
50
|
+
if (isIsoDateString(value)) {
|
|
51
|
+
body[key] = new Date(value);
|
|
52
|
+
} else if (typeof value === "object") {
|
|
53
|
+
handleDates(value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
axios.interceptors.response.use((response) => {
|
|
59
|
+
handleDates(response.data);
|
|
60
|
+
return response;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
axiosRetry(axios, {
|
|
64
|
+
retries: this.retryCount ?? 3,
|
|
65
|
+
retryCondition: this._isErrorRetryable,
|
|
66
|
+
retryDelay: axiosRetry.exponentialDelay,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async request<T>(
|
|
71
|
+
method: HttpMethod,
|
|
72
|
+
endpoint: string,
|
|
73
|
+
payload?: any
|
|
74
|
+
): Promise<T> {
|
|
75
|
+
try {
|
|
76
|
+
const response = await axios.request<T>({
|
|
77
|
+
baseURL: this.host,
|
|
78
|
+
method: method,
|
|
79
|
+
url: endpoint,
|
|
80
|
+
data: payload,
|
|
81
|
+
headers: this.headers,
|
|
82
|
+
});
|
|
83
|
+
return response.data;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (axios.isAxiosError(error)) {
|
|
86
|
+
if (error.response) {
|
|
87
|
+
throw new ApiRequestError(
|
|
88
|
+
error.response.status,
|
|
89
|
+
error.response.data.message ?? error.response.statusText
|
|
90
|
+
);
|
|
91
|
+
} else if (error.request) {
|
|
92
|
+
throw new Error(error.request);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_generateDefaultHeaders() {
|
|
100
|
+
return {
|
|
101
|
+
"user-agent": `theauthapi-client-node/${version}`,
|
|
102
|
+
"x-api-key": this.accessKey,
|
|
103
|
+
"api-key": this.accessKey,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
_isErrorRetryable(error: any) {
|
|
108
|
+
// Retry Network Errors.
|
|
109
|
+
if (axiosRetry.isNetworkError(error)) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!error.response) {
|
|
114
|
+
// Cannot determine if the request can be retried
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Retry Server Errors (5xx).
|
|
119
|
+
if (error.response.status >= 500 && error.response.status <= 599) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Retry if rate limited.
|
|
124
|
+
if (error.response.status === 429) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export default ApiRequest;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import TheAuthAPI from "../../index";
|
|
2
|
+
import testServer from "../testServer/server";
|
|
3
|
+
import { Server } from "http";
|
|
4
|
+
|
|
5
|
+
const port = 4063;
|
|
6
|
+
|
|
7
|
+
const createClient = (options?: any) => {
|
|
8
|
+
options = Object.assign(
|
|
9
|
+
{
|
|
10
|
+
host: `http://localhost:${port}`,
|
|
11
|
+
},
|
|
12
|
+
options
|
|
13
|
+
);
|
|
14
|
+
return new TheAuthAPI("access_key", options);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe("ApiKeys", () => {
|
|
18
|
+
let server: Server;
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
server = testServer.listen(port);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterAll(() => {
|
|
24
|
+
server.close();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should authenticate a valid api-key", async () => {
|
|
28
|
+
const client = createClient();
|
|
29
|
+
const data = await client.apiKeys.authenticateKey(
|
|
30
|
+
"live_access_zBA6cvuEbJEUhhDIWwuErXHLnwvWqtcqe2ajfV3RVVZvD6lc6xDUaSsSZL1fk53a"
|
|
31
|
+
);
|
|
32
|
+
console.log('day', data.createdAt.getDate(), 'month', data.createdAt.getMonth())
|
|
33
|
+
expect(data.name).toEqual("My customers first Api Key");
|
|
34
|
+
expect(data.key).toEqual(
|
|
35
|
+
"KGTSsxbDndjRRcpJGuQQp2or9UmQkqRrVQpCWgQruIXnvnNatmfdmOTcsgYnNwnH"
|
|
36
|
+
);
|
|
37
|
+
expect(data.createdAt).toEqual(new Date("2022-03-16T10:34:23.353Z"));
|
|
38
|
+
expect(data.updatedAt).toEqual(new Date("2022-03-16T10:34:23.353Z"));
|
|
39
|
+
expect(data.env).toEqual("live");
|
|
40
|
+
expect(data.customAccountId).toEqual("acc-id");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should list api keys", async () => {
|
|
44
|
+
const client = createClient();
|
|
45
|
+
const keys = await client.apiKeys.getKeys("project_1");
|
|
46
|
+
expect(keys).toEqual(
|
|
47
|
+
expect.arrayContaining([
|
|
48
|
+
expect.objectContaining({
|
|
49
|
+
key: "live_h3uDZInxQexGLkwoxMDmuqz6PsyXGjkbrmSTpEwFb8l97mdAlQKtt14kt9Rv91PL",
|
|
50
|
+
name: "my-first-api-key",
|
|
51
|
+
customMetaData: {},
|
|
52
|
+
customAccountId: null,
|
|
53
|
+
env: "live",
|
|
54
|
+
}),
|
|
55
|
+
expect.objectContaining({
|
|
56
|
+
key: "live_1OvRrfHbPdiCUrFAD4VwxiqEgg8L5uiVDlIgE4075juY7TnimZQG1Ll770irHyfM",
|
|
57
|
+
name: "my-second-api-key",
|
|
58
|
+
customMetaData: {},
|
|
59
|
+
customAccountId: null,
|
|
60
|
+
env: "live",
|
|
61
|
+
}),
|
|
62
|
+
])
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should create a key", async () => {
|
|
67
|
+
const client = createClient();
|
|
68
|
+
const key = await client.apiKeys.createKey({
|
|
69
|
+
name: "my-new-api-key1",
|
|
70
|
+
projectId: "b52262b5-eaa6-4edd-825c-ebcdf76a10e5",
|
|
71
|
+
});
|
|
72
|
+
expect(key).toEqual(
|
|
73
|
+
expect.objectContaining({
|
|
74
|
+
key: "live_1OvRrfHbPdiCUrFAD4VwxiqEgg8L5uiVDlIgE4075juY7TnimZQG1Ll770irHyfM",
|
|
75
|
+
name: "my-new-api-key1",
|
|
76
|
+
env: "live",
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should update a key", async () => {
|
|
82
|
+
const client = createClient();
|
|
83
|
+
const key = await client.apiKeys.updateKey(
|
|
84
|
+
"live_TVHW0PVtktylIVObMd8J0sBHb7Ym3ZraObpeT3qxu7YRHig2KxrEIwggn50sBpSZ",
|
|
85
|
+
{
|
|
86
|
+
name: "my-first-update-key",
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
expect(key.name).toEqual("my-first-updated-key");
|
|
90
|
+
expect(key.key).toEqual(
|
|
91
|
+
"live_TVHW0PVtktylIVObMd8J0sBHb7Ym3ZraObpeT3qxu7YRHig2KxrEIwggn50sBpSZ"
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("should delete a key", async () => {
|
|
96
|
+
const client = createClient();
|
|
97
|
+
const response = await client.apiKeys.deleteKey(
|
|
98
|
+
"live_TVHW0PVtktylIVObMd8J0sBHb7Ym3ZraObpeT3qxu7YRHig2KxrEIwggn50sBpSZ"
|
|
99
|
+
);
|
|
100
|
+
expect(response).toBeTruthy();
|
|
101
|
+
});
|
|
102
|
+
});
|