@ibertran/fortytwo-intra-client 2.0.0 → 3.1.0
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/README.md +2 -2
- package/dist/HttpError.d.ts +0 -8
- package/dist/HttpError.js +21 -23
- package/dist/index.d.ts +26 -13
- package/dist/index.js +131 -104
- package/dist/lib/logs.d.ts +4 -0
- package/dist/lib/logs.js +47 -0
- package/dist/lib/pagination.d.ts +1 -0
- package/dist/lib/pagination.js +29 -0
- package/dist/log.d.ts +4 -0
- package/dist/log.js +51 -0
- package/dist/types.d.ts +9 -3
- package/dist/utils.d.ts +0 -3
- package/dist/utils.js +0 -50
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -107,9 +107,9 @@ await client.delete('teams/123');
|
|
|
107
107
|
The `getAll` method automatically handles pagination and returns all results:
|
|
108
108
|
|
|
109
109
|
```typescript
|
|
110
|
-
// Get all users from
|
|
110
|
+
// Get all users from 42Lyon (handles pagination automatically)
|
|
111
111
|
const lyonUsers = await client.getAll('campus/9/users');
|
|
112
|
-
console.log(`
|
|
112
|
+
console.log(`42Lyon campus has ${lyonUsers.length} users`);
|
|
113
113
|
|
|
114
114
|
// Get all projects with custom page size
|
|
115
115
|
const allProjects = await client.getAll('projects', {
|
package/dist/HttpError.d.ts
CHANGED
|
@@ -1,9 +1 @@
|
|
|
1
|
-
declare class HttpError extends Error {
|
|
2
|
-
status: number | null;
|
|
3
|
-
url: string | null;
|
|
4
|
-
details: any;
|
|
5
|
-
constructor(err: any);
|
|
6
|
-
}
|
|
7
|
-
export declare function simplifySuperagentError(err: any): HttpError;
|
|
8
|
-
export declare function isSuperAgentError(err: any): boolean;
|
|
9
1
|
export {};
|
package/dist/HttpError.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return (err && typeof err === "object" && ("status" in err || "response" in err));
|
|
25
|
-
}
|
|
3
|
+
// class HttpError extends Error {
|
|
4
|
+
// status: number | null;
|
|
5
|
+
// url: string | null;
|
|
6
|
+
// details: any;
|
|
7
|
+
// constructor(err: any) {
|
|
8
|
+
// super(err.message || "Unknown API error");
|
|
9
|
+
// this.name = "HttpError";
|
|
10
|
+
// this.status = err.status || err.response?.status || null;
|
|
11
|
+
// this.url = err.config?.url || err.request?.responseURL || null;
|
|
12
|
+
// this.details = err.response?.data || null;
|
|
13
|
+
// }
|
|
14
|
+
// }
|
|
15
|
+
// export function simplifyAxiosError(err: any): HttpError {
|
|
16
|
+
// if (!err) {
|
|
17
|
+
// return new HttpError({ message: "Unknown error" });
|
|
18
|
+
// }
|
|
19
|
+
// return new HttpError(err);
|
|
20
|
+
// }
|
|
21
|
+
// export function isAxiosError(err: any): err is AxiosError {
|
|
22
|
+
// return err && err.isAxiosError === true;
|
|
23
|
+
// }
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { inputOptions
|
|
1
|
+
import { inputOptions } from "./types";
|
|
2
2
|
export interface FortytwoIntraClientConf {
|
|
3
3
|
redirect_uri: string | null;
|
|
4
4
|
base_url: string;
|
|
@@ -6,10 +6,12 @@ export interface FortytwoIntraClientConf {
|
|
|
6
6
|
oauth_url: string;
|
|
7
7
|
token_info_url: string;
|
|
8
8
|
scopes: string[];
|
|
9
|
-
|
|
9
|
+
rateLimitMaxRequests: number;
|
|
10
|
+
rateLimitPerMilliseconds: number;
|
|
10
11
|
maxRetry: number;
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
logLine: boolean;
|
|
13
|
+
errLogBody: boolean;
|
|
14
|
+
throwOnError: boolean;
|
|
13
15
|
}
|
|
14
16
|
export declare class FortytwoIntraClient {
|
|
15
17
|
private client_id;
|
|
@@ -20,10 +22,14 @@ export declare class FortytwoIntraClient {
|
|
|
20
22
|
private oauth_url;
|
|
21
23
|
private token_info_url;
|
|
22
24
|
private scopes;
|
|
23
|
-
private
|
|
25
|
+
private rateLimitMaxRequests;
|
|
26
|
+
private rateLimitPerMilliseconds;
|
|
27
|
+
private axiosInstance;
|
|
24
28
|
private retryOn;
|
|
25
29
|
private maxRetry;
|
|
26
|
-
private
|
|
30
|
+
private logLine;
|
|
31
|
+
private errLogBody;
|
|
32
|
+
private throwOnError;
|
|
27
33
|
private access_token;
|
|
28
34
|
constructor(client_id: string, client_secret: string, conf: Partial<FortytwoIntraClientConf>);
|
|
29
35
|
private generateToken;
|
|
@@ -31,13 +37,20 @@ export declare class FortytwoIntraClient {
|
|
|
31
37
|
private reqHandler;
|
|
32
38
|
private logSuccess;
|
|
33
39
|
private logError;
|
|
34
|
-
get(endpoint: URL | string, options?: Omit<inputOptions, "body">): Promise<any>;
|
|
35
|
-
post(endpoint: URL | string, options?: inputOptions): Promise<any>;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
get(endpoint: URL | string, options?: Omit<inputOptions, "body" | "perPage" | "maxPage">): Promise<any>;
|
|
41
|
+
post(endpoint: URL | string, options?: Omit<inputOptions, "perPage" | "maxPage">): Promise<any>;
|
|
42
|
+
put(endpoint: URL | string, options?: Omit<inputOptions, "perPage" | "maxPage">): Promise<any>;
|
|
43
|
+
patch(endpoint: URL | string, options?: Omit<inputOptions, "perPage" | "maxPage">): Promise<any>;
|
|
44
|
+
delete(endpoint: URL | string, options?: Omit<inputOptions, "perPage" | "maxPage">): Promise<any>;
|
|
45
|
+
getAll(endpoint: URL | string, options?: Omit<inputOptions, "body">): Promise<any>;
|
|
39
46
|
URL(endpoint: string): URL;
|
|
40
|
-
getOAuthUrl(
|
|
47
|
+
getOAuthUrl(options?: {
|
|
48
|
+
redirect_uri?: string;
|
|
49
|
+
state?: string;
|
|
50
|
+
}): {
|
|
51
|
+
url: string;
|
|
52
|
+
state: string;
|
|
53
|
+
};
|
|
41
54
|
exchangeOAuthCode(code: string, redirect_uri?: string): Promise<any>;
|
|
42
|
-
tokenInfos(): Promise<any>;
|
|
55
|
+
tokenInfos(options: Omit<inputOptions, "body" | "perPage" | "maxPage">): Promise<any>;
|
|
43
56
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,47 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
38
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
6
|
exports.FortytwoIntraClient = void 0;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const axios_rate_limit_1 = __importDefault(require("axios-rate-limit"));
|
|
9
|
+
const pagination_1 = require("./lib/pagination");
|
|
10
|
+
const logs_1 = require("./lib/logs");
|
|
11
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
45
12
|
const defaultConf = {
|
|
46
13
|
redirect_uri: null,
|
|
47
14
|
base_url: "https://api.intra.42.fr/v2/",
|
|
@@ -49,10 +16,12 @@ const defaultConf = {
|
|
|
49
16
|
oauth_url: "https://api.intra.42.fr/oauth/authorize",
|
|
50
17
|
token_info_url: "https://api.intra.42.fr/oauth/token/info",
|
|
51
18
|
scopes: ["public"],
|
|
52
|
-
|
|
19
|
+
rateLimitMaxRequests: 2,
|
|
20
|
+
rateLimitPerMilliseconds: 1200,
|
|
53
21
|
maxRetry: 5,
|
|
54
|
-
|
|
55
|
-
|
|
22
|
+
logLine: true,
|
|
23
|
+
errLogBody: true,
|
|
24
|
+
throwOnError: true,
|
|
56
25
|
};
|
|
57
26
|
class FortytwoIntraClient {
|
|
58
27
|
client_id;
|
|
@@ -63,10 +32,14 @@ class FortytwoIntraClient {
|
|
|
63
32
|
oauth_url;
|
|
64
33
|
token_info_url;
|
|
65
34
|
scopes;
|
|
66
|
-
|
|
35
|
+
rateLimitMaxRequests;
|
|
36
|
+
rateLimitPerMilliseconds;
|
|
37
|
+
axiosInstance;
|
|
67
38
|
retryOn;
|
|
68
39
|
maxRetry;
|
|
69
|
-
|
|
40
|
+
logLine;
|
|
41
|
+
errLogBody;
|
|
42
|
+
throwOnError;
|
|
70
43
|
access_token;
|
|
71
44
|
constructor(client_id, client_secret, conf) {
|
|
72
45
|
this.client_id = client_id;
|
|
@@ -78,28 +51,32 @@ class FortytwoIntraClient {
|
|
|
78
51
|
this.oauth_url = config.oauth_url;
|
|
79
52
|
this.token_info_url = config.token_info_url;
|
|
80
53
|
this.scopes = config.scopes;
|
|
81
|
-
this.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
54
|
+
this.rateLimitMaxRequests = config.rateLimitMaxRequests;
|
|
55
|
+
this.rateLimitPerMilliseconds = config.rateLimitPerMilliseconds;
|
|
56
|
+
// Create axios instance with rate limiting
|
|
57
|
+
const axiosInstance = axios_1.default.create();
|
|
58
|
+
this.axiosInstance = (0, axios_rate_limit_1.default)(axiosInstance, {
|
|
59
|
+
maxRequests: this.rateLimitMaxRequests,
|
|
60
|
+
perMilliseconds: this.rateLimitPerMilliseconds,
|
|
85
61
|
});
|
|
86
62
|
this.retryOn = [401, 429, 500];
|
|
87
63
|
this.maxRetry = config.maxRetry;
|
|
88
|
-
this.
|
|
64
|
+
this.logLine = config.logLine;
|
|
65
|
+
this.errLogBody = config.errLogBody;
|
|
66
|
+
this.throwOnError = config.throwOnError;
|
|
89
67
|
this.access_token = null;
|
|
90
68
|
}
|
|
91
69
|
async generateToken() {
|
|
92
|
-
const res = await
|
|
70
|
+
const res = await this.axiosInstance.post(this.token_url, {
|
|
93
71
|
grant_type: "client_credentials",
|
|
94
72
|
client_id: this.client_id,
|
|
95
73
|
client_secret: this.client_secret,
|
|
96
74
|
scope: this.scopes.join(" "),
|
|
97
75
|
});
|
|
98
|
-
return res.
|
|
76
|
+
return res.data.access_token;
|
|
99
77
|
}
|
|
100
78
|
async fetch(url, options) {
|
|
101
|
-
const { method, body } = options;
|
|
102
|
-
const req = (0, utils_1.initRequest)(method, url);
|
|
79
|
+
const { method, body, query } = options;
|
|
103
80
|
if (!options.token && !this.access_token) {
|
|
104
81
|
this.access_token = await this.generateToken();
|
|
105
82
|
}
|
|
@@ -107,16 +84,26 @@ class FortytwoIntraClient {
|
|
|
107
84
|
const accessToken = options.token
|
|
108
85
|
? options.token.access_token
|
|
109
86
|
: this.access_token;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
87
|
+
// Extract query parameters from URL and combine with options.query
|
|
88
|
+
const urlParams = {};
|
|
89
|
+
url.searchParams.forEach((value, key) => {
|
|
90
|
+
urlParams[key] = value;
|
|
91
|
+
});
|
|
92
|
+
// Combine URL params with query params (query params take precedence)
|
|
93
|
+
const combinedParams = { ...urlParams, ...query };
|
|
94
|
+
// Create clean URL without query parameters
|
|
95
|
+
const cleanUrl = new URL(url);
|
|
96
|
+
cleanUrl.search = '';
|
|
97
|
+
// Use the rate-limited axios instance
|
|
98
|
+
return this.axiosInstance.request({
|
|
99
|
+
method: method.toLowerCase(),
|
|
100
|
+
url: cleanUrl.toString(),
|
|
101
|
+
headers: {
|
|
102
|
+
Authorization: `Bearer ${accessToken}`,
|
|
103
|
+
},
|
|
104
|
+
params: combinedParams,
|
|
105
|
+
data: body ? body : undefined,
|
|
106
|
+
});
|
|
120
107
|
}
|
|
121
108
|
async reqHandler(url, options) {
|
|
122
109
|
try {
|
|
@@ -125,20 +112,20 @@ class FortytwoIntraClient {
|
|
|
125
112
|
return res;
|
|
126
113
|
}
|
|
127
114
|
catch (err) {
|
|
128
|
-
if (
|
|
115
|
+
if (err.isAxiosError) {
|
|
116
|
+
this.logError(err, options);
|
|
129
117
|
const { attempt, maxRetry } = options;
|
|
130
|
-
|
|
131
|
-
if (maxRetry > 0 &&
|
|
132
|
-
|
|
133
|
-
this.retryOn.includes(err.status)) {
|
|
134
|
-
if (err.status === 401) {
|
|
118
|
+
const status = err.response?.status;
|
|
119
|
+
if (maxRetry > 0 && attempt < maxRetry && status && this.retryOn.includes(status)) {
|
|
120
|
+
if (status === 401) {
|
|
135
121
|
this.access_token = null;
|
|
136
122
|
}
|
|
137
123
|
options.attempt++;
|
|
138
124
|
return this.reqHandler(url, options);
|
|
139
125
|
}
|
|
140
126
|
else {
|
|
141
|
-
|
|
127
|
+
if (this.throwOnError)
|
|
128
|
+
throw err;
|
|
142
129
|
}
|
|
143
130
|
}
|
|
144
131
|
else {
|
|
@@ -147,18 +134,23 @@ class FortytwoIntraClient {
|
|
|
147
134
|
}
|
|
148
135
|
}
|
|
149
136
|
logSuccess(res, options) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
console.log(msg);
|
|
137
|
+
if (!options.logLine)
|
|
138
|
+
return;
|
|
139
|
+
const line = (0, logs_1.getLogLine)(res, options);
|
|
140
|
+
console.log(line);
|
|
155
141
|
}
|
|
156
|
-
logError(err,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
|
|
142
|
+
logError(err, options) {
|
|
143
|
+
if (!options.logLine)
|
|
144
|
+
return;
|
|
145
|
+
const line = (0, logs_1.getErrorLogLine)(err, options);
|
|
146
|
+
const body = err.response?.data;
|
|
147
|
+
const logBody = options.errLogBody && body && Object.keys(body).length;
|
|
148
|
+
try {
|
|
149
|
+
console.log(line, logBody ? JSON.stringify(body, null, 2) : "");
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
console.log(line, logBody ? body : "");
|
|
153
|
+
}
|
|
162
154
|
}
|
|
163
155
|
// Public methods
|
|
164
156
|
async get(endpoint, options = {}) {
|
|
@@ -169,9 +161,11 @@ class FortytwoIntraClient {
|
|
|
169
161
|
method: "GET",
|
|
170
162
|
attempt: 0,
|
|
171
163
|
maxRetry: this.maxRetry,
|
|
164
|
+
logLine: this.logLine,
|
|
165
|
+
errLogBody: this.errLogBody,
|
|
172
166
|
...options,
|
|
173
167
|
});
|
|
174
|
-
return res
|
|
168
|
+
return res?.data;
|
|
175
169
|
}
|
|
176
170
|
async post(endpoint, options = {}) {
|
|
177
171
|
if (endpoint instanceof URL === false) {
|
|
@@ -181,11 +175,27 @@ class FortytwoIntraClient {
|
|
|
181
175
|
method: "POST",
|
|
182
176
|
attempt: 0,
|
|
183
177
|
maxRetry: this.maxRetry,
|
|
178
|
+
logLine: this.logLine,
|
|
179
|
+
errLogBody: this.errLogBody,
|
|
180
|
+
...options,
|
|
181
|
+
});
|
|
182
|
+
return res?.data;
|
|
183
|
+
}
|
|
184
|
+
async put(endpoint, options = {}) {
|
|
185
|
+
if (endpoint instanceof URL === false) {
|
|
186
|
+
endpoint = new URL(endpoint, this.base_url);
|
|
187
|
+
}
|
|
188
|
+
const res = await this.reqHandler(endpoint, {
|
|
189
|
+
method: "PUT",
|
|
190
|
+
attempt: 0,
|
|
191
|
+
maxRetry: this.maxRetry,
|
|
192
|
+
logLine: this.logLine,
|
|
193
|
+
errLogBody: this.errLogBody,
|
|
184
194
|
...options,
|
|
185
195
|
});
|
|
186
|
-
return res
|
|
196
|
+
return res?.data;
|
|
187
197
|
}
|
|
188
|
-
async patch(endpoint, options) {
|
|
198
|
+
async patch(endpoint, options = {}) {
|
|
189
199
|
if (endpoint instanceof URL === false) {
|
|
190
200
|
endpoint = new URL(endpoint, this.base_url);
|
|
191
201
|
}
|
|
@@ -193,11 +203,13 @@ class FortytwoIntraClient {
|
|
|
193
203
|
method: "PATCH",
|
|
194
204
|
attempt: 0,
|
|
195
205
|
maxRetry: this.maxRetry,
|
|
206
|
+
logLine: this.logLine,
|
|
207
|
+
errLogBody: this.errLogBody,
|
|
196
208
|
...options,
|
|
197
209
|
});
|
|
198
|
-
return res
|
|
210
|
+
return res?.data;
|
|
199
211
|
}
|
|
200
|
-
async delete(endpoint, options) {
|
|
212
|
+
async delete(endpoint, options = {}) {
|
|
201
213
|
if (endpoint instanceof URL === false) {
|
|
202
214
|
endpoint = new URL(endpoint, this.base_url);
|
|
203
215
|
}
|
|
@@ -205,9 +217,11 @@ class FortytwoIntraClient {
|
|
|
205
217
|
method: "DELETE",
|
|
206
218
|
attempt: 0,
|
|
207
219
|
maxRetry: this.maxRetry,
|
|
220
|
+
logLine: this.logLine,
|
|
221
|
+
errLogBody: this.errLogBody,
|
|
208
222
|
...options,
|
|
209
223
|
});
|
|
210
|
-
return res
|
|
224
|
+
return res?.data;
|
|
211
225
|
}
|
|
212
226
|
async getAll(endpoint, options = {}) {
|
|
213
227
|
if (endpoint instanceof URL === false) {
|
|
@@ -218,63 +232,76 @@ class FortytwoIntraClient {
|
|
|
218
232
|
const initialRes = await this.reqHandler(url, {
|
|
219
233
|
method: "GET",
|
|
220
234
|
attempt: 0,
|
|
235
|
+
currpage: 1,
|
|
236
|
+
lastPage: Infinity,
|
|
221
237
|
maxRetry: this.maxRetry,
|
|
238
|
+
logLine: this.logLine,
|
|
239
|
+
errLogBody: this.errLogBody,
|
|
222
240
|
...options,
|
|
223
241
|
query: {
|
|
242
|
+
...options.query,
|
|
224
243
|
page: 1,
|
|
225
|
-
per_page:
|
|
226
|
-
}
|
|
244
|
+
per_page: perPage,
|
|
245
|
+
}
|
|
227
246
|
});
|
|
228
247
|
let lastPage;
|
|
229
248
|
try {
|
|
230
|
-
lastPage = (0,
|
|
249
|
+
lastPage = Math.min((0, pagination_1.getLastPage)(initialRes.headers["link"]), options.maxPages || Infinity);
|
|
231
250
|
}
|
|
232
251
|
catch (err) {
|
|
233
|
-
return initialRes
|
|
252
|
+
return initialRes?.data;
|
|
234
253
|
}
|
|
235
254
|
const promises = [];
|
|
236
255
|
for (let i = 2; i <= lastPage; i++) {
|
|
237
256
|
url = new URL(endpoint);
|
|
238
|
-
url.searchParams.append("per_page", perPage.toString());
|
|
239
|
-
url.searchParams.append("page", i.toString());
|
|
240
257
|
promises.push(this.reqHandler(url, {
|
|
241
258
|
method: "GET",
|
|
242
259
|
attempt: 0,
|
|
260
|
+
currpage: i,
|
|
261
|
+
lastPage: lastPage,
|
|
243
262
|
maxRetry: this.maxRetry,
|
|
263
|
+
logLine: this.logLine,
|
|
264
|
+
errLogBody: this.errLogBody,
|
|
244
265
|
...options,
|
|
266
|
+
query: {
|
|
267
|
+
...options.query,
|
|
268
|
+
page: i,
|
|
269
|
+
per_page: perPage,
|
|
270
|
+
}
|
|
245
271
|
}));
|
|
246
272
|
}
|
|
247
273
|
return Promise.all(promises).then((values) => {
|
|
248
|
-
return initialRes.
|
|
274
|
+
return initialRes?.data.concat(...values.map((value) => value.data));
|
|
249
275
|
});
|
|
250
276
|
}
|
|
251
277
|
URL(endpoint) {
|
|
252
278
|
return new URL(endpoint, this.base_url);
|
|
253
279
|
}
|
|
254
|
-
getOAuthUrl(
|
|
255
|
-
redirect_uri
|
|
256
|
-
if (!
|
|
257
|
-
throw new Error(`
|
|
258
|
-
|
|
280
|
+
getOAuthUrl(options = {}) {
|
|
281
|
+
const redirectUri = options.redirect_uri || this.redirect_uri;
|
|
282
|
+
if (!redirectUri)
|
|
283
|
+
throw new Error(`Missing redirect_uri parameter`);
|
|
284
|
+
const state = options.state || crypto_1.default.randomBytes(32).toString('base64url');
|
|
259
285
|
const url = new URL(this.oauth_url);
|
|
260
286
|
url.searchParams.set("client_id", this.client_id);
|
|
261
|
-
url.searchParams.set("redirect_uri",
|
|
287
|
+
url.searchParams.set("redirect_uri", redirectUri);
|
|
262
288
|
url.searchParams.set("response_type", "code");
|
|
263
289
|
url.searchParams.set("scope", this.scopes.join(" "));
|
|
264
|
-
|
|
290
|
+
url.searchParams.set("state", state);
|
|
291
|
+
return { url: url.toString(), state };
|
|
265
292
|
}
|
|
266
293
|
async exchangeOAuthCode(code, redirect_uri) {
|
|
267
|
-
const res = await
|
|
294
|
+
const res = await this.axiosInstance.post(this.token_url, {
|
|
268
295
|
grant_type: "authorization_code",
|
|
269
296
|
client_id: this.client_id,
|
|
270
297
|
client_secret: this.client_secret,
|
|
271
298
|
redirect_uri: redirect_uri ? redirect_uri : this.redirect_uri,
|
|
272
299
|
code: code,
|
|
273
300
|
});
|
|
274
|
-
return res
|
|
301
|
+
return res?.data;
|
|
275
302
|
}
|
|
276
|
-
async tokenInfos() {
|
|
277
|
-
return this.get(this.token_info_url);
|
|
303
|
+
async tokenInfos(options) {
|
|
304
|
+
return this.get(this.token_info_url, options);
|
|
278
305
|
}
|
|
279
306
|
}
|
|
280
307
|
exports.FortytwoIntraClient = FortytwoIntraClient;
|
package/dist/lib/logs.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLogLine = getLogLine;
|
|
4
|
+
exports.getErrorLogLine = getErrorLogLine;
|
|
5
|
+
const green = "\x1b[42m";
|
|
6
|
+
const red = "\x1b[41m";
|
|
7
|
+
const reset = "\x1b[0m";
|
|
8
|
+
function getLogLine(res, options) {
|
|
9
|
+
const tokens = [];
|
|
10
|
+
// Get query parameters as object
|
|
11
|
+
const queryParams = res.config?.params || {};
|
|
12
|
+
tokens.push(`${green}${res.status}${reset}`);
|
|
13
|
+
tokens.push(options.method.padEnd(6, " "));
|
|
14
|
+
// Add the base URL path
|
|
15
|
+
if (res.config?.url) {
|
|
16
|
+
const url = new URL(res.config.url);
|
|
17
|
+
tokens.push(url.pathname);
|
|
18
|
+
}
|
|
19
|
+
// Add query parameters as object if they exist
|
|
20
|
+
console.log(queryParams);
|
|
21
|
+
if (Object.keys(queryParams).length > 0) {
|
|
22
|
+
delete queryParams.per_page;
|
|
23
|
+
delete queryParams.page;
|
|
24
|
+
tokens.push(JSON.stringify(queryParams));
|
|
25
|
+
}
|
|
26
|
+
if (options.currpage) {
|
|
27
|
+
tokens.push(`| page: ${options.currpage}/${options.lastPage === Infinity ? "unknown" : options.lastPage}`);
|
|
28
|
+
}
|
|
29
|
+
return tokens.join(" ");
|
|
30
|
+
}
|
|
31
|
+
function getErrorLogLine(err, options) {
|
|
32
|
+
const tokens = [];
|
|
33
|
+
// Get query parameters as object
|
|
34
|
+
const queryParams = err.config?.params || {};
|
|
35
|
+
tokens.push(`${red}${err.status}${reset}`);
|
|
36
|
+
tokens.push(options.method.padEnd(6, " "));
|
|
37
|
+
// Add the base URL path
|
|
38
|
+
if (err.config?.url) {
|
|
39
|
+
const url = new URL(err.config.url);
|
|
40
|
+
tokens.push(url.pathname);
|
|
41
|
+
}
|
|
42
|
+
// Add query parameters as object if they exist
|
|
43
|
+
if (Object.keys(queryParams).length > 0) {
|
|
44
|
+
tokens.push(JSON.stringify(queryParams));
|
|
45
|
+
}
|
|
46
|
+
return tokens.join(" ");
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getLastPage(header: string | undefined): number;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLastPage = getLastPage;
|
|
4
|
+
function getLastPage(header) {
|
|
5
|
+
if (!header) {
|
|
6
|
+
throw Error("No pagination link header");
|
|
7
|
+
}
|
|
8
|
+
const paginationlinks = header
|
|
9
|
+
.split(",")
|
|
10
|
+
.reduce((links, part) => {
|
|
11
|
+
const match = part.match(/<([^>]+)>\s*;\s*rel="([^"]+)"/);
|
|
12
|
+
if (match) {
|
|
13
|
+
const url = match[1];
|
|
14
|
+
const rel = match[2];
|
|
15
|
+
links[rel] = url;
|
|
16
|
+
}
|
|
17
|
+
return links;
|
|
18
|
+
}, {});
|
|
19
|
+
if (!paginationlinks.last) {
|
|
20
|
+
throw Error("Missing last page link");
|
|
21
|
+
}
|
|
22
|
+
const lastPageUrl = new URL(paginationlinks.last);
|
|
23
|
+
const rawLastPage = lastPageUrl.searchParams.get("page");
|
|
24
|
+
const lastPage = rawLastPage ? parseInt(rawLastPage, 10) : undefined;
|
|
25
|
+
if (!lastPage || isNaN(lastPage)) {
|
|
26
|
+
throw Error("Invalid last page link");
|
|
27
|
+
}
|
|
28
|
+
return lastPage;
|
|
29
|
+
}
|
package/dist/log.d.ts
ADDED
package/dist/log.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLogLine = getLogLine;
|
|
4
|
+
exports.getErrorLogLine = getErrorLogLine;
|
|
5
|
+
const green = "\x1b[42m";
|
|
6
|
+
const red = "\x1b[41m";
|
|
7
|
+
const reset = "\x1b[0m";
|
|
8
|
+
function getLogLine(res, options) {
|
|
9
|
+
const tokens = [];
|
|
10
|
+
// Get query parameters as object
|
|
11
|
+
const queryParams = res.config?.params || {};
|
|
12
|
+
if (process.stdout.isTTY) {
|
|
13
|
+
tokens.push(`${green}${res.status}${reset}`);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
tokens.push(`${res.status}`);
|
|
17
|
+
}
|
|
18
|
+
tokens.push(options.method.padEnd(6, " "));
|
|
19
|
+
// Add the base URL path
|
|
20
|
+
if (res.config?.url) {
|
|
21
|
+
const url = new URL(res.config.url);
|
|
22
|
+
tokens.push(url.pathname);
|
|
23
|
+
}
|
|
24
|
+
// Add query parameters as object if they exist
|
|
25
|
+
if (Object.keys(queryParams).length > 0) {
|
|
26
|
+
tokens.push(JSON.stringify(queryParams));
|
|
27
|
+
}
|
|
28
|
+
return tokens.join(" ");
|
|
29
|
+
}
|
|
30
|
+
function getErrorLogLine(err, options) {
|
|
31
|
+
const tokens = [];
|
|
32
|
+
// Get query parameters as object
|
|
33
|
+
const queryParams = err.config?.params || {};
|
|
34
|
+
if (process.stdout.isTTY) {
|
|
35
|
+
tokens.push(`${red}${err.status}${reset}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
tokens.push(`${err.status}`);
|
|
39
|
+
}
|
|
40
|
+
tokens.push(options.method.padEnd(6, " "));
|
|
41
|
+
// Add the base URL path
|
|
42
|
+
if (err.config?.url) {
|
|
43
|
+
const url = new URL(err.config.url);
|
|
44
|
+
tokens.push(url.pathname);
|
|
45
|
+
}
|
|
46
|
+
// Add query parameters as object if they exist
|
|
47
|
+
if (Object.keys(queryParams).length > 0) {
|
|
48
|
+
tokens.push(JSON.stringify(queryParams));
|
|
49
|
+
}
|
|
50
|
+
return tokens.join(" ");
|
|
51
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
export type Method = "GET" | "POST" | "PATCH" | "DELETE";
|
|
1
|
+
export type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
2
2
|
export type userToken = {
|
|
3
3
|
access_token: string;
|
|
4
4
|
};
|
|
5
5
|
export type reqOptions = {
|
|
6
6
|
method: Method;
|
|
7
|
-
maxRetry: number;
|
|
8
7
|
attempt: number;
|
|
8
|
+
currpage?: number;
|
|
9
|
+
lastPage?: number;
|
|
10
|
+
maxRetry: number;
|
|
11
|
+
perPage?: number;
|
|
12
|
+
maxPages?: number;
|
|
9
13
|
body?: any;
|
|
10
14
|
token?: userToken;
|
|
11
15
|
query?: querystring;
|
|
16
|
+
logLine?: boolean;
|
|
17
|
+
errLogBody?: boolean;
|
|
12
18
|
};
|
|
13
19
|
export type querystring = Record<string, string | number | boolean | Array<string | number | boolean>>;
|
|
14
20
|
export type perPage = {
|
|
15
21
|
perPage?: number;
|
|
16
22
|
};
|
|
17
|
-
type internal = "method" | "attempt";
|
|
23
|
+
type internal = "method" | "attempt" | "page";
|
|
18
24
|
type optional = "maxRetry";
|
|
19
25
|
export type inputOptions = Omit<reqOptions, internal | optional> & Partial<Pick<reqOptions, optional>>;
|
|
20
26
|
export {};
|
package/dist/utils.d.ts
CHANGED
package/dist/utils.js
CHANGED
|
@@ -1,56 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.initRequest = initRequest;
|
|
37
3
|
exports.getLastPage = getLastPage;
|
|
38
|
-
const superagent = __importStar(require("superagent"));
|
|
39
|
-
function initRequest(method, url) {
|
|
40
|
-
const endpoint = url.toString();
|
|
41
|
-
switch (method) {
|
|
42
|
-
case "GET":
|
|
43
|
-
return superagent.get(endpoint);
|
|
44
|
-
case "POST":
|
|
45
|
-
return superagent.post(endpoint);
|
|
46
|
-
case "PATCH":
|
|
47
|
-
return superagent.patch(endpoint);
|
|
48
|
-
case "DELETE":
|
|
49
|
-
return superagent.delete(endpoint);
|
|
50
|
-
default:
|
|
51
|
-
throw Error("Invalid HTTP method");
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
4
|
function getLastPage(header) {
|
|
55
5
|
if (!header) {
|
|
56
6
|
throw Error("No pagination link header");
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ibertran/fortytwo-intra-client",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"build": "tsc"
|
|
8
|
-
"prepare": "npm run build"
|
|
7
|
+
"build": "tsc"
|
|
9
8
|
},
|
|
10
9
|
"dependencies": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
10
|
+
"axios": "^1.6.2",
|
|
11
|
+
"axios-rate-limit": "^1.3.0"
|
|
13
12
|
},
|
|
14
13
|
"devDependencies": {
|
|
15
|
-
"
|
|
14
|
+
"typescript": "^5.9.3",
|
|
15
|
+
"dotenv": "^16.6.1",
|
|
16
16
|
"ts-node": "^10.9.2",
|
|
17
|
-
"
|
|
17
|
+
"express": "^4.18.2"
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"dist",
|