-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathups-api.ts
142 lines (131 loc) · 4.79 KB
/
ups-api.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { ClientCredentialsConfigurationParams } from "./configuration";
import * as authenticationApi from "./authentication";
import * as ratingApi from "./rating";
import * as shippingApi from "./shipping";
import * as timeInTransitApi from './time-in-transit'
import * as paperlessDocument from './paperless-document'
import { isTokenExpired } from "./util";
import { URL } from "node:url";
type ApiConstructorsType =
| typeof ratingApi.DefaultApi
| typeof shippingApi.DefaultApi
| typeof timeInTransitApi.DefaultApi
| typeof paperlessDocument.DefaultApi;
type ApiType =
| ratingApi.DefaultApi
| shippingApi.DefaultApi
| timeInTransitApi.DefaultApi
| paperlessDocument.DefaultApi;
export class UPSApi {
private configuration: ClientCredentialsConfigurationParams;
private baseURL: string;
private apis = new Map<ApiConstructorsType, ApiType>();
private authenticationApi: authenticationApi.DefaultApi;
private cachedToken: authenticationApi.GenerateTokenSuccessResponse;
/**
* The URL for the authentication service is obtained automatically by removing the path from baseURL
* @param baseURL You probably want https://wwwcie.ups.com/api for testing and https://onlinetools.ups.com/api for production
*/
constructor(
configuration: ClientCredentialsConfigurationParams,
baseURL: string
) {
this.configuration = configuration;
this.baseURL = baseURL;
const urlObject = new URL(baseURL);
this.authenticationApi = new authenticationApi.DefaultApi(
{
username: configuration.client_id,
password: configuration.client_secret,
},
urlObject.origin
);
}
_getApi(classConstructor: ApiConstructorsType) {
let api = this.apis.get(classConstructor);
if (api) {
return { new: false, api: api };
}
api = new classConstructor(
{ accessToken: this._getToken.bind(this) },
this.baseURL
);
this.apis.set(classConstructor, api);
return { new: true, api: api };
}
_getToken(): string {
return this.cachedToken.access_token!;
}
_wrapWithAuthentication<ArgsType extends any[], Return>(
func: (...args: ArgsType) => Promise<Return>
): (...args: ArgsType) => Promise<Return> {
return async (...params) => {
await this._checkAndRefreshToken();
return func(...params);
};
}
async _checkAndRefreshToken() {
// first time token is undefined
// otherwise check if it's expired or near expiration
if (!this.cachedToken || isTokenExpired(this.cachedToken, 10000)) {
const tokenResponse = await this.authenticationApi.generateToken(
"client_credentials"
);
this.cachedToken = tokenResponse;
}
}
public rating(): ratingApi.DefaultApi {
const apiInfo = this._getApi(ratingApi.DefaultApi) as {
new: boolean;
api: ratingApi.DefaultApi;
};
const api = apiInfo.api;
if (apiInfo.new) {
api.rate = this._wrapWithAuthentication(api.rate.bind(api));
}
return api;
}
public shipping(): shippingApi.DefaultApi {
const apiInfo = this._getApi(shippingApi.DefaultApi) as {
new: boolean;
api: shippingApi.DefaultApi;
};
const api = apiInfo.api;
if (apiInfo.new) {
api.shipment = this._wrapWithAuthentication(api.shipment.bind(api));
api.voidShipment = this._wrapWithAuthentication(
api.voidShipment.bind(api)
);
api.labelRecovery = this._wrapWithAuthentication(
api.labelRecovery.bind(api)
);
}
return api;
}
public timeInTransit(): timeInTransitApi.DefaultApi {
const apiInfo = this._getApi(timeInTransitApi.DefaultApi) as {
new: boolean;
api: timeInTransitApi.DefaultApi;
}
const api = apiInfo.api;
if(apiInfo.new) {
api.timeInTransit = this._wrapWithAuthentication(api.timeInTransit.bind(api))
}
return api;
}
public paperlessDocument(): paperlessDocument.DefaultApi {
const apiInfo = this._getApi(paperlessDocument.DefaultApi) as {
new: boolean;
api: paperlessDocument.DefaultApi
}
const api = apiInfo.api;
if (apiInfo.new) {
api._delete = this._wrapWithAuthentication(api._delete.bind(api));
api.pushToImageRepository = this._wrapWithAuthentication(
api.pushToImageRepository.bind(api)
);
api.upload = this._wrapWithAuthentication(api.upload.bind(api));
}
return api;
}
}