appstore-connect-sdk 1.2.0 → 1.3.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 +1 -1
- package/dist/cjs/main.js +175 -8
- package/dist/cjs/main.js.map +2 -2
- package/dist/main.js +175 -8
- package/dist/main.js.map +2 -2
- package/dist/types/auth.d.ts +1 -1
- package/dist/types/main.d.ts +40 -4
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -47,6 +47,135 @@ var Configuration = class {
|
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
var DefaultConfig = new Configuration();
|
|
50
|
+
var BaseAPI = class {
|
|
51
|
+
constructor(configuration = DefaultConfig) {
|
|
52
|
+
this.configuration = configuration;
|
|
53
|
+
this.fetchApi = async (url, init) => {
|
|
54
|
+
let fetchParams = { url, init };
|
|
55
|
+
for (const middleware of this.middleware) {
|
|
56
|
+
if (middleware.pre) {
|
|
57
|
+
fetchParams = await middleware.pre({
|
|
58
|
+
fetch: this.fetchApi,
|
|
59
|
+
...fetchParams
|
|
60
|
+
}) || fetchParams;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let response = void 0;
|
|
64
|
+
try {
|
|
65
|
+
response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
for (const middleware of this.middleware) {
|
|
68
|
+
if (middleware.onError) {
|
|
69
|
+
response = await middleware.onError({
|
|
70
|
+
fetch: this.fetchApi,
|
|
71
|
+
url: fetchParams.url,
|
|
72
|
+
init: fetchParams.init,
|
|
73
|
+
error: e,
|
|
74
|
+
response: response ? response.clone() : void 0
|
|
75
|
+
}) || response;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (response === void 0) {
|
|
79
|
+
if (e instanceof Error) {
|
|
80
|
+
throw new FetchError(e, "The request failed and the interceptors did not return an alternative response");
|
|
81
|
+
} else {
|
|
82
|
+
throw e;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const middleware of this.middleware) {
|
|
87
|
+
if (middleware.post) {
|
|
88
|
+
response = await middleware.post({
|
|
89
|
+
fetch: this.fetchApi,
|
|
90
|
+
url: fetchParams.url,
|
|
91
|
+
init: fetchParams.init,
|
|
92
|
+
response: response.clone()
|
|
93
|
+
}) || response;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return response;
|
|
97
|
+
};
|
|
98
|
+
this.middleware = configuration.middleware;
|
|
99
|
+
}
|
|
100
|
+
withMiddleware(...middlewares) {
|
|
101
|
+
const next = this.clone();
|
|
102
|
+
next.middleware = next.middleware.concat(...middlewares);
|
|
103
|
+
return next;
|
|
104
|
+
}
|
|
105
|
+
withPreMiddleware(...preMiddlewares) {
|
|
106
|
+
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
|
107
|
+
return this.withMiddleware(...middlewares);
|
|
108
|
+
}
|
|
109
|
+
withPostMiddleware(...postMiddlewares) {
|
|
110
|
+
const middlewares = postMiddlewares.map((post) => ({ post }));
|
|
111
|
+
return this.withMiddleware(...middlewares);
|
|
112
|
+
}
|
|
113
|
+
async request(context, initOverrides) {
|
|
114
|
+
const { url, init } = await this.createFetchParams(context, initOverrides);
|
|
115
|
+
const response = await this.fetchApi(url, init);
|
|
116
|
+
if (response && (response.status >= 200 && response.status < 300)) {
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
119
|
+
throw new ResponseError(response, "Response returned an error code");
|
|
120
|
+
}
|
|
121
|
+
async createFetchParams(context, initOverrides) {
|
|
122
|
+
let url = this.configuration.basePath + context.path;
|
|
123
|
+
if (context.query !== void 0 && Object.keys(context.query).length !== 0) {
|
|
124
|
+
url += "?" + this.configuration.queryParamsStringify(context.query);
|
|
125
|
+
}
|
|
126
|
+
const headers = Object.assign({}, this.configuration.headers, context.headers);
|
|
127
|
+
Object.keys(headers).forEach((key) => headers[key] === void 0 ? delete headers[key] : {});
|
|
128
|
+
const initOverrideFn = typeof initOverrides === "function" ? initOverrides : async () => initOverrides;
|
|
129
|
+
const initParams = {
|
|
130
|
+
method: context.method,
|
|
131
|
+
headers,
|
|
132
|
+
body: context.body,
|
|
133
|
+
credentials: this.configuration.credentials
|
|
134
|
+
};
|
|
135
|
+
const overriddenInit = {
|
|
136
|
+
...initParams,
|
|
137
|
+
...await initOverrideFn({
|
|
138
|
+
init: initParams,
|
|
139
|
+
context
|
|
140
|
+
})
|
|
141
|
+
};
|
|
142
|
+
const init = {
|
|
143
|
+
...overriddenInit,
|
|
144
|
+
body: isFormData(overriddenInit.body) || overriddenInit.body instanceof URLSearchParams || isBlob(overriddenInit.body) ? overriddenInit.body : JSON.stringify(overriddenInit.body)
|
|
145
|
+
};
|
|
146
|
+
return { url, init };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Create a shallow clone of `this` by constructing a new instance
|
|
150
|
+
* and then shallow cloning data members.
|
|
151
|
+
*/
|
|
152
|
+
clone() {
|
|
153
|
+
const constructor = this.constructor;
|
|
154
|
+
const next = new constructor(this.configuration);
|
|
155
|
+
next.middleware = this.middleware.slice();
|
|
156
|
+
return next;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
function isBlob(value) {
|
|
160
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
161
|
+
}
|
|
162
|
+
function isFormData(value) {
|
|
163
|
+
return typeof FormData !== "undefined" && value instanceof FormData;
|
|
164
|
+
}
|
|
165
|
+
var ResponseError = class extends Error {
|
|
166
|
+
constructor(response, msg) {
|
|
167
|
+
super(msg);
|
|
168
|
+
this.response = response;
|
|
169
|
+
this.name = "ResponseError";
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
var FetchError = class extends Error {
|
|
173
|
+
constructor(cause, msg) {
|
|
174
|
+
super(msg);
|
|
175
|
+
this.cause = cause;
|
|
176
|
+
this.name = "FetchError";
|
|
177
|
+
}
|
|
178
|
+
};
|
|
50
179
|
function querystring(params, prefix = "") {
|
|
51
180
|
return Object.keys(params).map((key) => querystringSingleKey(key, params[key], prefix)).filter((part) => part.length > 0).join("&");
|
|
52
181
|
}
|
|
@@ -907,11 +1036,12 @@ async function generateAuthToken({ apiKeyId, issuerId, privateKey, expirationTim
|
|
|
907
1036
|
kid: apiKeyId,
|
|
908
1037
|
// The type of the token (JWT)
|
|
909
1038
|
typ: "JWT"
|
|
910
|
-
}).setIssuer(issuerId).setAudience("appstoreconnect-v1").setExpirationTime(expirationTime
|
|
1039
|
+
}).setIssuer(issuerId).setAudience("appstoreconnect-v1").setExpirationTime(expirationTime).sign(key);
|
|
911
1040
|
return token;
|
|
912
1041
|
}
|
|
913
1042
|
|
|
914
1043
|
// src/main.ts
|
|
1044
|
+
var DEFAULT_EXPIRATION_DURATION_SECONDS = 60 * 20;
|
|
915
1045
|
var AppStoreConnectAPI = class {
|
|
916
1046
|
/**
|
|
917
1047
|
* Creates an instance of the AppStoreConnectAPI.
|
|
@@ -921,13 +1051,15 @@ var AppStoreConnectAPI = class {
|
|
|
921
1051
|
* @param options.privateKey - The content of the private key used for generating JWT token.
|
|
922
1052
|
* @param options.fetchApi - (Optional) The FetchAPI implementation to use for API requests.
|
|
923
1053
|
* @param options.bearerToken - (Optional) A pre-generated bearer token to use for authentication.
|
|
924
|
-
* @param options.
|
|
1054
|
+
* @param options.expirationDuration - (Optional) The expiration duration for the bearer token in seconds (default 20 minutes).
|
|
925
1055
|
* @param options.basePath - (Optional) The base path for the API (without trailing slash, default https://api.appstoreconnect.apple.com).
|
|
926
1056
|
* @throws {string} Will throw an error if no bearerToken or private key is provided
|
|
927
1057
|
*/
|
|
928
1058
|
constructor(options) {
|
|
1059
|
+
/**
|
|
1060
|
+
* The time (in milliseconds) when the current bearer token was generated.
|
|
1061
|
+
*/
|
|
929
1062
|
this.bearerTokenGeneratedAt = 0;
|
|
930
|
-
if (options.expirationTime) options.expirationTime = options.expirationTime;
|
|
931
1063
|
this.options = options;
|
|
932
1064
|
}
|
|
933
1065
|
/**
|
|
@@ -936,16 +1068,16 @@ var AppStoreConnectAPI = class {
|
|
|
936
1068
|
async genToken() {
|
|
937
1069
|
if (this.options.bearerToken) {
|
|
938
1070
|
return this.options.bearerToken;
|
|
939
|
-
}
|
|
1071
|
+
}
|
|
1072
|
+
if (this.options.privateKeyId && this.options.issuerId && this.options.privateKey) {
|
|
940
1073
|
return await generateAuthToken({
|
|
941
1074
|
apiKeyId: this.options.privateKeyId,
|
|
942
1075
|
issuerId: this.options.issuerId,
|
|
943
1076
|
privateKey: this.options.privateKey,
|
|
944
|
-
expirationTime: this.options.
|
|
1077
|
+
expirationTime: Math.floor(Date.now() / 1e3) + (this.options.expirationDuration ?? DEFAULT_EXPIRATION_DURATION_SECONDS)
|
|
945
1078
|
});
|
|
946
|
-
} else {
|
|
947
|
-
throw "No bearerToken!!!";
|
|
948
1079
|
}
|
|
1080
|
+
throw "No bearerToken or private key provided";
|
|
949
1081
|
}
|
|
950
1082
|
/**
|
|
951
1083
|
* Create a Configuration object with the authentication token and any provided FetchAPI implementation.
|
|
@@ -964,7 +1096,9 @@ var AppStoreConnectAPI = class {
|
|
|
964
1096
|
* Returns the current bearer token, generating a new one if necessary.
|
|
965
1097
|
*/
|
|
966
1098
|
async getConfiguration() {
|
|
967
|
-
const
|
|
1099
|
+
const latestBearerTokenDuration = this.bearerTokenGeneratedAt ? Date.now() - this.bearerTokenGeneratedAt : 0;
|
|
1100
|
+
const expirationDurationMs = 1e3 * (this.options.expirationDuration ?? DEFAULT_EXPIRATION_DURATION_SECONDS);
|
|
1101
|
+
const hasExpired = latestBearerTokenDuration > expirationDurationMs;
|
|
968
1102
|
if (!this.configuration || hasExpired) {
|
|
969
1103
|
await this.genConfiguration();
|
|
970
1104
|
}
|
|
@@ -978,6 +1112,39 @@ var AppStoreConnectAPI = class {
|
|
|
978
1112
|
async create(apiClass) {
|
|
979
1113
|
return new apiClass(await this.getConfiguration());
|
|
980
1114
|
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Makes an API request.
|
|
1117
|
+
* @param context - The request context for the API request.
|
|
1118
|
+
* @param initOverrides - (Optional) The request options to use for the API request.
|
|
1119
|
+
* @returns The response from the API request.
|
|
1120
|
+
*/
|
|
1121
|
+
async request(context, initOverrides) {
|
|
1122
|
+
if (!context.url && !context.path) {
|
|
1123
|
+
throw new Error("No url or path provided");
|
|
1124
|
+
}
|
|
1125
|
+
const _context = { ...context };
|
|
1126
|
+
if (!_context.path && _context.url) {
|
|
1127
|
+
if (_context.url.startsWith(BASE_PATH)) {
|
|
1128
|
+
_context.path = _context.url.replace(BASE_PATH, "");
|
|
1129
|
+
} else {
|
|
1130
|
+
throw new Error("url must start with " + BASE_PATH);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
if (!_context.method) {
|
|
1134
|
+
_context.method = "GET";
|
|
1135
|
+
}
|
|
1136
|
+
delete _context.url;
|
|
1137
|
+
const globalApi = new GlobalAPI(await this.getConfiguration());
|
|
1138
|
+
return await globalApi.request(_context, initOverrides);
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
var GlobalAPI = class extends BaseAPI {
|
|
1142
|
+
constructor(configuration) {
|
|
1143
|
+
super(configuration);
|
|
1144
|
+
}
|
|
1145
|
+
request(context, initOverrides) {
|
|
1146
|
+
return super.request(context, initOverrides);
|
|
1147
|
+
}
|
|
981
1148
|
};
|
|
982
1149
|
export {
|
|
983
1150
|
AppStoreConnectAPI
|