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 CHANGED
@@ -86,7 +86,7 @@ import { AppStoreConnectAPI } from "appstore-connect-sdk";
86
86
  import {
87
87
  AppsApi,
88
88
  AppEventLocalizationsApi,
89
- } from "appstore-connect-sdk/dist/openapi/apis";
89
+ } from "appstore-connect-sdk/openapi";
90
90
 
91
91
  const client = new AppStoreConnectAPI({
92
92
  issuerId: "<YOUR ISSUER ID>",
package/dist/cjs/main.js CHANGED
@@ -83,6 +83,135 @@ var Configuration = class {
83
83
  }
84
84
  };
85
85
  var DefaultConfig = new Configuration();
86
+ var BaseAPI = class {
87
+ constructor(configuration = DefaultConfig) {
88
+ this.configuration = configuration;
89
+ this.fetchApi = async (url, init) => {
90
+ let fetchParams = { url, init };
91
+ for (const middleware of this.middleware) {
92
+ if (middleware.pre) {
93
+ fetchParams = await middleware.pre({
94
+ fetch: this.fetchApi,
95
+ ...fetchParams
96
+ }) || fetchParams;
97
+ }
98
+ }
99
+ let response = void 0;
100
+ try {
101
+ response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
102
+ } catch (e) {
103
+ for (const middleware of this.middleware) {
104
+ if (middleware.onError) {
105
+ response = await middleware.onError({
106
+ fetch: this.fetchApi,
107
+ url: fetchParams.url,
108
+ init: fetchParams.init,
109
+ error: e,
110
+ response: response ? response.clone() : void 0
111
+ }) || response;
112
+ }
113
+ }
114
+ if (response === void 0) {
115
+ if (e instanceof Error) {
116
+ throw new FetchError(e, "The request failed and the interceptors did not return an alternative response");
117
+ } else {
118
+ throw e;
119
+ }
120
+ }
121
+ }
122
+ for (const middleware of this.middleware) {
123
+ if (middleware.post) {
124
+ response = await middleware.post({
125
+ fetch: this.fetchApi,
126
+ url: fetchParams.url,
127
+ init: fetchParams.init,
128
+ response: response.clone()
129
+ }) || response;
130
+ }
131
+ }
132
+ return response;
133
+ };
134
+ this.middleware = configuration.middleware;
135
+ }
136
+ withMiddleware(...middlewares) {
137
+ const next = this.clone();
138
+ next.middleware = next.middleware.concat(...middlewares);
139
+ return next;
140
+ }
141
+ withPreMiddleware(...preMiddlewares) {
142
+ const middlewares = preMiddlewares.map((pre) => ({ pre }));
143
+ return this.withMiddleware(...middlewares);
144
+ }
145
+ withPostMiddleware(...postMiddlewares) {
146
+ const middlewares = postMiddlewares.map((post) => ({ post }));
147
+ return this.withMiddleware(...middlewares);
148
+ }
149
+ async request(context, initOverrides) {
150
+ const { url, init } = await this.createFetchParams(context, initOverrides);
151
+ const response = await this.fetchApi(url, init);
152
+ if (response && (response.status >= 200 && response.status < 300)) {
153
+ return response;
154
+ }
155
+ throw new ResponseError(response, "Response returned an error code");
156
+ }
157
+ async createFetchParams(context, initOverrides) {
158
+ let url = this.configuration.basePath + context.path;
159
+ if (context.query !== void 0 && Object.keys(context.query).length !== 0) {
160
+ url += "?" + this.configuration.queryParamsStringify(context.query);
161
+ }
162
+ const headers = Object.assign({}, this.configuration.headers, context.headers);
163
+ Object.keys(headers).forEach((key) => headers[key] === void 0 ? delete headers[key] : {});
164
+ const initOverrideFn = typeof initOverrides === "function" ? initOverrides : async () => initOverrides;
165
+ const initParams = {
166
+ method: context.method,
167
+ headers,
168
+ body: context.body,
169
+ credentials: this.configuration.credentials
170
+ };
171
+ const overriddenInit = {
172
+ ...initParams,
173
+ ...await initOverrideFn({
174
+ init: initParams,
175
+ context
176
+ })
177
+ };
178
+ const init = {
179
+ ...overriddenInit,
180
+ body: isFormData(overriddenInit.body) || overriddenInit.body instanceof URLSearchParams || isBlob(overriddenInit.body) ? overriddenInit.body : JSON.stringify(overriddenInit.body)
181
+ };
182
+ return { url, init };
183
+ }
184
+ /**
185
+ * Create a shallow clone of `this` by constructing a new instance
186
+ * and then shallow cloning data members.
187
+ */
188
+ clone() {
189
+ const constructor = this.constructor;
190
+ const next = new constructor(this.configuration);
191
+ next.middleware = this.middleware.slice();
192
+ return next;
193
+ }
194
+ };
195
+ function isBlob(value) {
196
+ return typeof Blob !== "undefined" && value instanceof Blob;
197
+ }
198
+ function isFormData(value) {
199
+ return typeof FormData !== "undefined" && value instanceof FormData;
200
+ }
201
+ var ResponseError = class extends Error {
202
+ constructor(response, msg) {
203
+ super(msg);
204
+ this.response = response;
205
+ this.name = "ResponseError";
206
+ }
207
+ };
208
+ var FetchError = class extends Error {
209
+ constructor(cause, msg) {
210
+ super(msg);
211
+ this.cause = cause;
212
+ this.name = "FetchError";
213
+ }
214
+ };
86
215
  function querystring(params, prefix = "") {
87
216
  return Object.keys(params).map((key) => querystringSingleKey(key, params[key], prefix)).filter((part) => part.length > 0).join("&");
88
217
  }
@@ -943,11 +1072,12 @@ async function generateAuthToken({ apiKeyId, issuerId, privateKey, expirationTim
943
1072
  kid: apiKeyId,
944
1073
  // The type of the token (JWT)
945
1074
  typ: "JWT"
946
- }).setIssuer(issuerId).setAudience("appstoreconnect-v1").setExpirationTime(expirationTime ?? (/* @__PURE__ */ new Date()).getTime() / 1e3).sign(key);
1075
+ }).setIssuer(issuerId).setAudience("appstoreconnect-v1").setExpirationTime(expirationTime).sign(key);
947
1076
  return token;
