@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 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 42 Lyon (handles pagination automatically)
110
+ // Get all users from 42Lyon (handles pagination automatically)
111
111
  const lyonUsers = await client.getAll('campus/9/users');
112
- console.log(`Paris campus has ${lyonUsers.length} users`);
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', {
@@ -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
- exports.simplifySuperagentError = simplifySuperagentError;
4
- exports.isSuperAgentError = isSuperAgentError;
5
- class HttpError extends Error {
6
- status;
7
- url;
8
- details;
9
- constructor(err) {
10
- super(err.message || "Unknown API error");
11
- this.name = "HttpError";
12
- this.status = err.status || null;
13
- this.url = err.response?.request?.url || null;
14
- this.details = err.response?.body || null;
15
- }
16
- }
17
- function simplifySuperagentError(err) {
18
- if (!err) {
19
- return new HttpError({ message: "Unknown error" });
20
- }
21
- return new HttpError(err);
22
- }
23
- function isSuperAgentError(err) {
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, perPage } from "./types";
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
- rate: number;
9
+ rateLimitMaxRequests: number;
10
+ rateLimitPerMilliseconds: number;
10
11
  maxRetry: number;
11
- logs: boolean;
12
- errors: boolean;
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 throttler;
25
+ private rateLimitMaxRequests;
26
+ private rateLimitPerMilliseconds;
27
+ private axiosInstance;
24
28
  private retryOn;
25
29
  private maxRetry;
26
- private logs;
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
- patch(endpoint: URL | string, options: inputOptions): Promise<any>;
37
- delete(endpoint: URL | string, options: inputOptions): Promise<any>;
38
- getAll(endpoint: URL | string, options?: inputOptions & perPage): Promise<any>;
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(redirect_uri?: string | null): string;
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 superagent = __importStar(require("superagent"));
41
- // @ts-ignore
42
- const superagent_throttle_1 = __importDefault(require("superagent-throttle"));
43
- const utils_1 = require("./utils");
44
- const HttpError_1 = require("./HttpError");
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
- rate: 2,
19
+ rateLimitMaxRequests: 2,
20
+ rateLimitPerMilliseconds: 1200,
53
21
  maxRetry: 5,
54
- logs: true,
55
- errors: true,
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
- throttler;
35
+ rateLimitMaxRequests;
36
+ rateLimitPerMilliseconds;
37
+ axiosInstance;
67
38
  retryOn;
68
39
  maxRetry;
69
- logs;
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.throttler = new superagent_throttle_1.default({
82
- rate: config.rate,
83
- ratePer: 1100,
84
- concurrent: config.rate - 1 > 0 ? config.rate - 1 : 1,
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.logs = config.logs;
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 superagent.post(this.token_url).send({
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.body.access_token;
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
- req.set("Authorization", `Bearer ${accessToken}`);
111
- // Add query string
112
- if (options.query)
113
- req.query(options.query);
114
- // Send body if any is provided
115
- if (body)
116
- req.send(body);
117
- // Throttle resquest based on rate limit
118
- req.use(this.throttler.plugin());
119
- return req;
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 ((0, HttpError_1.isSuperAgentError)(err)) {
115
+ if (err.isAxiosError) {
116
+ this.logError(err, options);
129
117
  const { attempt, maxRetry } = options;
130
- this.logError(err, url, options);
131
- if (maxRetry > 0 &&
132
- attempt < maxRetry &&
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
- throw (0, HttpError_1.simplifySuperagentError)(err);
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
- const method = options.method.padEnd(6, " ");
151
- const color = "\x1b[42m";
152
- const reset = "\x1b[0m";
153
- const msg = `${color + res.status + reset} ${method} ${res.request.url}${options.attempt ? ` retry ${options.attempt}/${options.maxRetry}` : ``}`;
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, url, options) {
157
- const method = options.method.padEnd(6, " ");
158
- const color = "\x1b[41m";
159
- const reset = "\x1b[0m";
160
- const msg = `${color + err.status + reset} ${method} ${err.response.request.url}${options.attempt ? ` retry ${options.attempt}/${options.maxRetry}` : ``}`;
161
- console.log(msg, JSON.stringify(err.response.body, null, 2));
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.body;
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.body;
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.body;
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.body;
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: 100,
226
- },
244
+ per_page: perPage,
245
+ }
227
246
  });
228
247
  let lastPage;
229
248
  try {
230
- lastPage = (0, utils_1.getLastPage)(initialRes.header["link"]);
249
+ lastPage = Math.min((0, pagination_1.getLastPage)(initialRes.headers["link"]), options.maxPages || Infinity);
231
250
  }
232
251
  catch (err) {
233
- return initialRes.body;
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.body.concat(...values.map((value) => value.body));
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(redirect_uri = null) {
255
- redirect_uri ??= this.redirect_uri;
256
- if (!redirect_uri) {
257
- throw new Error(`undefined redirect_uri`);
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", 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
- return url.toString();
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 superagent.post(this.token_url).send({
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.body;
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;
@@ -0,0 +1,4 @@
1
+ import { reqOptions } from "../types";
2
+ import { AxiosResponse, AxiosError } from "axios";
3
+ export declare function getLogLine(res: AxiosResponse, options: reqOptions): string;
4
+ export declare function getErrorLogLine(err: AxiosError, options: reqOptions): string;
@@ -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
@@ -0,0 +1,4 @@
1
+ import { reqOptions } from "./types";
2
+ import { AxiosResponse, AxiosError } from "axios";
3
+ export declare function getLogLine(res: AxiosResponse, options: reqOptions): string;
4
+ export declare function getErrorLogLine(err: AxiosError, options: reqOptions): string;
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
@@ -1,4 +1 @@
1
- import * as superagent from "superagent";
2
- import { Method } from "./types";
3
- export declare function initRequest(method: Method, url: URL): superagent.Request;
4
1
  export declare function getLastPage(header: string | undefined): number;
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": "2.0.0",
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
- "superagent": "^10.2.1",
12
- "superagent-throttle": "^1.0.1"
10
+ "axios": "^1.6.2",
11
+ "axios-rate-limit": "^1.3.0"
13
12
  },
14
13
  "devDependencies": {
15
- "@types/superagent": "^8.1.9",
14
+ "typescript": "^5.9.3",
15
+ "dotenv": "^16.6.1",
16
16
  "ts-node": "^10.9.2",
17
- "tsc": "^2.0.4"
17
+ "express": "^4.18.2"
18
18
  },
19
19
  "files": [
20
20
  "dist",