attlaz-client 1.16.8 → 1.17.1

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.
@@ -1,9 +1,10 @@
1
1
  import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
2
2
  import { State } from '../../Model/State.js';
3
3
  export declare class QueryString {
4
- private readonly command;
4
+ private command;
5
5
  private parameters;
6
- constructor(command: string);
6
+ constructor(command?: string);
7
+ setCommand(command: string): void;
7
8
  set(parameter: string, value: string | number | boolean | string[]): void;
8
9
  addPagination(pagination: CursorPagination | null): void;
9
10
  addStateFilter(states: State[] | null): void;
@@ -1,7 +1,10 @@
1
1
  export class QueryString {
2
2
  command;
3
3
  parameters = [];
4
- constructor(command) {
4
+ constructor(command = '') {
5
+ this.command = command;
6
+ }
7
+ setCommand(command) {
5
8
  this.command = command;
6
9
  }
7
10
  set(parameter, value) {
@@ -12,7 +12,7 @@ export declare class HttpClient {
12
12
  static HTTP_UNAVAILABLE: number;
13
13
  static HTTP_TIMEOUT: number;
14
14
  static request(request: HttpClientRequest): Promise<HttpClientResponse>;
15
- private static popsicleRequest;
15
+ private static axiosRequest;
16
16
  private static isJson;
17
17
  static formatContentType(input: string): {
18
18
  type: string;
@@ -1,4 +1,5 @@
1
- import { fetch } from 'popsicle';
1
+ // import {fetch} from 'popsicle';
2
+ import axios from 'axios';
2
3
  import { HttpClientResponse } from './HttpClientResponse.js';
3
4
  import { ClientError } from './ClientError.js';
4
5
  export class HttpClient {
@@ -13,7 +14,7 @@ export class HttpClient {
13
14
  static HTTP_UNAVAILABLE = 503;
14
15
  static HTTP_TIMEOUT = 504;
15
16
  static async request(request) {
16
- const response = await HttpClient.popsicleRequest(request);
17
+ const response = await HttpClient.axiosRequest(request);
17
18
  // const response: HttpClientResponse = await HttpClient.superAgentRequest(request);
18
19
  const error = ClientError.byStatus(response.status, response.statusText);
19
20
  if (error !== null && error !== undefined) {
@@ -24,39 +25,74 @@ export class HttpClient {
24
25
  }
25
26
  return response;
26
27
  }
27
- static async popsicleRequest(request) {
28
- const rawRequest = {
28
+ static async axiosRequest(request) {
29
+ const requestConfig = {
29
30
  url: request.getFullUrl(),
30
31
  method: request.method,
31
32
  headers: request.headers,
32
- omitDefaultHeaders: true,
33
- body: request.body,
33
+ data: request.body,
34
34
  };
35
- const rawResponse = await fetch(request.getFullUrl(), rawRequest);
35
+ // TODO: should we share this instance between requests?
36
+ const axiosInstance = axios.create();
37
+ const rawResponse = await axiosInstance.request(requestConfig);
36
38
  const httpResponse = new HttpClientResponse(rawResponse.status, rawResponse.statusText);
37
- for (const header of rawResponse.headers.keys()) {
38
- const headerValue = rawResponse.headers.get(header);
39
+ Object.keys(rawResponse.headers).forEach((header) => {
40
+ const headerValue = rawResponse.headers[header];
39
41
  httpResponse.headers[header] = headerValue === null ? '' : headerValue;
40
- }
41
- httpResponse.body = await rawResponse.text();
42
- if (HttpClient.isJson(httpResponse)) {
43
- let jsonData = null;
44
- if (httpResponse.body !== '') {
45
- try {
46
- jsonData = JSON.parse(httpResponse.body);
47
- }
48
- catch (e) {
49
- // console.error(, {statusText: httpResponse.statusText, error: e});
50
- throw new Error('Unable to parse response data to JSON');
51
- }
52
- }
53
- httpResponse.body = jsonData;
54
- }
55
- else {
56
- // response.body = rawData;
57
- }
42
+ });
43
+ // console.log('Raw', rawResponse.data);
44
+ // console.log('Is json', HttpClient.isJson(httpResponse));
45
+ httpResponse.body = await rawResponse.data;
46
+ // if (HttpClient.isJson(httpResponse)) {
47
+ // let jsonData: object | null = null;
48
+ // if (httpResponse.body !== '') {
49
+ // try {
50
+ // jsonData = JSON.parse(httpResponse.body);
51
+ // } catch (e) {
52
+ // // console.error(, {statusText: httpResponse.statusText, error: e});
53
+ // throw new Error('Unable to parse response data to JSON');
54
+ // }
55
+ // }
56
+ // httpResponse.body = jsonData;
57
+ // } else {
58
+ // // response.body = rawData;
59
+ // }
58
60
  return httpResponse;
59
61
  }
62
+ // private static async popsicleRequest(request: HttpClientRequest): Promise<HttpClientResponse> {
63
+ // const rawRequest: CommonRequestOptions<any> = {
64
+ // url: request.getFullUrl(),
65
+ // method: request.method,
66
+ // headers: request.headers,
67
+ // omitDefaultHeaders: true,
68
+ // body: request.body,
69
+ // } as CommonRequestOptions<any>;
70
+ // const rawResponse: PopsicleResponse = await fetch(request.getFullUrl(), rawRequest);
71
+ // const httpResponse: HttpClientResponse = new HttpClientResponse(rawResponse.status, rawResponse.statusText);
72
+ // for (const header of rawResponse.headers.keys()) {
73
+ // const headerValue: string | null = rawResponse.headers.get(header);
74
+ // httpResponse.headers[header] = headerValue === null ? '' : headerValue;
75
+ // }
76
+ //
77
+ // httpResponse.body = await rawResponse.text();
78
+ // if (HttpClient.isJson(httpResponse)) {
79
+ // let jsonData: object | null = null;
80
+ // if (httpResponse.body !== '') {
81
+ // try {
82
+ // jsonData = JSON.parse(httpResponse.body);
83
+ // } catch (e) {
84
+ // // console.error(, {statusText: httpResponse.statusText, error: e});
85
+ // throw new Error('Unable to parse response data to JSON');
86
+ // }
87
+ // }
88
+ // httpResponse.body = jsonData;
89
+ // } else {
90
+ // // response.body = rawData;
91
+ // }
92
+ //
93
+ //
94
+ // return httpResponse;
95
+ // }
60
96
  // private static async superAgentRequest(request: HttpClientRequest): Promise<HttpClientResponse> {
61
97
  //
62
98
  //
@@ -2,17 +2,18 @@ import { OAuthClientOptions } from './OAuthClientOptions.js';
2
2
  import { OAuthClientToken } from './OAuthClientToken.js';
3
3
  import { Parameters } from './Data/Parameters.js';
4
4
  import { Headers } from './Data/Headers.js';
5
+ import { QueryString } from './Data/QueryString.js';
5
6
  export declare class OAuthClient {
6
7
  private readonly options;
7
8
  private debug;
8
- private oauthClient;
9
- private oauthToken;
9
+ private axiosInstance;
10
10
  private oathClientToken;
11
11
  private refreshTokenPromise;
12
12
  constructor(options: OAuthClientOptions);
13
13
  authenticate(username: string, password: string): Promise<boolean>;
14
14
  authenticate(): Promise<boolean>;
15
15
  refreshToken(): Promise<void>;
16
+ private getAxiosInstance;
16
17
  isTokenExpires(): boolean;
17
18
  request(action: string, parameters?: Parameters, method?: string, signWithOauthToken?: boolean): Promise<any>;
18
19
  isAuthenticated(): boolean;
@@ -22,15 +23,11 @@ export declare class OAuthClient {
22
23
  enableDebug(): void;
23
24
  disableDebug(): void;
24
25
  isDebugEnabled(): boolean;
25
- getTokenFlowUrl(options?: {
26
- query?: {
27
- [key: string]: string | string[];
28
- };
29
- } | null): string;
26
+ getTokenFlowUrl(options?: QueryString | null): string;
30
27
  getDefaultHeaders(): Headers;
31
28
  private isNodeEnvironment;
32
29
  private tokenToOauthClientToken;
33
- private getUri;
30
+ private getApiEndpointUrl;
34
31
  private createRequestData;
35
32
  private signRequest;
36
33
  }
@@ -1,45 +1,54 @@
1
- import ClientOAuth2 from 'client-oauth2';
1
+ // import ClientOAuth2, {Token} from 'client-oauth2';
2
+ import { clientCredentials, ownerCredentials, refreshToken } from 'axios-oauth-client';
3
+ import axios from 'axios';
2
4
  import { ClientError } from './ClientError.js';
3
5
  import { HttpClient } from './HttpClient.js';
4
6
  import { HttpClientRequest } from './HttpClientRequest.js';
5
7
  import { OAuthClientToken } from './OAuthClientToken.js';
6
8
  import { JsonSerializable } from '../Model/JsonSerializable.js';
7
9
  import { VERSION } from '../version.js';
10
+ import { QueryString } from './Data/QueryString.js';
8
11
  export class OAuthClient {
9
12
  options;
10
13
  debug = false;
11
- oauthClient;
12
- oauthToken = null;
14
+ axiosInstance = null;
15
+ // private oauthClient: ClientOAuth2;
16
+ // private oauthToken: Token | null = null;
13
17
  oathClientToken = null;
14
18
  refreshTokenPromise = null;
15
19
  constructor(options) {
16
20
  this.options = options;
17
- this.oauthClient = new ClientOAuth2({
18
- clientId: options.clientId === null ? undefined : options.clientId,
19
- clientSecret: options.clientSecret === null ? undefined : options.clientSecret,
20
- accessTokenUri: this.getUri(options.accessTokenUri),
21
- authorizationUri: this.getUri(options.authorizationUri),
22
- redirectUri: options.redirectUri,
23
- scopes: options.scopes,
24
- state: options.state,
25
- headers: this.getDefaultHeaders(),
26
- });
21
+ // this.oauthClient = new ClientOAuth2({
22
+ // clientId: options.clientId === null ? undefined : options.clientId,
23
+ // clientSecret: options.clientSecret === null ? undefined : options.clientSecret,
24
+ // accessTokenUri: this.getUri(options.accessTokenUri),
25
+ // authorizationUri: this.getUri(options.authorizationUri),
26
+ // redirectUri: options.redirectUri,
27
+ // scopes: options.scopes,
28
+ // state: options.state,
29
+ // headers: this.getDefaultHeaders(),
30
+ // });
27
31
  }
28
32
  async authenticate(username = null, password = null) {
29
33
  // TODO: should we encrypt the password in the client (or is https save enough)?
30
34
  try {
31
- let accessToken;
32
35
  if (username !== null && username !== undefined && password !== null && password !== undefined) {
33
- // Password flow
34
- accessToken = await this.oauthClient.owner.getToken(username, password);
36
+ // Password flow / Owner Credentials grant
37
+ const getOwnerCredentials = ownerCredentials(this.getAxiosInstance(), this.getApiEndpointUrl(this.options.accessTokenUri), this.options.clientId === null ? undefined : this.options.clientId, this.options.clientSecret === null ? undefined : this.options.clientSecret);
38
+ const rawAuthToken = await getOwnerCredentials(username, password, 'OPTIONAL_SCOPES');
39
+ this.oathClientToken = this.tokenToOauthClientToken(rawAuthToken);
40
+ // accessToken = await this.oauthClient.owner.getToken(username, password);
41
+ return true;
35
42
  }
36
- else {
37
- // Client credentials flow
38
- accessToken = await this.oauthClient.credentials.getToken();
39
- }
40
- this.oauthToken = accessToken;
41
- this.oathClientToken = this.tokenToOauthClientToken(this.oauthToken);
43
+ // Client credentials flow
44
+ const getClientCredentials = clientCredentials(this.getAxiosInstance(), this.getApiEndpointUrl(this.options.accessTokenUri), this.options.clientId === null ? undefined : this.options.clientId, this.options.clientSecret === null ? undefined : this.options.clientSecret);
45
+ const rawAuthToken = await getClientCredentials('OPTIONAL_SCOPES');
46
+ this.oathClientToken = this.tokenToOauthClientToken(rawAuthToken);
47
+ // accessToken = await this.oauthClient.credentials.getToken();
42
48
  return true;
49
+ // this.oauthToken = accessToken;
50
+ // this.oathClientToken = this.tokenToOauthClientToken(rawAuthToken);
51
+ // return true;
43
52
  }
44
53
  catch (e) {
45
54
  if (this.debug) {
@@ -52,25 +61,37 @@ export class OAuthClient {
52
61
  if (this.debug) {
53
62
  console.debug('[OAuthClient] refresh token');
54
63
  }
55
- if (this.oauthToken === null) {
64
+ if (this.oathClientToken === null) {
56
65
  throw new Error('unable to refresh token, auth token not set');
57
66
  }
58
- if (this.oauthToken.refreshToken === undefined || this.oauthToken.refreshToken === null || this.oauthToken.refreshToken === '') {
67
+ if (this.oathClientToken.refresh_token === undefined || this.oathClientToken.refresh_token === null || this.oathClientToken.refresh_token === '') {
59
68
  throw new Error('unable to refresh token, refresh token not set');
60
69
  }
61
70
  try {
62
- this.oauthToken = await this.oauthToken.refresh();
63
- this.oathClientToken = this.tokenToOauthClientToken(this.oauthToken);
71
+ const getRefreshToken = refreshToken(this.getAxiosInstance(), this.getApiEndpointUrl(this.options.accessTokenUri), this.options.clientId === null ? undefined : this.options.clientId, this.options.clientSecret === null ? undefined : this.options.clientSecret);
72
+ const auth = await getRefreshToken(this.oathClientToken.refresh_token, 'OPTIONAL_SCOPES');
73
+ // this.oauthToken = await this.oauthToken.refresh();
74
+ this.oathClientToken = this.tokenToOauthClientToken(auth);
64
75
  }
65
76
  catch (e) {
66
77
  throw ClientError.fromError(e);
67
78
  }
68
79
  }
80
+ getAxiosInstance() {
81
+ if (this.axiosInstance === null) {
82
+ this.axiosInstance = axios.create({
83
+ // httpsAgent: new https.Agent({
84
+ // rejectUnauthorized: false,
85
+ // }),
86
+ });
87
+ }
88
+ return this.axiosInstance;
89
+ }
69
90
  isTokenExpires() {
70
- if (this.oauthToken === null) {
91
+ if (this.oathClientToken === null) {
71
92
  throw new Error('No token defined');
72
93
  }
73
- return this.oauthToken.expired();
94
+ return OAuthClientToken.isExpired(this.oathClientToken);
74
95
  }
75
96
  async request(action, parameters = null, method = 'GET', signWithOauthToken = true) {
76
97
  if (signWithOauthToken && !this.isAuthenticated()) {
@@ -78,10 +99,10 @@ export class OAuthClient {
78
99
  }
79
100
  else {
80
101
  if (signWithOauthToken) {
81
- if (this.oauthToken === null) {
102
+ if (this.oathClientToken === null) {
82
103
  throw new ClientError('Unable to perform request, access token not provided');
83
104
  }
84
- if (signWithOauthToken && this.oauthToken.expired()) {
105
+ if (signWithOauthToken && OAuthClientToken.isExpired(this.oathClientToken)) {
85
106
  if (this.refreshTokenPromise === null) {
86
107
  this.refreshTokenPromise = this.refreshToken();
87
108
  await this.refreshTokenPromise;
@@ -120,30 +141,25 @@ export class OAuthClient {
120
141
  return this.oathClientToken !== null && this.oathClientToken !== undefined;
121
142
  }
122
143
  getToken() {
123
- if (this.oauthToken === null) {
124
- return null;
125
- }
126
- if (this.oathClientToken === null) {
127
- this.oathClientToken = this.tokenToOauthClientToken(this.oauthToken);
128
- }
129
144
  return this.oathClientToken;
130
145
  }
131
146
  setToken(token) {
132
- const data = {
133
- access_token: token.access_token,
134
- token_type: token.token_type,
135
- refresh_token: token.refresh_token,
136
- scope: token.scope,
137
- };
138
- const oauthToken = this.oauthClient.createToken(data);
139
- if (token.expires !== null && token.expires !== undefined) {
140
- oauthToken.expiresIn(token.expires);
141
- }
142
- this.oauthToken = oauthToken;
147
+ // const data: {} = {
148
+ // access_token: token.access_token,
149
+ // token_type: token.token_type,
150
+ // refresh_token: token.refresh_token,
151
+ // scope: token.scope,
152
+ //
153
+ // };
154
+ // const oauthToken: Token = this.oauthClient.createToken(data);
155
+ // if (token.expires !== null && token.expires !== undefined) {
156
+ // oauthToken.expiresIn(token.expires);
157
+ // }
158
+ // this.oauthToken = oauthToken;
143
159
  this.oathClientToken = token;
144
160
  }
145
161
  unsetToken() {
146
- this.oauthToken = null;
162
+ // this.oauthToken = null;
147
163
  this.oathClientToken = null;
148
164
  }
149
165
  enableDebug() {
@@ -156,7 +172,11 @@ export class OAuthClient {
156
172
  return this.debug;
157
173
  }
158
174
  getTokenFlowUrl(options = null) {
159
- return this.oauthClient.token.getUri(options === null ? undefined : options);
175
+ if (options === null) {
176
+ options = new QueryString();
177
+ }
178
+ options.setCommand(this.getApiEndpointUrl(this.options.accessTokenUri));
179
+ return options.build();
160
180
  }
161
181
  getDefaultHeaders() {
162
182
  const userAgentInfo = {
@@ -175,28 +195,28 @@ export class OAuthClient {
175
195
  return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
176
196
  }
177
197
  tokenToOauthClientToken(oauthToken) {
178
- let scopes = '';
179
- if (Object.prototype.hasOwnProperty.call(oauthToken.data, 'scopes')) {
180
- scopes = oauthToken.data.scopes;
181
- }
182
- else if (Object.prototype.hasOwnProperty.call(oauthToken.data, 'scope')) {
183
- scopes = oauthToken.data.scope;
184
- }
185
- const token = new OAuthClientToken(oauthToken.accessToken, oauthToken.tokenType, oauthToken.refreshToken, scopes);
186
- const rawTokenExpires = oauthToken.expires;
187
- if (rawTokenExpires !== null && rawTokenExpires !== undefined) {
188
- token.expires = rawTokenExpires;
189
- }
198
+ // console.log('Auth token', oauthToken);
199
+ // let scopes: string = '';
200
+ // if (Object.prototype.hasOwnProperty.call(oauthToken.data, 'scopes')) {
201
+ // scopes = oauthToken.data.scopes;
202
+ // } else if (Object.prototype.hasOwnProperty.call(oauthToken.data, 'scope')) {
203
+ // scopes = oauthToken.data.scope;
204
+ // }
205
+ const refreshToken = oauthToken.refresh_token === undefined || oauthToken.refresh_token === null ? null : oauthToken.refresh_token;
206
+ const token = new OAuthClientToken(oauthToken.access_token, oauthToken.token_type, refreshToken, oauthToken.scope);
207
+ const t = new Date();
208
+ t.setSeconds(t.getSeconds() + oauthToken.expires_in);
209
+ token.expires = t;
190
210
  return token;
191
211
  }
192
- getUri(uri) {
212
+ getApiEndpointUrl(uri) {
193
213
  if (uri.indexOf('http://') === 0 || uri.indexOf('https://') === 0) {
194
214
  return uri;
195
215
  }
196
216
  return this.options.apiEndpoint.replace(/\/+$/, '') + '/' + uri.replace(/^\/+/g, '');
197
217
  }
198
218
  createRequestData(action, parameters = null, method = 'GET', signWithOauthToken = true) {
199
- const url = this.getUri(action);
219
+ const url = this.getApiEndpointUrl(action);
200
220
  let requestData = new HttpClientRequest(url, method);
201
221
  requestData.headers = this.getDefaultHeaders();
202
222
  if ((method === 'POST' || method === 'DELETE' || method === 'PUT') && parameters !== null && parameters !== undefined) {
@@ -219,22 +239,23 @@ export class OAuthClient {
219
239
  });
220
240
  }
221
241
  if (signWithOauthToken) {
222
- if (this.oauthToken === null) {
242
+ if (this.oathClientToken === null) {
223
243
  throw new ClientError('Unable to perform request, access token not provided');
224
244
  }
225
- if (this.oauthToken.expired()) {
245
+ if (OAuthClientToken.isExpired(this.oathClientToken)) {
226
246
  throw new Error('Unable to sign request, token is expired');
227
247
  }
228
248
  requestData = this.signRequest(requestData);
229
249
  }
230
- else {
231
- }
232
250
  return requestData;
233
251
  }
234
252
  signRequest(requestObject) {
235
253
  if (this.oathClientToken === null) {
236
254
  throw new ClientError('Unable to sign request, access token not provided');
237
255
  }
256
+ if (OAuthClientToken.isExpired(this.oathClientToken)) {
257
+ throw new Error('Unable to sign request, token is expired');
258
+ }
238
259
  const tokenType = this.oathClientToken.token_type;
239
260
  const accessToken = this.oathClientToken.access_token;
240
261
  if (tokenType !== undefined && tokenType.toLowerCase() === 'bearer') {
@@ -4,7 +4,7 @@ export declare class OAuthClientToken {
4
4
  refresh_token: string | null;
5
5
  expires: Date | null;
6
6
  scope: string;
7
- constructor(access_token: string, token_type: string, refresh_token: string, scope: string);
7
+ constructor(access_token: string, token_type: string, refresh_token: string | null, scope: string);
8
8
  static isExpired(token: OAuthClientToken): boolean;
9
9
  static serialize(token: OAuthClientToken): string;
10
10
  static deserialize(serializedToken: string): OAuthClientToken;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "attlaz-client",
3
- "version": "1.16.8",
3
+ "version": "1.17.1",
4
4
  "description": "Javascript Client to access Attlaz API",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -41,8 +41,8 @@
41
41
  "registry": "https://registry.npmjs.org"
42
42
  },
43
43
  "dependencies": {
44
- "client-oauth2": "^4.3.3",
45
- "popsicle": "^12.1.0"
44
+ "axios": "^1.7.7",
45
+ "axios-oauth-client": "^2.2.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/jest": "^29.5.2",