948
1077
  }
949
1078
 
950
1079
  // src/main.ts
1080
+ var DEFAULT_EXPIRATION_DURATION_SECONDS = 60 * 20;
951
1081
  var AppStoreConnectAPI = class {
952
1082
  /**
953
1083
  * Creates an instance of the AppStoreConnectAPI.
@@ -957,13 +1087,15 @@ var AppStoreConnectAPI = class {
957
1087
  * @param options.privateKey - The content of the private key used for generating JWT token.
958
1088
  * @param options.fetchApi - (Optional) The FetchAPI implementation to use for API requests.
959
1089
  * @param options.bearerToken - (Optional) A pre-generated bearer token to use for authentication.
960
- * @param options.expirationTime - (Optional) The time (in seconds) until the token expires (default 10 minutes)
1090
+ * @param options.expirationDuration - (Optional) The expiration duration for the bearer token in seconds (default 20 minutes).
961
1091
  * @param options.basePath - (Optional) The base path for the API (without trailing slash, default https://api.appstoreconnect.apple.com).
962
1092
  * @throws {string} Will throw an error if no bearerToken or private key is provided
963
1093
  */
964
1094
  constructor(options) {
1095
+ /**
1096
+ * The time (in milliseconds) when the current bearer token was generated.
1097
+ */
965
1098
  this.bearerTokenGeneratedAt = 0;
966
- if (options.expirationTime) options.expirationTime = options.expirationTime;
967
1099
  this.options = options;
968
1100
  }
969
1101
  /**
@@ -972,16 +1104,16 @@ var AppStoreConnectAPI = class {
972
1104
  async genToken() {
973
1105
  if (this.options.bearerToken) {
974
1106
  return this.options.bearerToken;
975
- } else if (this.options.privateKeyId && this.options.issuerId && this.options.privateKey) {
1107
+ }
1108
+ if (this.options.privateKeyId && this.options.issuerId && this.options.privateKey) {
976
1109
  return await generateAuthToken({
977
1110
  apiKeyId: this.options.privateKeyId,
978
1111
  issuerId: this.options.issuerId,
979
1112
  privateKey: this.options.privateKey,
980
- expirationTime: this.options.expirationTime
1113
+ expirationTime: Math.floor(Date.now() / 1e3) + (this.options.expirationDuration ?? DEFAULT_EXPIRATION_DURATION_SECONDS)
981
1114
  });
982
- } else {
983
- throw "No bearerToken!!!";
984
1115
  }
1116
+ throw "No bearerToken or private key provided";
985
1117
  }
986
1118
  /**
987
1119
  * Create a Configuration object with the authentication token and any provided FetchAPI implementation.
@@ -1000,7 +1132,9 @@ var AppStoreConnectAPI = class {
1000
1132
  * Returns the current bearer token, generating a new one if necessary.
1001
1133
  */
1002
1134
  async getConfiguration() {
1003
- const hasExpired = this.bearerTokenGeneratedAt && Date.now() - this.bearerTokenGeneratedAt > 1e3 * this.options.expirationTime;
1135
+ const latestBearerTokenDuration = this.bearerTokenGeneratedAt ? Date.now() - this.bearerTokenGeneratedAt : 0;
1136
+ const expirationDurationMs = 1e3 * (this.options.expirationDuration ?? DEFAULT_EXPIRATION_DURATION_SECONDS);
1137
+ const hasExpired = latestBearerTokenDuration > expirationDurationMs;
1004
1138
  if (!this.configuration || hasExpired) {
1005
1139
  await this.genConfiguration();
1006
1140
  }
@@ -1014,6 +1148,39 @@ var AppStoreConnectAPI = class {
1014
1148
  async create(apiClass) {
1015
1149
  return new apiClass(await this.getConfiguration());
1016
1150
  }
1151
+ /**
1152
+ * Makes an API request.
1153
+ * @param context - The request context for the API request.
1154
+ * @param initOverrides - (Optional) The request options to use for the API request.
1155
+ * @returns The response from the API request.
1156
+ */
1157
+ async request(context, initOverrides) {
1158
+ if (!context.url && !context.path) {
1159
+ throw new Error("No url or path provided");
1160
+ }
1161
+ const _context = { ...context };
1162
+ if (!_context.path && _context.url) {
1163
+ if (_context.url.startsWith(BASE_PATH)) {
1164
+ _context.path = _context.url.replace(BASE_PATH, "");
1165
+ } else {
1166
+ throw new Error("url must start with " + BASE_PATH);
1167
+ }
1168
+ }
1169
+ if (!_context.method) {
1170
+ _context.method = "GET";
1171
+ }
1172
+ delete _context.url;
1173
+ const globalApi = new GlobalAPI(await this.getConfiguration());
1174
+ return await globalApi.request(_context, initOverrides);
1175
+ }
1176
+ };
1177
+ var GlobalAPI = class extends BaseAPI {
1178
+ constructor(configuration) {
1179
+ super(configuration);
1180
+ }
1181
+ request(context, initOverrides) {
1182
+ return super.request(context, initOverrides);
1183
+ }
1017
1184
  };
1018
1185
  // Annotate the CommonJS export names for ESM import in node:
1019
1186
  0 && (module.exports = {