@oapiex/sdk-kit 0.1.11 → 0.1.12
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/dist/index.d.ts +2 -1
- package/package.json +6 -12
- package/dist/index.cjs +0 -1216
- /package/dist/{contracts.mjs → contracts.js} +0 -0
- /package/dist/{index.mjs → index.js} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { A as CountryCodeRestricted, C as UnifiedResponse, D as ValidationErrorResponse, E as ValidationError, O as XGenericObject, S as SuccessResponse, T as UserUrls, _ as NormalPagination, a as AuthErrorResponse, b as Response, c as BasicAuthConfig, d as CustomAuthConfig, f as DebugLevel, g as InitOptions, h as HttpMethod, i as AuthConfig, j as CurrencyCode, k as CountryCode, l as BearerAuthConfig, m as ErrorResponse, n as AccessValidationResult, o as AuthRequestConfig, p as Environment, r as ApiKeyAuthConfig, s as AuthResponse, t as AccessValidationConfigUpdate, u as CursorPagination, v as OAuth2AuthConfig, w as UserConfig, x as ResponseStatus, y as PageInfoMeta } from "./index-CZOi0v1m.js";
|
|
2
|
+
import "dotenv/config";
|
|
2
3
|
import * as axios0 from "axios";
|
|
3
4
|
import { RawAxiosRequestHeaders } from "axios";
|
|
4
5
|
|
|
@@ -320,7 +321,7 @@ declare class HttpException extends Error {
|
|
|
320
321
|
* @param code
|
|
321
322
|
* @param data
|
|
322
323
|
*/
|
|
323
|
-
static fromCode(code: number, data: Required<UnifiedResponse>, parent?: Error): BadRequestException |
|
|
324
|
+
static fromCode(code: number, data: Required<UnifiedResponse>, parent?: Error): BadRequestException | ForbiddenRequestException | HttpException | UnauthorizedRequestException;
|
|
324
325
|
}
|
|
325
326
|
//#endregion
|
|
326
327
|
//#region src/Apis/BaseApi.d.ts
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oapiex/sdk-kit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.12",
|
|
5
5
|
"description": "A TypeScript Base for building SDKs using OpenAPI specifications extracted by OAPIEX.",
|
|
6
|
-
"main": "./dist/index.
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
7
|
"private": false,
|
|
8
|
-
"homepage": "https://toneflix.github.io/oapiex/sdk-kit",
|
|
8
|
+
"homepage": "https://toneflix.github.io/oapiex/reference/sdk-kit",
|
|
9
9
|
"repository": {
|
|
10
10
|
"url": "https://github.com/toneflix/oapiex.git",
|
|
11
11
|
"type": "git",
|
|
@@ -14,17 +14,11 @@
|
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
|
-
"module": "./dist/index.
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
19
|
"exports": {
|
|
20
|
-
".":
|
|
21
|
-
|
|
22
|
-
"require": "./dist/index.cjs"
|
|
23
|
-
},
|
|
24
|
-
"./contracts": {
|
|
25
|
-
"import": "./dist/contracts.mjs",
|
|
26
|
-
"require": "./dist/contracts.cjs"
|
|
27
|
-
},
|
|
20
|
+
".": "./dist/index.js",
|
|
21
|
+
"./contracts": "./dist/contracts.js",
|
|
28
22
|
"./package.json": "./package.json"
|
|
29
23
|
},
|
|
30
24
|
"files": [
|
package/dist/index.cjs
DELETED
|
@@ -1,1216 +0,0 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
require("dotenv/config");
|
|
25
|
-
let axios = require("axios");
|
|
26
|
-
axios = __toESM(axios);
|
|
27
|
-
let path = require("path");
|
|
28
|
-
path = __toESM(path);
|
|
29
|
-
let jiti = require("jiti");
|
|
30
|
-
jiti = __toESM(jiti);
|
|
31
|
-
let node_path = require("node:path");
|
|
32
|
-
node_path = __toESM(node_path);
|
|
33
|
-
let crypto = require("crypto");
|
|
34
|
-
crypto = __toESM(crypto);
|
|
35
|
-
let __h3ravel_shared = require("@h3ravel/shared");
|
|
36
|
-
__h3ravel_shared = __toESM(__h3ravel_shared);
|
|
37
|
-
|
|
38
|
-
//#region src/utilities/global.ts
|
|
39
|
-
String.prototype.toKebabCase = function() {
|
|
40
|
-
return this.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
41
|
-
};
|
|
42
|
-
String.prototype.toCamelCase = function() {
|
|
43
|
-
return this.replace(/[-_ ]+([a-zA-Z0-9])/g, (_, c) => c.toUpperCase()).replace(/^[A-Z]/, (c) => c.toLowerCase());
|
|
44
|
-
};
|
|
45
|
-
String.prototype.toPascalCase = function() {
|
|
46
|
-
return this.replace(/(^\w|[-_ ]+\w)/g, (match) => match.replace(/[-_ ]+/, "").toUpperCase());
|
|
47
|
-
};
|
|
48
|
-
String.prototype.toSnakeCase = function() {
|
|
49
|
-
return this.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
|
|
50
|
-
};
|
|
51
|
-
String.prototype.toSlug = function(separator = "-") {
|
|
52
|
-
return this.toSnakeCase().replace(/[/__:]+/g, "_").replace(/_/g, separator);
|
|
53
|
-
};
|
|
54
|
-
String.prototype.toTitleCase = function() {
|
|
55
|
-
return this.toLowerCase().replace(/(^|\s)\w/g, (match) => match.toUpperCase());
|
|
56
|
-
};
|
|
57
|
-
String.prototype.toCleanCase = function() {
|
|
58
|
-
return this.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ").trim().replace(/\b\w{1,3}\b/g, (match) => match.toUpperCase());
|
|
59
|
-
};
|
|
60
|
-
String.prototype.truncate = function(n, suffix = "…") {
|
|
61
|
-
return this.length > n ? this.slice(0, n - 1) + suffix : this.toString();
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
//#endregion
|
|
65
|
-
//#region src/utilities/helpers.ts
|
|
66
|
-
/**
|
|
67
|
-
* Takes a value like the one prodvided in a destructuring assignment where for instance
|
|
68
|
-
* a single value might have been provided as opposed to an array of values and
|
|
69
|
-
* normalizes it.
|
|
70
|
-
*
|
|
71
|
-
* Examples:
|
|
72
|
-
* Definition:
|
|
73
|
-
* (...value: string[]) => normalizeValue(value)
|
|
74
|
-
*
|
|
75
|
-
* Usage:
|
|
76
|
-
* normalizeValue('singleValue') // returns ['singleValue']
|
|
77
|
-
* normalizeValue('value1', 'value2') // returns ['value1', 'value2']
|
|
78
|
-
* normalizeValue(['value1', 'value2']) // returns ['value1', 'value2']
|
|
79
|
-
*
|
|
80
|
-
* @param value
|
|
81
|
-
* @returns
|
|
82
|
-
*/
|
|
83
|
-
const normalizeValue = (value) => {
|
|
84
|
-
if (Array.isArray(value)) return value;
|
|
85
|
-
return [value];
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* Builds a full url based on endpoint provided
|
|
89
|
-
*
|
|
90
|
-
* @param baseUrl
|
|
91
|
-
* @param endpoint
|
|
92
|
-
*
|
|
93
|
-
* @returns
|
|
94
|
-
*/
|
|
95
|
-
const buildUrl = (baseUrl, ...endpoint) => {
|
|
96
|
-
return (baseUrl + path.default.normalize(path.default.join(...normalizeValue(endpoint)))).replace(/([^:]\/)\/+/g, "$1");
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
//#endregion
|
|
100
|
-
//#region src/config.ts
|
|
101
|
-
const defaultConfig = {
|
|
102
|
-
environment: "sandbox",
|
|
103
|
-
urls: {
|
|
104
|
-
live: "",
|
|
105
|
-
sandbox: ""
|
|
106
|
-
},
|
|
107
|
-
headers: {},
|
|
108
|
-
debugLevel: 0
|
|
109
|
-
};
|
|
110
|
-
const createDefaultConfig = () => ({
|
|
111
|
-
...defaultConfig,
|
|
112
|
-
urls: { ...defaultConfig.urls ?? {} },
|
|
113
|
-
headers: { ...defaultConfig.headers ?? {} }
|
|
114
|
-
});
|
|
115
|
-
const mergeConfig = (baseConfig, config) => ({
|
|
116
|
-
...baseConfig,
|
|
117
|
-
...config,
|
|
118
|
-
urls: config.urls ? {
|
|
119
|
-
...baseConfig.urls ?? defaultConfig.urls,
|
|
120
|
-
...config.urls
|
|
121
|
-
} : baseConfig.urls,
|
|
122
|
-
headers: config.headers ? {
|
|
123
|
-
...baseConfig.headers ?? defaultConfig.headers,
|
|
124
|
-
...config.headers
|
|
125
|
-
} : baseConfig.headers
|
|
126
|
-
});
|
|
127
|
-
const defineConfig = (config) => config;
|
|
128
|
-
|
|
129
|
-
//#endregion
|
|
130
|
-
//#region src/utilities/Manager.ts
|
|
131
|
-
const CONFIG_BASENAMES = [
|
|
132
|
-
"oapiex.config.ts",
|
|
133
|
-
"oapiex.config.js",
|
|
134
|
-
"oapiex.config.cjs"
|
|
135
|
-
];
|
|
136
|
-
let globalConfig = createDefaultConfig();
|
|
137
|
-
let loadedConfigRoot = null;
|
|
138
|
-
const pickInitOptions = (value) => {
|
|
139
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
140
|
-
const config = value;
|
|
141
|
-
const scoped = config.sdkKit ?? config.sdk;
|
|
142
|
-
if (scoped && typeof scoped === "object" && !Array.isArray(scoped)) return pickInitOptions(scoped);
|
|
143
|
-
const nextConfig = [
|
|
144
|
-
"clientId",
|
|
145
|
-
"clientSecret",
|
|
146
|
-
"encryptionKey",
|
|
147
|
-
"environment",
|
|
148
|
-
"urls",
|
|
149
|
-
"headers",
|
|
150
|
-
"timeout",
|
|
151
|
-
"auth",
|
|
152
|
-
"debugLevel"
|
|
153
|
-
].reduce((result, key) => {
|
|
154
|
-
if (config[key] !== void 0) result[key] = config[key];
|
|
155
|
-
return result;
|
|
156
|
-
}, {});
|
|
157
|
-
return Object.keys(nextConfig).length > 0 ? nextConfig : null;
|
|
158
|
-
};
|
|
159
|
-
const loadUserConfig = (rootDir = process.cwd()) => {
|
|
160
|
-
const syncLoad = (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, {
|
|
161
|
-
interopDefault: true,
|
|
162
|
-
moduleCache: false,
|
|
163
|
-
fsCache: false
|
|
164
|
-
});
|
|
165
|
-
for (const basename of CONFIG_BASENAMES) {
|
|
166
|
-
const configPath = node_path.default.join(rootDir, basename);
|
|
167
|
-
try {
|
|
168
|
-
const loaded = syncLoad(configPath);
|
|
169
|
-
const loadedModule = typeof loaded === "object" && loaded !== null ? loaded : null;
|
|
170
|
-
const sdkConfig = pickInitOptions(loadedModule?.default ?? loadedModule?.config ?? loaded);
|
|
171
|
-
if (sdkConfig) return sdkConfig;
|
|
172
|
-
} catch {
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return null;
|
|
177
|
-
};
|
|
178
|
-
const ensureConfigLoaded = (rootDir = process.cwd()) => {
|
|
179
|
-
if (loadedConfigRoot === rootDir) return globalConfig;
|
|
180
|
-
globalConfig = createDefaultConfig();
|
|
181
|
-
loadedConfigRoot = rootDir;
|
|
182
|
-
const userConfig = loadUserConfig(rootDir);
|
|
183
|
-
if (userConfig) globalConfig = mergeConfig(globalConfig, userConfig);
|
|
184
|
-
return globalConfig;
|
|
185
|
-
};
|
|
186
|
-
const updateConfig = (config) => {
|
|
187
|
-
const userConfig = mergeConfig(ensureConfigLoaded(), config);
|
|
188
|
-
globalConfig = userConfig;
|
|
189
|
-
return userConfig;
|
|
190
|
-
};
|
|
191
|
-
const getConfig = () => ensureConfigLoaded();
|
|
192
|
-
const resetConfig = () => {
|
|
193
|
-
loadedConfigRoot = null;
|
|
194
|
-
globalConfig = createDefaultConfig();
|
|
195
|
-
return globalConfig;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
//#endregion
|
|
199
|
-
//#region src/Builder.ts
|
|
200
|
-
var Builder = class {
|
|
201
|
-
static baseUrls = {
|
|
202
|
-
live: "",
|
|
203
|
-
sandbox: ""
|
|
204
|
-
};
|
|
205
|
-
/**
|
|
206
|
-
* API Environment
|
|
207
|
-
*/
|
|
208
|
-
static environment;
|
|
209
|
-
constructor() {}
|
|
210
|
-
/**
|
|
211
|
-
* Sets the environment for the builder
|
|
212
|
-
*
|
|
213
|
-
* @param env
|
|
214
|
-
*/
|
|
215
|
-
static setEnvironment(env) {
|
|
216
|
-
this.environment = env;
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Gets the base url based on environment
|
|
220
|
-
*
|
|
221
|
-
* @returns
|
|
222
|
-
*/
|
|
223
|
-
static baseUrl() {
|
|
224
|
-
const config = getConfig();
|
|
225
|
-
const env = this.environment ?? config.environment ?? this.normalizeEnvironment(process.env.ENVIRONMENT) ?? "sandbox";
|
|
226
|
-
const configuredUrl = config.urls?.[env];
|
|
227
|
-
if (configuredUrl) return this.normalizeBaseUrl(configuredUrl);
|
|
228
|
-
return this.normalizeBaseUrl(this.baseUrls[env]);
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Builds a full url based on endpoint provided
|
|
232
|
-
*
|
|
233
|
-
* @param endpoint
|
|
234
|
-
* @returns
|
|
235
|
-
*/
|
|
236
|
-
static buildUrl(...endpoint) {
|
|
237
|
-
return buildUrl(this.baseUrl(), ...endpoint);
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Builds parameters for query or path
|
|
241
|
-
*
|
|
242
|
-
* @param params
|
|
243
|
-
* @param type
|
|
244
|
-
* @returns
|
|
245
|
-
*/
|
|
246
|
-
static buildParams(params, type = "path") {
|
|
247
|
-
let built = "";
|
|
248
|
-
if (type === "path") built = Object.values(params).join("/");
|
|
249
|
-
else {
|
|
250
|
-
const queryParams = [];
|
|
251
|
-
for (const [key, value] of Object.entries(params)) queryParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
252
|
-
built = queryParams.join("&");
|
|
253
|
-
}
|
|
254
|
-
return built;
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Assigns parameters to url {placeholders} based on type
|
|
258
|
-
*
|
|
259
|
-
* @param url
|
|
260
|
-
* @param params
|
|
261
|
-
* @param type
|
|
262
|
-
*
|
|
263
|
-
* @returns
|
|
264
|
-
*/
|
|
265
|
-
static assignParamsToUrl(url, params, type = "path") {
|
|
266
|
-
let builtUrl = url;
|
|
267
|
-
if (type === "path") for (const [key, value] of Object.entries(params)) {
|
|
268
|
-
builtUrl = builtUrl.replace(`{${key}}`, encodeURIComponent(String(value)));
|
|
269
|
-
builtUrl = builtUrl.replace(`:${key}`, encodeURIComponent(String(value)));
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
272
|
-
if (Object.keys(params).length === 0) return builtUrl;
|
|
273
|
-
const queryString = this.buildParams(params, "query");
|
|
274
|
-
const separator = builtUrl.includes("?") ? "&" : "?";
|
|
275
|
-
builtUrl += `${separator}${queryString}`;
|
|
276
|
-
}
|
|
277
|
-
return builtUrl;
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Builds the target url by assigning both path and query parameters
|
|
281
|
-
*
|
|
282
|
-
* @param path
|
|
283
|
-
* @param params
|
|
284
|
-
* @param queryParams
|
|
285
|
-
* @returns
|
|
286
|
-
*/
|
|
287
|
-
static buildTargetUrl(path$3, params = {}, queryParams = {}) {
|
|
288
|
-
const url = this.buildUrl(path$3);
|
|
289
|
-
let builtUrl = this.assignParamsToUrl(url, params, "path");
|
|
290
|
-
builtUrl = this.assignParamsToUrl(builtUrl, queryParams, "query");
|
|
291
|
-
return builtUrl;
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Encrypts specified keys in the input object and returns a new object with
|
|
295
|
-
* encrypted values.
|
|
296
|
-
*
|
|
297
|
-
* @param input The input object containing the data to be encrypted.
|
|
298
|
-
* @param keysToEncrypt The keys in the input object that should be encrypted.
|
|
299
|
-
* @param outputMapping A mapping of input keys to output keys for the encrypted values.
|
|
300
|
-
* @returns A new object with the specified keys encrypted.
|
|
301
|
-
*/
|
|
302
|
-
static async encryptDetails(input, keysToEncrypt = [], outputMapping = {}) {
|
|
303
|
-
const encryptionKey = getConfig().encryptionKey ?? process.env.ENCRYPTION_KEY;
|
|
304
|
-
if (!encryptionKey) throw new Error("Encryption key is required to encrypt details");
|
|
305
|
-
const nonce = crypto.default.randomBytes(12).toString("base64").slice(0, 12);
|
|
306
|
-
const encryptableKeys = keysToEncrypt.length > 0 ? keysToEncrypt : Object.keys(input);
|
|
307
|
-
const encrypted = Object.fromEntries(Object.entries(input).map(([key, value]) => {
|
|
308
|
-
if (encryptableKeys.includes(key) && typeof value === "string") return [outputMapping?.[key] || key, this.encryptAES(value, encryptionKey, nonce)];
|
|
309
|
-
return [key, value];
|
|
310
|
-
}));
|
|
311
|
-
for (const key of encryptableKeys) delete input[key];
|
|
312
|
-
return encrypted;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Encrypts data using AES-GCM encryption
|
|
316
|
-
* @param data
|
|
317
|
-
* @param token
|
|
318
|
-
* @param nonce
|
|
319
|
-
* @returns
|
|
320
|
-
*/
|
|
321
|
-
static async encryptAES(data, token, nonce) {
|
|
322
|
-
if (nonce.length !== 12) throw new Error("Nonce must be exactly 12 characters long");
|
|
323
|
-
const cryptoSubtle = globalThis.crypto?.subtle || crypto.default.webcrypto?.subtle;
|
|
324
|
-
if (!cryptoSubtle) throw new Error("Crypto API is not available in this environment.");
|
|
325
|
-
const decodedKeyBytes = Uint8Array.from(atob(token), (c) => c.charCodeAt(0));
|
|
326
|
-
const key = await cryptoSubtle.importKey("raw", decodedKeyBytes, { name: "AES-GCM" }, false, ["encrypt"]);
|
|
327
|
-
const iv = new TextEncoder().encode(nonce);
|
|
328
|
-
const encryptedData = await cryptoSubtle.encrypt({
|
|
329
|
-
name: "AES-GCM",
|
|
330
|
-
iv
|
|
331
|
-
}, key, new TextEncoder().encode(data));
|
|
332
|
-
return btoa(String.fromCharCode(...new Uint8Array(encryptedData)));
|
|
333
|
-
}
|
|
334
|
-
static normalizeBaseUrl = (url) => url.endsWith("/") ? url : `${url}/`;
|
|
335
|
-
static normalizeEnvironment = (value) => {
|
|
336
|
-
if (value === "live" || value === "sandbox") return value;
|
|
337
|
-
};
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
//#endregion
|
|
341
|
-
//#region src/Exceptions/BadRequestException.ts
|
|
342
|
-
var BadRequestException = class extends Error {
|
|
343
|
-
statusCode = 400;
|
|
344
|
-
type = "INVALID_REQUEST";
|
|
345
|
-
code = "400";
|
|
346
|
-
data;
|
|
347
|
-
constructor(data) {
|
|
348
|
-
super(data?.error.message ?? data?.message ?? "Bad request. The server could not understand the request due to invalid syntax.");
|
|
349
|
-
if (data?.error.code) this.type = data.error.type;
|
|
350
|
-
if (data?.error.code) this.code = data.error.code;
|
|
351
|
-
this.data = data ?? {
|
|
352
|
-
status: "failed",
|
|
353
|
-
error: {
|
|
354
|
-
type: this.type,
|
|
355
|
-
code: this.code,
|
|
356
|
-
message: this.message,
|
|
357
|
-
validation_errors: []
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
this.name = "BadRequestException";
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
//#endregion
|
|
365
|
-
//#region src/Exceptions/ForbiddenRequestException.ts
|
|
366
|
-
var ForbiddenRequestException = class extends Error {
|
|
367
|
-
statusCode = 403;
|
|
368
|
-
type = "FORBIDDEN";
|
|
369
|
-
code = "403";
|
|
370
|
-
data;
|
|
371
|
-
constructor(data) {
|
|
372
|
-
super(data?.error.message ?? data?.message ?? "Forbidden request. You do not have permission to access this resource.");
|
|
373
|
-
if (data?.error.code) this.type = data.error.type;
|
|
374
|
-
if (data?.error.code) this.code = data.error.code;
|
|
375
|
-
this.data = data ?? {
|
|
376
|
-
status: "failed",
|
|
377
|
-
error: {
|
|
378
|
-
type: this.type,
|
|
379
|
-
code: this.code,
|
|
380
|
-
message: this.message
|
|
381
|
-
}
|
|
382
|
-
};
|
|
383
|
-
this.name = "ForbiddenRequestException";
|
|
384
|
-
}
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
//#endregion
|
|
388
|
-
//#region src/Exceptions/UnauthorizedRequestException.ts
|
|
389
|
-
var UnauthorizedRequestException = class extends Error {
|
|
390
|
-
statusCode = 401;
|
|
391
|
-
type = "UNAUTHORIZED";
|
|
392
|
-
code = "401";
|
|
393
|
-
data;
|
|
394
|
-
constructor(data) {
|
|
395
|
-
super(data?.error.message ?? data?.message ?? "Forbidden request. You do not have permission to access this resource.");
|
|
396
|
-
if (data?.error.code) this.type = data.error.type;
|
|
397
|
-
if (data?.error.code) this.code = data.error.code;
|
|
398
|
-
this.data = data ?? {
|
|
399
|
-
status: "failed",
|
|
400
|
-
error: {
|
|
401
|
-
type: this.type,
|
|
402
|
-
code: this.code,
|
|
403
|
-
message: this.message
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
this.name = "UnauthorizedRequestException";
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
//#endregion
|
|
411
|
-
//#region src/Exceptions/HttpException.ts
|
|
412
|
-
var HttpException = class HttpException extends Error {
|
|
413
|
-
statusCode = 500;
|
|
414
|
-
parent;
|
|
415
|
-
constructor(data, statusCode, parent) {
|
|
416
|
-
super(data.message);
|
|
417
|
-
this.data = data;
|
|
418
|
-
this.name = "HttpException";
|
|
419
|
-
this.parent = parent;
|
|
420
|
-
if (statusCode) this.statusCode = statusCode;
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Create an exception from status code
|
|
424
|
-
*
|
|
425
|
-
* @param code
|
|
426
|
-
* @param data
|
|
427
|
-
*/
|
|
428
|
-
static fromCode(code, data, parent) {
|
|
429
|
-
switch (code) {
|
|
430
|
-
case 400: return new BadRequestException(data);
|
|
431
|
-
case 401: return new UnauthorizedRequestException(data);
|
|
432
|
-
case 403: return new ForbiddenRequestException(data);
|
|
433
|
-
default: return new HttpException(data, code, parent);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
//#endregion
|
|
439
|
-
//#region src/utilities/Log.ts
|
|
440
|
-
var Logger = class Logger {
|
|
441
|
-
/**
|
|
442
|
-
* Render a log message with colors based on the type of each value
|
|
443
|
-
*
|
|
444
|
-
* @param message
|
|
445
|
-
*/
|
|
446
|
-
static run(...message) {
|
|
447
|
-
console.log(message.map((m) => typeof m === "object" ? new Logger().build(m, message.length === 1 ? 0 : 2) : m).join("\n"));
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Recursively build a log string with colors based on the type of each value
|
|
451
|
-
*
|
|
452
|
-
* @param obj
|
|
453
|
-
* @param indent
|
|
454
|
-
* @returns
|
|
455
|
-
*/
|
|
456
|
-
build = (obj, indent = 0) => {
|
|
457
|
-
const indentation = " ".repeat(indent);
|
|
458
|
-
let str = "";
|
|
459
|
-
for (const key in obj) {
|
|
460
|
-
const value = obj[key];
|
|
461
|
-
if (typeof value === "object" && value !== null) {
|
|
462
|
-
str += `${indentation}${this.stringFormatter(key)}:`;
|
|
463
|
-
str += `\n${this.build(value, indent + 2)}\n`;
|
|
464
|
-
} else {
|
|
465
|
-
let coloredValue;
|
|
466
|
-
switch (typeof value) {
|
|
467
|
-
case "string":
|
|
468
|
-
coloredValue = __h3ravel_shared.Logger.log(value, "green", false);
|
|
469
|
-
break;
|
|
470
|
-
case "number":
|
|
471
|
-
coloredValue = __h3ravel_shared.Logger.log(String(value), "yellow", false);
|
|
472
|
-
break;
|
|
473
|
-
case "boolean":
|
|
474
|
-
coloredValue = __h3ravel_shared.Logger.log(String(value), "blue", false);
|
|
475
|
-
break;
|
|
476
|
-
case "object":
|
|
477
|
-
if (value === null) coloredValue = __h3ravel_shared.Logger.log("null", "gray", false);
|
|
478
|
-
else coloredValue = __h3ravel_shared.Logger.log(JSON.stringify(value), "cyan", false);
|
|
479
|
-
break;
|
|
480
|
-
default: coloredValue = value;
|
|
481
|
-
}
|
|
482
|
-
str += `${indentation}${this.stringFormatter(key)}: ${coloredValue}\n`;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
return str;
|
|
486
|
-
};
|
|
487
|
-
/**
|
|
488
|
-
* Format a string to be more human-readable.
|
|
489
|
-
*
|
|
490
|
-
* @param str
|
|
491
|
-
* @returns
|
|
492
|
-
*/
|
|
493
|
-
stringFormatter = (str) => {
|
|
494
|
-
return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ").trim().replace(/^(\w{2})$/, (_, p1) => p1.toUpperCase());
|
|
495
|
-
};
|
|
496
|
-
};
|
|
497
|
-
|
|
498
|
-
//#endregion
|
|
499
|
-
//#region src/Http.ts
|
|
500
|
-
var Http = class Http {
|
|
501
|
-
/**
|
|
502
|
-
* Bearer token
|
|
503
|
-
*/
|
|
504
|
-
static bearerToken;
|
|
505
|
-
/**
|
|
506
|
-
* Debug level
|
|
507
|
-
*/
|
|
508
|
-
static debugLevel = 0;
|
|
509
|
-
static apiInstance;
|
|
510
|
-
/**
|
|
511
|
-
* Creates an instance of Http.
|
|
512
|
-
*
|
|
513
|
-
* @param method
|
|
514
|
-
* @param url
|
|
515
|
-
* @param headers
|
|
516
|
-
* @param body
|
|
517
|
-
*/
|
|
518
|
-
constructor(headers = {}, body) {
|
|
519
|
-
this.headers = headers;
|
|
520
|
-
this.body = body;
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Set the debug level
|
|
524
|
-
*
|
|
525
|
-
* @param debug
|
|
526
|
-
*/
|
|
527
|
-
static setDebugLevel(level = 0) {
|
|
528
|
-
this.debugLevel = level ?? 0;
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Set the API instance
|
|
532
|
-
*
|
|
533
|
-
* @param api
|
|
534
|
-
*/
|
|
535
|
-
static setApiInstance(api) {
|
|
536
|
-
this.apiInstance = api;
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Set the bearer token
|
|
540
|
-
*
|
|
541
|
-
* @param token
|
|
542
|
-
*/
|
|
543
|
-
static setBearerToken(token) {
|
|
544
|
-
this.bearerToken = token;
|
|
545
|
-
updateConfig({ auth: {
|
|
546
|
-
type: "bearer",
|
|
547
|
-
token
|
|
548
|
-
} });
|
|
549
|
-
}
|
|
550
|
-
static setAuth(auth) {
|
|
551
|
-
updateConfig({ auth });
|
|
552
|
-
}
|
|
553
|
-
static setBasicAuth(username, password) {
|
|
554
|
-
this.setAuth({
|
|
555
|
-
type: "basic",
|
|
556
|
-
username,
|
|
557
|
-
password
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
static setApiKey(name, value, location = "header", prefix) {
|
|
561
|
-
this.setAuth({
|
|
562
|
-
type: "apiKey",
|
|
563
|
-
name,
|
|
564
|
-
value,
|
|
565
|
-
in: location,
|
|
566
|
-
prefix
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
static clearAuth() {
|
|
570
|
-
this.bearerToken = void 0;
|
|
571
|
-
updateConfig({ auth: void 0 });
|
|
572
|
-
}
|
|
573
|
-
setDefaultHeaders(defaults) {
|
|
574
|
-
const config = getConfig();
|
|
575
|
-
this.headers = {
|
|
576
|
-
...defaults,
|
|
577
|
-
...config.headers ?? {},
|
|
578
|
-
...this.headers
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
getHeaders() {
|
|
582
|
-
return this.headers;
|
|
583
|
-
}
|
|
584
|
-
getBody() {
|
|
585
|
-
return this.body;
|
|
586
|
-
}
|
|
587
|
-
axiosApi() {
|
|
588
|
-
const config = getConfig();
|
|
589
|
-
this.setDefaultHeaders({
|
|
590
|
-
"Accept": "application/json",
|
|
591
|
-
"Content-Type": "application/json"
|
|
592
|
-
});
|
|
593
|
-
const instance = axios.default.create({
|
|
594
|
-
baseURL: Builder.baseUrl(),
|
|
595
|
-
headers: this.getHeaders(),
|
|
596
|
-
timeout: config.timeout
|
|
597
|
-
});
|
|
598
|
-
if (Http.debugLevel > 0) {
|
|
599
|
-
instance.interceptors.request.use((request) => {
|
|
600
|
-
Logger.run("Starting Request:", {
|
|
601
|
-
url: request.url,
|
|
602
|
-
method: request.method,
|
|
603
|
-
headers: Http.debugLevel < 3 ? Object.fromEntries(Object.entries(request.headers || {}).filter(([key]) => key.toLowerCase() !== "authorization")) : request.headers,
|
|
604
|
-
params: request.params,
|
|
605
|
-
data: request.data
|
|
606
|
-
});
|
|
607
|
-
return request;
|
|
608
|
-
}, (error) => {
|
|
609
|
-
Logger.run("Request Error:", error);
|
|
610
|
-
return Promise.reject(error);
|
|
611
|
-
});
|
|
612
|
-
instance.interceptors.response.use((response) => {
|
|
613
|
-
Logger.run("Response:", {
|
|
614
|
-
status: response.status,
|
|
615
|
-
data: Http.debugLevel < 3 ? Object.fromEntries(Object.entries(response.data || {}).filter(([key]) => key.toLowerCase() !== "access_token")) : response.data
|
|
616
|
-
});
|
|
617
|
-
return response;
|
|
618
|
-
}, (error) => {
|
|
619
|
-
Logger.run("Response Error:", {
|
|
620
|
-
status: error.response?.status,
|
|
621
|
-
data: Object.fromEntries(Object.entries(error.response?.data || {}).filter(([key]) => key.toLowerCase() !== "access_token"))
|
|
622
|
-
});
|
|
623
|
-
return Promise.reject(error);
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
return instance;
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* Makes a GET request
|
|
630
|
-
*
|
|
631
|
-
* @param url
|
|
632
|
-
* @param headers
|
|
633
|
-
* @param params
|
|
634
|
-
* @returns
|
|
635
|
-
*/
|
|
636
|
-
static async get(url, params, headers = {}) {
|
|
637
|
-
return this.send(url, "GET", void 0, headers, params);
|
|
638
|
-
}
|
|
639
|
-
/**
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
* @param url
|
|
643
|
-
* @param headers
|
|
644
|
-
* @param params
|
|
645
|
-
* @returns
|
|
646
|
-
*/
|
|
647
|
-
static async send(url, method, body, headers = {}, params) {
|
|
648
|
-
try {
|
|
649
|
-
const request = await this.prepareRequest({
|
|
650
|
-
url,
|
|
651
|
-
method,
|
|
652
|
-
body,
|
|
653
|
-
headers: this.toHeaderRecord(headers),
|
|
654
|
-
params: { ...params ?? {} }
|
|
655
|
-
});
|
|
656
|
-
const { data } = await new Http(request.headers, request.body).axiosApi()({
|
|
657
|
-
url: request.url,
|
|
658
|
-
method: request.method,
|
|
659
|
-
data: request.body,
|
|
660
|
-
params: request.params
|
|
661
|
-
});
|
|
662
|
-
return {
|
|
663
|
-
success: true,
|
|
664
|
-
message: data.message || "Request successful",
|
|
665
|
-
data: data.data ?? data,
|
|
666
|
-
meta: data.meta
|
|
667
|
-
};
|
|
668
|
-
} catch (e) {
|
|
669
|
-
const error = e.response?.data ?? {};
|
|
670
|
-
throw this.exception(e.response?.status ?? 500, error || e, e);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
static async prepareRequest(request) {
|
|
674
|
-
let prepared = {
|
|
675
|
-
...request,
|
|
676
|
-
headers: { ...request.headers },
|
|
677
|
-
params: { ...request.params ?? {} }
|
|
678
|
-
};
|
|
679
|
-
for (const auth of this.getConfiguredAuth()) prepared = await this.applyAuth(prepared, auth);
|
|
680
|
-
return prepared;
|
|
681
|
-
}
|
|
682
|
-
static getConfiguredAuth() {
|
|
683
|
-
const configuredAuth = getConfig().auth;
|
|
684
|
-
if (configuredAuth) return Array.isArray(configuredAuth) ? configuredAuth : [configuredAuth];
|
|
685
|
-
if (this.bearerToken) return [{
|
|
686
|
-
type: "bearer",
|
|
687
|
-
token: this.bearerToken
|
|
688
|
-
}];
|
|
689
|
-
return [];
|
|
690
|
-
}
|
|
691
|
-
static async applyAuth(request, auth) {
|
|
692
|
-
switch (auth.type) {
|
|
693
|
-
case "bearer":
|
|
694
|
-
this.setHeaderIfMissing(request.headers, "Authorization", `${auth.prefix ?? "Bearer"} ${auth.token}`.trim());
|
|
695
|
-
return request;
|
|
696
|
-
case "oauth2":
|
|
697
|
-
this.setHeaderIfMissing(request.headers, "Authorization", `${auth.tokenType ?? "Bearer"} ${auth.accessToken}`.trim());
|
|
698
|
-
return request;
|
|
699
|
-
case "basic": {
|
|
700
|
-
const encoded = Buffer.from(`${auth.username}:${auth.password}`).toString("base64");
|
|
701
|
-
this.setHeaderIfMissing(request.headers, "Authorization", `Basic ${encoded}`);
|
|
702
|
-
return request;
|
|
703
|
-
}
|
|
704
|
-
case "apiKey": {
|
|
705
|
-
const value = auth.prefix ? `${auth.prefix} ${auth.value}`.trim() : auth.value;
|
|
706
|
-
const location = auth.in ?? "header";
|
|
707
|
-
if (location === "query") {
|
|
708
|
-
if (request.params[auth.name] === void 0) request.params[auth.name] = value;
|
|
709
|
-
return request;
|
|
710
|
-
}
|
|
711
|
-
if (location === "cookie") {
|
|
712
|
-
this.appendCookie(request.headers, auth.name, value);
|
|
713
|
-
return request;
|
|
714
|
-
}
|
|
715
|
-
this.setHeaderIfMissing(request.headers, auth.name, value);
|
|
716
|
-
return request;
|
|
717
|
-
}
|
|
718
|
-
case "custom": return await auth.apply({
|
|
719
|
-
...request,
|
|
720
|
-
headers: { ...request.headers },
|
|
721
|
-
params: { ...request.params }
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
static setHeaderIfMissing(headers, name, value) {
|
|
726
|
-
if (!Object.keys(headers).find((header) => header.toLowerCase() === name.toLowerCase())) headers[name] = value;
|
|
727
|
-
}
|
|
728
|
-
static appendCookie(headers, name, value) {
|
|
729
|
-
const headerName = Object.keys(headers).find((header) => header.toLowerCase() === "cookie") ?? "Cookie";
|
|
730
|
-
const existingCookie = headers[headerName];
|
|
731
|
-
const cookieEntry = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
732
|
-
if (!existingCookie) {
|
|
733
|
-
headers[headerName] = cookieEntry;
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
if (!existingCookie.split(";").map((part) => part.trim()).some((part) => part.startsWith(`${encodeURIComponent(name)}=`))) headers[headerName] = `${existingCookie}; ${cookieEntry}`;
|
|
737
|
-
}
|
|
738
|
-
/**
|
|
739
|
-
* Create an HttpException from status and error
|
|
740
|
-
*
|
|
741
|
-
* @param status
|
|
742
|
-
* @param error
|
|
743
|
-
* @returns
|
|
744
|
-
*/
|
|
745
|
-
static exception(status, error, originalError) {
|
|
746
|
-
const exception = HttpException.fromCode(status, {
|
|
747
|
-
success: false,
|
|
748
|
-
message: `Request failed: ${error.error?.message || "An error occurred"}`,
|
|
749
|
-
status: "failed",
|
|
750
|
-
data: void 0,
|
|
751
|
-
meta: {},
|
|
752
|
-
error: {
|
|
753
|
-
type: ((typeof error.error === "string" ? error.error : error.error?.type) ?? "UNKNOWN_ERROR").toUpperCase(),
|
|
754
|
-
code: error.error?.code ?? "000000",
|
|
755
|
-
message: error.error?.message ?? error.error_description ?? error.message,
|
|
756
|
-
validation_errors: error.error?.validation_errors ?? []
|
|
757
|
-
}
|
|
758
|
-
}, originalError);
|
|
759
|
-
if (this.apiInstance) this.apiInstance.setLastException(exception);
|
|
760
|
-
return exception;
|
|
761
|
-
}
|
|
762
|
-
static toHeaderRecord = (headers) => {
|
|
763
|
-
return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key, String(value)]));
|
|
764
|
-
};
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
//#endregion
|
|
768
|
-
//#region src/Apis/BaseApi.ts
|
|
769
|
-
var BaseApi = class {
|
|
770
|
-
/**
|
|
771
|
-
* API Core instance for API bootstrapping and shared utilities
|
|
772
|
-
*/
|
|
773
|
-
#core;
|
|
774
|
-
lastException;
|
|
775
|
-
/**
|
|
776
|
-
* Create a BaseApi instance
|
|
777
|
-
*
|
|
778
|
-
* @param coreInstance Core instance
|
|
779
|
-
*/
|
|
780
|
-
constructor(coreInstance) {
|
|
781
|
-
this.#core = coreInstance;
|
|
782
|
-
}
|
|
783
|
-
/**
|
|
784
|
-
* Get the owning core instance for SDK-specific API bootstrapping.
|
|
785
|
-
*/
|
|
786
|
-
get core() {
|
|
787
|
-
return this.#core;
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Hook for SDK-specific API registration.
|
|
791
|
-
*/
|
|
792
|
-
boot() {}
|
|
793
|
-
/**
|
|
794
|
-
* Set access validator function
|
|
795
|
-
*
|
|
796
|
-
* @param validator
|
|
797
|
-
*/
|
|
798
|
-
setAccessValidator(validator) {
|
|
799
|
-
this.#core.setAccessValidator(validator);
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* Get the last exception
|
|
803
|
-
*
|
|
804
|
-
* @returns
|
|
805
|
-
*/
|
|
806
|
-
getLastException() {
|
|
807
|
-
return this.lastException;
|
|
808
|
-
}
|
|
809
|
-
/**
|
|
810
|
-
* Set the last exception
|
|
811
|
-
*
|
|
812
|
-
* @param exception
|
|
813
|
-
*/
|
|
814
|
-
setLastException(exception) {
|
|
815
|
-
this.lastException = exception;
|
|
816
|
-
}
|
|
817
|
-
/**
|
|
818
|
-
* Initialize BaseApi and its sub-APIs
|
|
819
|
-
*
|
|
820
|
-
* @param coreInstance Core instance
|
|
821
|
-
* @returns
|
|
822
|
-
*/
|
|
823
|
-
static initialize(coreInstance) {
|
|
824
|
-
Http.setDebugLevel(coreInstance.debugLevel);
|
|
825
|
-
const baseApi = new this(coreInstance);
|
|
826
|
-
Http.setApiInstance(baseApi);
|
|
827
|
-
baseApi.boot();
|
|
828
|
-
return baseApi;
|
|
829
|
-
}
|
|
830
|
-
};
|
|
831
|
-
|
|
832
|
-
//#endregion
|
|
833
|
-
//#region src/RuntimeSdk.ts
|
|
834
|
-
const createRuntimeApi = (core, bundle) => {
|
|
835
|
-
const api = BaseApi.initialize(core);
|
|
836
|
-
for (const group of bundle.manifest.groups) {
|
|
837
|
-
const namespace = {};
|
|
838
|
-
for (const operation of group.operations) namespace[operation.methodName] = async (...args) => {
|
|
839
|
-
await core.validateAccess();
|
|
840
|
-
const [pathParams, queryParams, body, headers] = normalizeRuntimeArguments(operation, args);
|
|
841
|
-
validateRequiredArguments(operation.pathParams, pathParams, "path");
|
|
842
|
-
validateRequiredArguments(operation.queryParams, queryParams, "query");
|
|
843
|
-
validateRequiredArguments(operation.headerParams, headers, "header");
|
|
844
|
-
if (operation.hasBody && operation.bodyRequired && body == null) throw new Error(`Missing required request body for ${operation.method} ${operation.path}`);
|
|
845
|
-
const { data } = await Http.send(core.builder.buildTargetUrl(operation.path, pathParams, queryParams), operation.method, body ?? {}, headers);
|
|
846
|
-
return data;
|
|
847
|
-
};
|
|
848
|
-
api[group.propertyName] = namespace;
|
|
849
|
-
}
|
|
850
|
-
return api;
|
|
851
|
-
};
|
|
852
|
-
const createSdk = (bundle, options) => {
|
|
853
|
-
return new Core(options).useDocument(bundle);
|
|
854
|
-
};
|
|
855
|
-
const normalizeRuntimeArguments = (operation, args) => {
|
|
856
|
-
let cursor = 0;
|
|
857
|
-
return [
|
|
858
|
-
operation.pathParams.length > 0 ? toRecord(args[cursor++]) : {},
|
|
859
|
-
operation.queryParams.length > 0 ? toRecord(args[cursor++]) : {},
|
|
860
|
-
operation.hasBody ? args[cursor++] : void 0,
|
|
861
|
-
operation.headerParams.length > 0 ? toRecord(args[cursor++]) : {}
|
|
862
|
-
];
|
|
863
|
-
};
|
|
864
|
-
const validateRequiredArguments = (parameters, values, location) => {
|
|
865
|
-
for (const parameter of parameters) {
|
|
866
|
-
if (!parameter.required) continue;
|
|
867
|
-
if (values[parameter.name] === void 0 && values[parameter.accessor] === void 0) throw new Error(`Missing required ${location} parameter: ${parameter.name}`);
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
const toRecord = (value) => {
|
|
871
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) return value;
|
|
872
|
-
return {};
|
|
873
|
-
};
|
|
874
|
-
|
|
875
|
-
//#endregion
|
|
876
|
-
//#region src/Core.ts
|
|
877
|
-
var Core = class Core {
|
|
878
|
-
static apiClass = BaseApi;
|
|
879
|
-
debugLevel = 0;
|
|
880
|
-
/**
|
|
881
|
-
* Client ID
|
|
882
|
-
*/
|
|
883
|
-
clientId;
|
|
884
|
-
/**
|
|
885
|
-
* Client Secret
|
|
886
|
-
*/
|
|
887
|
-
clientSecret;
|
|
888
|
-
/**
|
|
889
|
-
* API Environment
|
|
890
|
-
*/
|
|
891
|
-
environment = "live";
|
|
892
|
-
accessValidator;
|
|
893
|
-
/**
|
|
894
|
-
* API Instance
|
|
895
|
-
*/
|
|
896
|
-
api;
|
|
897
|
-
/**
|
|
898
|
-
* Builder Instance
|
|
899
|
-
*/
|
|
900
|
-
builder = Builder;
|
|
901
|
-
constructor(clientId, clientSecret, encryptionKey, env, config) {
|
|
902
|
-
const currentConfig = getConfig();
|
|
903
|
-
const resolvedConfig = clientId && typeof clientId === "object" ? this.resolveInitOptionsFromObject(clientId, currentConfig) : this.resolveInitOptionsFromArgs(clientId, clientSecret, encryptionKey, env, config, currentConfig);
|
|
904
|
-
this.clientId = Core.normalizeCredential(resolvedConfig.clientId);
|
|
905
|
-
this.clientSecret = Core.normalizeCredential(resolvedConfig.clientSecret);
|
|
906
|
-
this.environment = resolvedConfig.environment ?? Core.normalizeEnvironment(process.env.ENVIRONMENT) ?? "live";
|
|
907
|
-
this.configure({
|
|
908
|
-
...resolvedConfig,
|
|
909
|
-
environment: this.environment
|
|
910
|
-
});
|
|
911
|
-
this.debug(resolvedConfig.debugLevel ?? 0);
|
|
912
|
-
if (!this.clientSecret && !this.hasConfiguredAuth()) throw new Error("Client Secret is required to initialize API instance when auth is not provided");
|
|
913
|
-
this.api = this.createApi();
|
|
914
|
-
}
|
|
915
|
-
createApi() {
|
|
916
|
-
return (this.constructor.apiClass ?? BaseApi).initialize(this);
|
|
917
|
-
}
|
|
918
|
-
init(clientId, clientSecret, encryptionKey, env, config) {
|
|
919
|
-
return new this.constructor(clientId, clientSecret, encryptionKey, env, config);
|
|
920
|
-
}
|
|
921
|
-
configure(config) {
|
|
922
|
-
const nextConfig = updateConfig(config);
|
|
923
|
-
if (nextConfig.environment) {
|
|
924
|
-
this.environment = nextConfig.environment;
|
|
925
|
-
this.builder.setEnvironment(nextConfig.environment);
|
|
926
|
-
}
|
|
927
|
-
if ("clientId" in config) this.clientId = Core.normalizeCredential(nextConfig.clientId);
|
|
928
|
-
if ("clientSecret" in config) this.clientSecret = Core.normalizeCredential(nextConfig.clientSecret);
|
|
929
|
-
if (nextConfig.debugLevel !== void 0) this.debug(nextConfig.debugLevel);
|
|
930
|
-
return this;
|
|
931
|
-
}
|
|
932
|
-
/**
|
|
933
|
-
* Set the debug level
|
|
934
|
-
*
|
|
935
|
-
* @param level
|
|
936
|
-
* @returns
|
|
937
|
-
*/
|
|
938
|
-
debug(level = 0) {
|
|
939
|
-
this.debugLevel = level;
|
|
940
|
-
Http.setDebugLevel(level);
|
|
941
|
-
return this;
|
|
942
|
-
}
|
|
943
|
-
/**
|
|
944
|
-
* Get the current environment
|
|
945
|
-
*
|
|
946
|
-
* @returns
|
|
947
|
-
*/
|
|
948
|
-
getEnvironment() {
|
|
949
|
-
return this.environment;
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* Get the configured client identifier.
|
|
953
|
-
*/
|
|
954
|
-
getClientId() {
|
|
955
|
-
return this.clientId;
|
|
956
|
-
}
|
|
957
|
-
/**
|
|
958
|
-
* Get the configured client secret.
|
|
959
|
-
*/
|
|
960
|
-
getClientSecret() {
|
|
961
|
-
return this.clientSecret;
|
|
962
|
-
}
|
|
963
|
-
/**
|
|
964
|
-
* Get the current shared SDK config.
|
|
965
|
-
*/
|
|
966
|
-
getConfig() {
|
|
967
|
-
return getConfig();
|
|
968
|
-
}
|
|
969
|
-
/**
|
|
970
|
-
* Replace the active auth strategy.
|
|
971
|
-
*/
|
|
972
|
-
setAuth(auth) {
|
|
973
|
-
return this.configure({ auth });
|
|
974
|
-
}
|
|
975
|
-
/**
|
|
976
|
-
* Clear any configured auth strategy.
|
|
977
|
-
*/
|
|
978
|
-
clearAuth() {
|
|
979
|
-
Http.clearAuth();
|
|
980
|
-
return this;
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* Set access validator function
|
|
984
|
-
*
|
|
985
|
-
* @param validator Function to validate access
|
|
986
|
-
*/
|
|
987
|
-
setAccessValidator(validator) {
|
|
988
|
-
this.accessValidator = validator;
|
|
989
|
-
return this;
|
|
990
|
-
}
|
|
991
|
-
/**
|
|
992
|
-
* Validates access using the provided access validator function
|
|
993
|
-
*
|
|
994
|
-
* @throws Error if validation fails
|
|
995
|
-
*/
|
|
996
|
-
async validateAccess() {
|
|
997
|
-
const check = this.accessValidator ? await this.accessValidator(this) : true;
|
|
998
|
-
if (check === true || check == null) return;
|
|
999
|
-
if (this.isAuthConfigOrArray(check)) {
|
|
1000
|
-
this.setAuth(check);
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
if (this.isConfigUpdate(check)) {
|
|
1004
|
-
this.configure(check);
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
|
-
throw new Error(typeof check === "string" ? check : "Access validation failed");
|
|
1008
|
-
}
|
|
1009
|
-
/**
|
|
1010
|
-
* Use a manifest bundle to create the API instance
|
|
1011
|
-
*
|
|
1012
|
-
* @param bundle
|
|
1013
|
-
* @returns
|
|
1014
|
-
*/
|
|
1015
|
-
useDocument(bundle) {
|
|
1016
|
-
this.api = createRuntimeApi(this, bundle);
|
|
1017
|
-
return this;
|
|
1018
|
-
}
|
|
1019
|
-
/**
|
|
1020
|
-
* Use a manifest bundle to create the API instance (alias for useDocument).
|
|
1021
|
-
*
|
|
1022
|
-
* @param bundle
|
|
1023
|
-
* @returns
|
|
1024
|
-
*/
|
|
1025
|
-
useSdk(bundle) {
|
|
1026
|
-
return this.useDocument(bundle);
|
|
1027
|
-
}
|
|
1028
|
-
static normalizeEnvironment = (value) => {
|
|
1029
|
-
if (value === "live" || value === "sandbox") return value;
|
|
1030
|
-
};
|
|
1031
|
-
static normalizeCredential(value) {
|
|
1032
|
-
if (typeof value !== "string") return;
|
|
1033
|
-
const normalized = value.trim();
|
|
1034
|
-
return normalized ? normalized : void 0;
|
|
1035
|
-
}
|
|
1036
|
-
resolveInitOptionsFromObject(config, currentConfig) {
|
|
1037
|
-
return {
|
|
1038
|
-
...currentConfig,
|
|
1039
|
-
...config,
|
|
1040
|
-
clientId: Core.normalizeCredential(config.clientId) ?? Core.normalizeCredential(currentConfig.clientId) ?? Core.normalizeCredential(process.env.CLIENT_ID),
|
|
1041
|
-
clientSecret: Core.normalizeCredential(config.clientSecret) ?? Core.normalizeCredential(currentConfig.clientSecret) ?? Core.normalizeCredential(process.env.CLIENT_SECRET),
|
|
1042
|
-
environment: config.environment ?? currentConfig.environment ?? Core.normalizeEnvironment(process.env.ENVIRONMENT) ?? "live",
|
|
1043
|
-
encryptionKey: config.encryptionKey ?? currentConfig.encryptionKey,
|
|
1044
|
-
urls: config.urls ?? currentConfig.urls,
|
|
1045
|
-
headers: config.headers ?? currentConfig.headers,
|
|
1046
|
-
timeout: config.timeout ?? currentConfig.timeout,
|
|
1047
|
-
auth: config.auth ?? currentConfig.auth,
|
|
1048
|
-
debugLevel: config.debugLevel ?? currentConfig.debugLevel ?? 0
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
resolveInitOptionsFromArgs(clientId, clientSecret, encryptionKey, env, config, currentConfig) {
|
|
1052
|
-
return {
|
|
1053
|
-
...currentConfig,
|
|
1054
|
-
...config ?? {},
|
|
1055
|
-
clientId: Core.normalizeCredential(clientId) ?? Core.normalizeCredential(currentConfig.clientId) ?? Core.normalizeCredential(process.env.CLIENT_ID),
|
|
1056
|
-
clientSecret: Core.normalizeCredential(clientSecret) ?? Core.normalizeCredential(currentConfig.clientSecret) ?? Core.normalizeCredential(process.env.CLIENT_SECRET),
|
|
1057
|
-
environment: env ?? config?.environment ?? currentConfig.environment ?? Core.normalizeEnvironment(process.env.ENVIRONMENT) ?? "live",
|
|
1058
|
-
encryptionKey: encryptionKey ?? config?.encryptionKey ?? currentConfig.encryptionKey,
|
|
1059
|
-
urls: config?.urls ?? currentConfig.urls,
|
|
1060
|
-
headers: config?.headers ?? currentConfig.headers,
|
|
1061
|
-
timeout: config?.timeout ?? currentConfig.timeout,
|
|
1062
|
-
auth: config?.auth ?? currentConfig.auth,
|
|
1063
|
-
debugLevel: config?.debugLevel ?? currentConfig.debugLevel ?? 0
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
hasConfiguredAuth() {
|
|
1067
|
-
const auth = getConfig().auth;
|
|
1068
|
-
if (Array.isArray(auth)) return auth.length > 0;
|
|
1069
|
-
return auth != null;
|
|
1070
|
-
}
|
|
1071
|
-
isAuthConfigOrArray(value) {
|
|
1072
|
-
if (Array.isArray(value)) return value.every((entry) => this.isAuthConfig(entry));
|
|
1073
|
-
return this.isAuthConfig(value);
|
|
1074
|
-
}
|
|
1075
|
-
isAuthConfig(value) {
|
|
1076
|
-
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
|
|
1077
|
-
}
|
|
1078
|
-
isConfigUpdate(value) {
|
|
1079
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1080
|
-
return [
|
|
1081
|
-
"auth",
|
|
1082
|
-
"clientId",
|
|
1083
|
-
"clientSecret",
|
|
1084
|
-
"debugLevel",
|
|
1085
|
-
"environment",
|
|
1086
|
-
"headers",
|
|
1087
|
-
"timeout",
|
|
1088
|
-
"urls",
|
|
1089
|
-
"encryptionKey"
|
|
1090
|
-
].some((key) => key in value);
|
|
1091
|
-
}
|
|
1092
|
-
};
|
|
1093
|
-
|
|
1094
|
-
//#endregion
|
|
1095
|
-
//#region src/utilities/AuthCache.ts
|
|
1096
|
-
/**
|
|
1097
|
-
* Cache any auth payload returned from a loader until it expires.
|
|
1098
|
-
*/
|
|
1099
|
-
const createAuthCache = (loader) => {
|
|
1100
|
-
let cached;
|
|
1101
|
-
return async (core) => {
|
|
1102
|
-
if (cached && !isExpired(cached.expiresAt)) return cached.auth;
|
|
1103
|
-
cached = await loader(core);
|
|
1104
|
-
return cached.auth;
|
|
1105
|
-
};
|
|
1106
|
-
};
|
|
1107
|
-
/**
|
|
1108
|
-
* Cache bearer or oauth-style access tokens returned from a loader until expiry.
|
|
1109
|
-
*/
|
|
1110
|
-
const createAccessTokenCache = (loader) => {
|
|
1111
|
-
return createAuthCache(async (core) => {
|
|
1112
|
-
const token = await loader(core);
|
|
1113
|
-
const expiresAt = token.expiresAt ?? (typeof token.expiresInMs === "number" ? Date.now() + token.expiresInMs : typeof token.expiresInSeconds === "number" ? Date.now() + token.expiresInSeconds * 1e3 : void 0);
|
|
1114
|
-
return {
|
|
1115
|
-
auth: {
|
|
1116
|
-
type: "oauth2",
|
|
1117
|
-
accessToken: token.token,
|
|
1118
|
-
tokenType: token.tokenType ?? "Bearer"
|
|
1119
|
-
},
|
|
1120
|
-
expiresAt
|
|
1121
|
-
};
|
|
1122
|
-
});
|
|
1123
|
-
};
|
|
1124
|
-
const isExpired = (expiresAt) => {
|
|
1125
|
-
return typeof expiresAt === "number" && expiresAt <= Date.now();
|
|
1126
|
-
};
|
|
1127
|
-
|
|
1128
|
-
//#endregion
|
|
1129
|
-
//#region src/utilities/WebhookValidator.ts
|
|
1130
|
-
var WebhookValidator = class {
|
|
1131
|
-
algorithm = "sha256";
|
|
1132
|
-
encoding = "base64";
|
|
1133
|
-
/**
|
|
1134
|
-
* @param secretHash
|
|
1135
|
-
* @param options
|
|
1136
|
-
*/
|
|
1137
|
-
constructor(secretHash, options) {
|
|
1138
|
-
this.secretHash = secretHash;
|
|
1139
|
-
this.algorithm = options?.hashAlgorithm || "sha256";
|
|
1140
|
-
this.encoding = options?.encoding || "base64";
|
|
1141
|
-
if (!this.secretHash || this.secretHash.length === 0) this.secretHash = process.env.SECRET_HASH;
|
|
1142
|
-
}
|
|
1143
|
-
/**
|
|
1144
|
-
* Validate webhook signature
|
|
1145
|
-
* @param rawBody - Raw request body as string
|
|
1146
|
-
* @param signature - Signature from request header
|
|
1147
|
-
* @returns {boolean} - True if signature is valid
|
|
1148
|
-
*/
|
|
1149
|
-
validate(rawBody, signature) {
|
|
1150
|
-
if (!this.secretHash) throw new Error("Secret hash is required for validation");
|
|
1151
|
-
return crypto.default.createHmac(this.algorithm, this.secretHash).update(rawBody).digest(this.encoding) === signature;
|
|
1152
|
-
}
|
|
1153
|
-
/**
|
|
1154
|
-
* Generate signature for testing/verification
|
|
1155
|
-
* @param rawBody - Raw request body as string
|
|
1156
|
-
* @returns {string} - Generated signature
|
|
1157
|
-
*/
|
|
1158
|
-
generateSignature(rawBody) {
|
|
1159
|
-
if (!this.secretHash) throw new Error("Secret hash is required to generate signature");
|
|
1160
|
-
return crypto.default.createHmac(this.algorithm, this.secretHash).update(rawBody).digest(this.encoding);
|
|
1161
|
-
}
|
|
1162
|
-
/**
|
|
1163
|
-
* Async version of validate (for large payloads)
|
|
1164
|
-
*
|
|
1165
|
-
* @param rawBody
|
|
1166
|
-
* @param signature
|
|
1167
|
-
* @returns {Promise<boolean>}
|
|
1168
|
-
*/
|
|
1169
|
-
validateAsync(rawBody, signature) {
|
|
1170
|
-
if (!this.secretHash) throw new Error("Secret hash is required for validation");
|
|
1171
|
-
const hmac = crypto.default.createHmac(this.algorithm, this.secretHash);
|
|
1172
|
-
hmac.update(rawBody);
|
|
1173
|
-
return hmac.digest(this.encoding) === signature;
|
|
1174
|
-
}
|
|
1175
|
-
/**
|
|
1176
|
-
* Get current configuration
|
|
1177
|
-
*/
|
|
1178
|
-
getConfig() {
|
|
1179
|
-
return {
|
|
1180
|
-
algorithm: this.algorithm,
|
|
1181
|
-
encoding: this.encoding,
|
|
1182
|
-
secretHashLength: this.secretHash?.length
|
|
1183
|
-
};
|
|
1184
|
-
}
|
|
1185
|
-
};
|
|
1186
|
-
|
|
1187
|
-
//#endregion
|
|
1188
|
-
exports.BadRequestException = BadRequestException;
|
|
1189
|
-
exports.BaseApi = BaseApi;
|
|
1190
|
-
exports.Builder = Builder;
|
|
1191
|
-
exports.Core = Core;
|
|
1192
|
-
exports.ForbiddenRequestException = ForbiddenRequestException;
|
|
1193
|
-
exports.Http = Http;
|
|
1194
|
-
exports.HttpException = HttpException;
|
|
1195
|
-
exports.UnauthorizedRequestException = UnauthorizedRequestException;
|
|
1196
|
-
exports.WebhookValidator = WebhookValidator;
|
|
1197
|
-
exports.buildUrl = buildUrl;
|
|
1198
|
-
exports.createAccessTokenCache = createAccessTokenCache;
|
|
1199
|
-
exports.createAuthCache = createAuthCache;
|
|
1200
|
-
exports.createDefaultConfig = createDefaultConfig;
|
|
1201
|
-
exports.createRuntimeApi = createRuntimeApi;
|
|
1202
|
-
exports.createSdk = createSdk;
|
|
1203
|
-
exports.defaultConfig = defaultConfig;
|
|
1204
|
-
exports.defineConfig = defineConfig;
|
|
1205
|
-
exports.getConfig = getConfig;
|
|
1206
|
-
Object.defineProperty(exports, 'globalConfig', {
|
|
1207
|
-
enumerable: true,
|
|
1208
|
-
get: function () {
|
|
1209
|
-
return globalConfig;
|
|
1210
|
-
}
|
|
1211
|
-
});
|
|
1212
|
-
exports.loadUserConfig = loadUserConfig;
|
|
1213
|
-
exports.mergeConfig = mergeConfig;
|
|
1214
|
-
exports.normalizeValue = normalizeValue;
|
|
1215
|
-
exports.resetConfig = resetConfig;
|
|
1216
|
-
exports.updateConfig = updateConfig;
|
|
File without changes
|
|
File without changes
|