@centia-io/sdk 0.0.27 → 0.0.28
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/LICENSE +21 -0
- package/dist/centia-io-sdk.cjs +588 -0
- package/dist/centia-io-sdk.d.cts +243 -0
- package/dist/centia-io-sdk.d.cts.map +1 -0
- package/dist/{index.d.ts → centia-io-sdk.d.ts} +1 -1
- package/dist/centia-io-sdk.d.ts.map +1 -0
- package/dist/{index.js → centia-io-sdk.js} +1 -1
- package/dist/centia-io-sdk.js.map +1 -0
- package/dist/centia-io-sdk.umd.js +594 -0
- package/package.json +12 -8
- package/build/centia-io-sdk.js +0 -12
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 MapCentia ApS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/util/jwt-decode.ts
|
|
3
|
+
var InvalidTokenError = class extends Error {};
|
|
4
|
+
InvalidTokenError.prototype.name = "InvalidTokenError";
|
|
5
|
+
function b64DecodeUnicode(str) {
|
|
6
|
+
return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {
|
|
7
|
+
let code = p.charCodeAt(0).toString(16).toUpperCase();
|
|
8
|
+
if (code.length < 2) code = "0" + code;
|
|
9
|
+
return "%" + code;
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
function base64UrlDecode(str) {
|
|
13
|
+
let output = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
14
|
+
switch (output.length % 4) {
|
|
15
|
+
case 0: break;
|
|
16
|
+
case 2:
|
|
17
|
+
output += "==";
|
|
18
|
+
break;
|
|
19
|
+
case 3:
|
|
20
|
+
output += "=";
|
|
21
|
+
break;
|
|
22
|
+
default: throw new Error("base64 string is not of the correct length");
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
return b64DecodeUnicode(output);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
return atob(output);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function jwtDecode(token, options) {
|
|
31
|
+
if (typeof token !== "string") throw new InvalidTokenError("Invalid token specified: must be a string");
|
|
32
|
+
options ||= {};
|
|
33
|
+
const pos = options.header === true ? 0 : 1;
|
|
34
|
+
const part = token.split(".")[pos];
|
|
35
|
+
if (typeof part !== "string") throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);
|
|
36
|
+
let decoded;
|
|
37
|
+
try {
|
|
38
|
+
decoded = base64UrlDecode(part);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(decoded);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/util/storage.ts
|
|
51
|
+
var MemoryStorage = class {
|
|
52
|
+
constructor() {
|
|
53
|
+
this.store = /* @__PURE__ */ new Map();
|
|
54
|
+
}
|
|
55
|
+
getItem(key) {
|
|
56
|
+
return this.store.has(key) ? this.store.get(key) : null;
|
|
57
|
+
}
|
|
58
|
+
setItem(key, value) {
|
|
59
|
+
this.store.set(key, String(value));
|
|
60
|
+
}
|
|
61
|
+
removeItem(key) {
|
|
62
|
+
this.store.delete(key);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
let cached = null;
|
|
66
|
+
function getStorage() {
|
|
67
|
+
if (cached) return cached;
|
|
68
|
+
try {
|
|
69
|
+
const g$1 = typeof globalThis !== "undefined" ? globalThis : window;
|
|
70
|
+
if (g$1 && g$1.localStorage && typeof g$1.localStorage.getItem === "function") {
|
|
71
|
+
cached = g$1.localStorage;
|
|
72
|
+
return cached;
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {}
|
|
75
|
+
const g = typeof globalThis !== "undefined" ? globalThis : {};
|
|
76
|
+
if (!g.__gc2_memory_storage) g.__gc2_memory_storage = new MemoryStorage();
|
|
77
|
+
cached = g.__gc2_memory_storage;
|
|
78
|
+
return cached;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/util/utils.ts
|
|
83
|
+
const generatePkceChallenge = async () => {
|
|
84
|
+
const generateRandomString = () => {
|
|
85
|
+
const array = new Uint32Array(28);
|
|
86
|
+
crypto.getRandomValues(array);
|
|
87
|
+
return Array.from(array, (dec) => ("0" + dec.toString(16)).substr(-2)).join("");
|
|
88
|
+
};
|
|
89
|
+
const sha256 = (plain) => {
|
|
90
|
+
const data = new TextEncoder().encode(plain);
|
|
91
|
+
return crypto.subtle.digest("SHA-256", data);
|
|
92
|
+
};
|
|
93
|
+
const base64urlEncode = (str) => {
|
|
94
|
+
return btoa(String.fromCharCode.apply(null, [...new Uint8Array(str)])).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
95
|
+
};
|
|
96
|
+
async function pkceChallengeFromVerifier(v) {
|
|
97
|
+
return base64urlEncode(await sha256(v));
|
|
98
|
+
}
|
|
99
|
+
const { state, codeVerifier } = {
|
|
100
|
+
state: generateRandomString(),
|
|
101
|
+
codeVerifier: generateRandomString()
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
state,
|
|
105
|
+
codeVerifier,
|
|
106
|
+
codeChallenge: await pkceChallengeFromVerifier(codeVerifier)
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
const isTokenExpired = (token) => {
|
|
110
|
+
let isJwtExpired = false;
|
|
111
|
+
const { exp } = jwtDecode(token);
|
|
112
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
113
|
+
if (exp) {
|
|
114
|
+
if (currentTime > exp) isJwtExpired = true;
|
|
115
|
+
}
|
|
116
|
+
return isJwtExpired;
|
|
117
|
+
};
|
|
118
|
+
const claims = (token) => {
|
|
119
|
+
return jwtDecode(token);
|
|
120
|
+
};
|
|
121
|
+
const isLogin = async (gc2) => {
|
|
122
|
+
const { accessToken, refreshToken } = getTokens();
|
|
123
|
+
if (!accessToken && !refreshToken) return false;
|
|
124
|
+
if (!accessToken || accessToken && isTokenExpired(accessToken)) {
|
|
125
|
+
if (refreshToken && isTokenExpired(refreshToken)) {
|
|
126
|
+
clearTokens();
|
|
127
|
+
clearOptions();
|
|
128
|
+
throw new Error("Refresh token has expired. Please login again.");
|
|
129
|
+
}
|
|
130
|
+
if (refreshToken) try {
|
|
131
|
+
const data = await gc2.getRefreshToken(refreshToken);
|
|
132
|
+
setTokens({
|
|
133
|
+
accessToken: data.access_token,
|
|
134
|
+
refreshToken,
|
|
135
|
+
idToken: data?.id_token
|
|
136
|
+
});
|
|
137
|
+
console.log("Access token refreshed");
|
|
138
|
+
} catch (e) {
|
|
139
|
+
throw new Error("Could not get refresh token.");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
};
|
|
144
|
+
const setTokens = (tokens) => {
|
|
145
|
+
getStorage().setItem("gc2_tokens", JSON.stringify({
|
|
146
|
+
"accessToken": tokens.accessToken,
|
|
147
|
+
"refreshToken": tokens.refreshToken,
|
|
148
|
+
"idToken": tokens?.idToken || ""
|
|
149
|
+
}));
|
|
150
|
+
};
|
|
151
|
+
const getTokens = () => {
|
|
152
|
+
const str = getStorage().getItem("gc2_tokens");
|
|
153
|
+
const tokens = str ? JSON.parse(str) : {};
|
|
154
|
+
return {
|
|
155
|
+
accessToken: tokens?.accessToken || "",
|
|
156
|
+
refreshToken: tokens?.refreshToken || "",
|
|
157
|
+
idToken: tokens?.idToken || ""
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
const setOptions = (options) => {
|
|
161
|
+
getStorage().setItem("gc2_options", JSON.stringify({
|
|
162
|
+
"clientId": options.clientId,
|
|
163
|
+
"host": options.host,
|
|
164
|
+
"redirectUri": options.redirectUri
|
|
165
|
+
}));
|
|
166
|
+
};
|
|
167
|
+
const getOptions = () => {
|
|
168
|
+
const str = getStorage().getItem("gc2_options");
|
|
169
|
+
const options = str ? JSON.parse(str) : {};
|
|
170
|
+
return {
|
|
171
|
+
clientId: options?.clientId || "",
|
|
172
|
+
host: options?.host || "",
|
|
173
|
+
redirectUri: options?.redirectUri || ""
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
const clearTokens = () => {
|
|
177
|
+
getStorage().removeItem("gc2_tokens");
|
|
178
|
+
};
|
|
179
|
+
const clearOptions = () => {
|
|
180
|
+
getStorage().removeItem("gc2_options");
|
|
181
|
+
};
|
|
182
|
+
const getNonce = () => {
|
|
183
|
+
return getStorage().getItem("gc2_nonce");
|
|
184
|
+
};
|
|
185
|
+
const clearNonce = () => {
|
|
186
|
+
getStorage().removeItem("gc2_nonce");
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/services/gc2.services.ts
|
|
191
|
+
var Gc2Service = class {
|
|
192
|
+
constructor(options) {
|
|
193
|
+
this.options = options;
|
|
194
|
+
this.host = options.host;
|
|
195
|
+
}
|
|
196
|
+
isCodeFlowOptions(options) {
|
|
197
|
+
return "redirectUri" in options;
|
|
198
|
+
}
|
|
199
|
+
isPasswordFlowOptions(options) {
|
|
200
|
+
return "username" in options;
|
|
201
|
+
}
|
|
202
|
+
buildUrl(path) {
|
|
203
|
+
if (path.startsWith("http://") || path.startsWith("https://")) return path;
|
|
204
|
+
return `${this.host}${path}`;
|
|
205
|
+
}
|
|
206
|
+
async request(url, method, body, contentType = "application/json") {
|
|
207
|
+
const headers = { "Content-Type": contentType };
|
|
208
|
+
let payload;
|
|
209
|
+
if (contentType === "application/json") payload = JSON.stringify(body);
|
|
210
|
+
else payload = new URLSearchParams(body).toString();
|
|
211
|
+
const response = await fetch(url, {
|
|
212
|
+
method,
|
|
213
|
+
headers,
|
|
214
|
+
body: payload
|
|
215
|
+
});
|
|
216
|
+
if (!response.ok) {
|
|
217
|
+
const errText = await response.text();
|
|
218
|
+
throw new Error(`HTTP error ${response.status}: ${errText}`);
|
|
219
|
+
}
|
|
220
|
+
return response.json();
|
|
221
|
+
}
|
|
222
|
+
async getDeviceCode() {
|
|
223
|
+
const path = this.options.deviceUri ?? `${this.host}/api/v4/oauth/device`;
|
|
224
|
+
return this.request(this.buildUrl(path), "POST", { client_id: this.options.clientId });
|
|
225
|
+
}
|
|
226
|
+
async pollToken(deviceCode, interval) {
|
|
227
|
+
const path = this.options.tokenUri ?? `${this.host}/api/v4/oauth`;
|
|
228
|
+
const getToken = async () => {
|
|
229
|
+
try {
|
|
230
|
+
return await this.request(this.buildUrl(path), "POST", {
|
|
231
|
+
client_id: this.options.clientId,
|
|
232
|
+
device_code: deviceCode,
|
|
233
|
+
grant_type: "device_code"
|
|
234
|
+
});
|
|
235
|
+
} catch (e) {
|
|
236
|
+
const err = JSON.parse(e.message.split(": ")[1]);
|
|
237
|
+
if (err.error === "authorization_pending") return null;
|
|
238
|
+
return err.error_description;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
let response = await getToken();
|
|
242
|
+
while (response === null) {
|
|
243
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1100));
|
|
244
|
+
response = await getToken();
|
|
245
|
+
}
|
|
246
|
+
if (typeof response === "string") throw new Error(response);
|
|
247
|
+
return response;
|
|
248
|
+
}
|
|
249
|
+
getAuthorizationCodeURL(codeChallenge, state) {
|
|
250
|
+
let redirectUri;
|
|
251
|
+
if (this.isCodeFlowOptions(this.options)) redirectUri = this.options.redirectUri;
|
|
252
|
+
else throw new Error("CodeFlow options required for this operation");
|
|
253
|
+
const base = this.options.authUri ?? `${this.host}/auth/`;
|
|
254
|
+
const params = new URLSearchParams();
|
|
255
|
+
const nonce = getNonce();
|
|
256
|
+
params.set("response_type", "code");
|
|
257
|
+
params.set("client_id", this.options.clientId);
|
|
258
|
+
params.set("redirect_uri", redirectUri);
|
|
259
|
+
params.set("state", state);
|
|
260
|
+
params.set("code_challenge", codeChallenge);
|
|
261
|
+
params.set("code_challenge_method", "S256");
|
|
262
|
+
if (nonce) params.set("nonce", nonce);
|
|
263
|
+
if (this.options.scope) params.set("scope", this.options.scope);
|
|
264
|
+
return `${base}?${params.toString()}`;
|
|
265
|
+
}
|
|
266
|
+
async getAuthorizationCodeToken(code, codeVerifier) {
|
|
267
|
+
let redirectUri;
|
|
268
|
+
if (this.isCodeFlowOptions(this.options)) redirectUri = this.options.redirectUri;
|
|
269
|
+
else throw new Error("CodeFlow options required for this operation");
|
|
270
|
+
const path = this.options.tokenUri ?? `${this.host}/api/v4/oauth`;
|
|
271
|
+
return this.request(this.buildUrl(path), "POST", {
|
|
272
|
+
client_id: this.options.clientId,
|
|
273
|
+
redirect_uri: redirectUri,
|
|
274
|
+
grant_type: "authorization_code",
|
|
275
|
+
code,
|
|
276
|
+
code_verifier: codeVerifier
|
|
277
|
+
}, "application/x-www-form-urlencoded");
|
|
278
|
+
}
|
|
279
|
+
async getPasswordToken() {
|
|
280
|
+
let username, password, database;
|
|
281
|
+
if (this.isPasswordFlowOptions(this.options)) {
|
|
282
|
+
username = this.options.username;
|
|
283
|
+
password = this.options.password;
|
|
284
|
+
database = this.options.database;
|
|
285
|
+
} else throw new Error("PasswordFlow options required for this operation");
|
|
286
|
+
const path = `${this.host}/api/v4/oauth`;
|
|
287
|
+
return this.request(this.buildUrl(path), "POST", {
|
|
288
|
+
client_id: this.options.clientId,
|
|
289
|
+
grant_type: "password",
|
|
290
|
+
username,
|
|
291
|
+
password,
|
|
292
|
+
database
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
async getRefreshToken(token) {
|
|
296
|
+
const path = this.options.tokenUri ?? `${this.host}/api/v4/oauth`;
|
|
297
|
+
return this.request(this.buildUrl(path), "POST", {
|
|
298
|
+
client_id: this.options.clientId,
|
|
299
|
+
grant_type: "refresh_token",
|
|
300
|
+
refresh_token: token
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
getSignOutURL() {
|
|
304
|
+
let redirectUri;
|
|
305
|
+
if (this.isCodeFlowOptions(this.options)) redirectUri = this.options.redirectUri;
|
|
306
|
+
else throw new Error("CodeFlow options required for this operation");
|
|
307
|
+
const params = new URLSearchParams({ redirect_uri: redirectUri });
|
|
308
|
+
return this.options.logoutUri ?? `${this.host}/signout?${params.toString()}`;
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
//#endregion
|
|
313
|
+
//#region src/CodeFlow.ts
|
|
314
|
+
var CodeFlow = class {
|
|
315
|
+
constructor(options) {
|
|
316
|
+
this.options = options;
|
|
317
|
+
this.service = new Gc2Service(options);
|
|
318
|
+
}
|
|
319
|
+
async redirectHandle() {
|
|
320
|
+
const url = window.location.search;
|
|
321
|
+
const queryParams = new URLSearchParams(url);
|
|
322
|
+
if (queryParams.get("error")) throw new Error(`Failed to redirect: ${url}`);
|
|
323
|
+
const code = queryParams.get("code");
|
|
324
|
+
if (code) {
|
|
325
|
+
if (queryParams.get("state") !== getStorage().getItem("state")) throw new Error("Possible CSRF attack. Aborting login!");
|
|
326
|
+
try {
|
|
327
|
+
const { access_token, refresh_token, id_token } = await this.service.getAuthorizationCodeToken(code, getStorage().getItem("codeVerifier"));
|
|
328
|
+
setTokens({
|
|
329
|
+
accessToken: access_token,
|
|
330
|
+
refreshToken: refresh_token,
|
|
331
|
+
idToken: id_token
|
|
332
|
+
});
|
|
333
|
+
setOptions({
|
|
334
|
+
clientId: this.options.clientId,
|
|
335
|
+
host: this.options.host,
|
|
336
|
+
redirectUri: this.options.redirectUri
|
|
337
|
+
});
|
|
338
|
+
getStorage().removeItem("state");
|
|
339
|
+
getStorage().removeItem("codeVerifier");
|
|
340
|
+
const params = new URLSearchParams(window.location.search);
|
|
341
|
+
params.delete("code");
|
|
342
|
+
params.delete("state");
|
|
343
|
+
const loc = window.location;
|
|
344
|
+
const newUrl = loc.origin + loc.pathname + (params.size > 0 ? "?" + params.toString() : "");
|
|
345
|
+
history.pushState(null, "", newUrl);
|
|
346
|
+
return Promise.resolve(true);
|
|
347
|
+
} catch (e) {
|
|
348
|
+
throw new Error(e.message);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return await isLogin(this.service);
|
|
352
|
+
}
|
|
353
|
+
async signIn() {
|
|
354
|
+
const { state, codeVerifier, codeChallenge } = await generatePkceChallenge();
|
|
355
|
+
getStorage().setItem("state", state);
|
|
356
|
+
getStorage().setItem("codeVerifier", codeVerifier);
|
|
357
|
+
window.location = this.service.getAuthorizationCodeURL(codeChallenge, state);
|
|
358
|
+
}
|
|
359
|
+
signOut() {
|
|
360
|
+
this.clear();
|
|
361
|
+
window.location = this.service.getSignOutURL();
|
|
362
|
+
}
|
|
363
|
+
clear() {
|
|
364
|
+
clearTokens();
|
|
365
|
+
clearOptions();
|
|
366
|
+
clearNonce();
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region src/PasswordFlow.ts
|
|
372
|
+
var PasswordFlow = class {
|
|
373
|
+
constructor(options) {
|
|
374
|
+
this.options = options;
|
|
375
|
+
this.service = new Gc2Service(options);
|
|
376
|
+
}
|
|
377
|
+
async signIn() {
|
|
378
|
+
const { access_token, refresh_token } = await this.service.getPasswordToken();
|
|
379
|
+
setTokens({
|
|
380
|
+
accessToken: access_token,
|
|
381
|
+
refreshToken: refresh_token
|
|
382
|
+
});
|
|
383
|
+
setOptions({
|
|
384
|
+
clientId: this.options.clientId,
|
|
385
|
+
host: this.options.host,
|
|
386
|
+
redirectUri: ""
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
signOut() {
|
|
390
|
+
this.clear();
|
|
391
|
+
}
|
|
392
|
+
clear() {
|
|
393
|
+
clearTokens();
|
|
394
|
+
clearOptions();
|
|
395
|
+
clearNonce();
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
//#endregion
|
|
400
|
+
//#region src/util/request-headers.ts
|
|
401
|
+
const getHeaders = async (contentType = "application/json") => {
|
|
402
|
+
if (!await isLogin(new Gc2Service(getOptions()))) return Promise.reject("Is not logged in");
|
|
403
|
+
const { accessToken } = getTokens();
|
|
404
|
+
const headers = {
|
|
405
|
+
Accept: "application/json",
|
|
406
|
+
Cookie: "XDEBUG_SESSION=XDEBUG_ECLIPSE",
|
|
407
|
+
Authorization: accessToken ? "Bearer " + accessToken : null
|
|
408
|
+
};
|
|
409
|
+
if (contentType) headers["Content-Type"] = contentType;
|
|
410
|
+
return headers;
|
|
411
|
+
};
|
|
412
|
+
var request_headers_default = getHeaders;
|
|
413
|
+
|
|
414
|
+
//#endregion
|
|
415
|
+
//#region src/util/make-request.ts
|
|
416
|
+
const make = async (version, resource, method, payload, contentType = "application/json") => {
|
|
417
|
+
const options = getOptions();
|
|
418
|
+
let request = {
|
|
419
|
+
method,
|
|
420
|
+
headers: await request_headers_default(contentType),
|
|
421
|
+
redirect: "manual"
|
|
422
|
+
};
|
|
423
|
+
if (payload) request.body = contentType === "application/json" ? JSON.stringify(payload) : payload;
|
|
424
|
+
return await fetch(options.host + `/api/v${version}/${resource}`, request);
|
|
425
|
+
};
|
|
426
|
+
var make_request_default = make;
|
|
427
|
+
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/util/get-response.ts
|
|
430
|
+
const get = async (response, expectedCode) => {
|
|
431
|
+
let res = null;
|
|
432
|
+
let bodyText = "";
|
|
433
|
+
try {
|
|
434
|
+
bodyText = await response.text();
|
|
435
|
+
} catch (e) {}
|
|
436
|
+
if (bodyText) try {
|
|
437
|
+
res = JSON.parse(bodyText);
|
|
438
|
+
} catch (e) {}
|
|
439
|
+
if (response.status !== expectedCode) {
|
|
440
|
+
const msg = res && (res.message || res.error) || bodyText || `Unexpected status ${response.status}`;
|
|
441
|
+
throw new Error(msg);
|
|
442
|
+
}
|
|
443
|
+
return res;
|
|
444
|
+
};
|
|
445
|
+
var get_response_default = get;
|
|
446
|
+
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region src/Sql.ts
|
|
449
|
+
var Sql = class {
|
|
450
|
+
async exec(request) {
|
|
451
|
+
return await get_response_default(await make_request_default("4", `sql`, "POST", request), 200);
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
//#endregion
|
|
456
|
+
//#region src/Rpc.ts
|
|
457
|
+
var Rpc = class {
|
|
458
|
+
async call(request) {
|
|
459
|
+
return await get_response_default(await make_request_default("4", `call`, "POST", request), 200);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
//#endregion
|
|
464
|
+
//#region src/Meta.ts
|
|
465
|
+
var Meta = class {
|
|
466
|
+
async query(rel) {
|
|
467
|
+
return await get_response_default(await make_request_default("3", `meta/${rel}`, "GET", null), 200);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
//#endregion
|
|
472
|
+
//#region src/Status.ts
|
|
473
|
+
var Status = class {
|
|
474
|
+
isAuth() {
|
|
475
|
+
const tokens = getTokens();
|
|
476
|
+
return !(!tokens.accessToken && !tokens.refreshToken);
|
|
477
|
+
}
|
|
478
|
+
getTokens() {
|
|
479
|
+
return getTokens();
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
//#endregion
|
|
484
|
+
//#region src/Claims.ts
|
|
485
|
+
var Claims = class {
|
|
486
|
+
get() {
|
|
487
|
+
const tokens = getTokens().accessToken;
|
|
488
|
+
return claims(tokens);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/Users.ts
|
|
494
|
+
var Users = class {
|
|
495
|
+
async get(user) {
|
|
496
|
+
return await get_response_default(await make_request_default("4", `users/${user}`, "GET", null), 200);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
//#endregion
|
|
501
|
+
//#region src/Ws.ts
|
|
502
|
+
var Ws = class {
|
|
503
|
+
constructor(options) {
|
|
504
|
+
this.options = options;
|
|
505
|
+
}
|
|
506
|
+
connect() {
|
|
507
|
+
const me = this;
|
|
508
|
+
const { accessToken } = getTokens();
|
|
509
|
+
const connect = () => {
|
|
510
|
+
const ws = new WebSocket(this.options.host + `/?token=` + accessToken);
|
|
511
|
+
ws.onopen = function() {
|
|
512
|
+
console.log("WebSocket connected!");
|
|
513
|
+
};
|
|
514
|
+
ws.onmessage = function(event) {
|
|
515
|
+
me.options?.callBack(event.data);
|
|
516
|
+
};
|
|
517
|
+
ws.onclose = function(event) {
|
|
518
|
+
if (accessToken !== "") {
|
|
519
|
+
console.log("WebSocket closed, reconnecting in 3 seconds...", event.reason);
|
|
520
|
+
setTimeout(connect, 3e3);
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
ws.onerror = function(err) {
|
|
524
|
+
console.error("WebSocket error observed:", err);
|
|
525
|
+
ws.close();
|
|
526
|
+
};
|
|
527
|
+
};
|
|
528
|
+
if (accessToken !== "") connect();
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
//#endregion
|
|
533
|
+
//#region src/Stats.ts
|
|
534
|
+
var Stats = class {
|
|
535
|
+
async get() {
|
|
536
|
+
return await get_response_default(await make_request_default("4", `stats`, "GET", null), 200);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
//#endregion
|
|
541
|
+
//#region src/Tables.ts
|
|
542
|
+
var Tables = class {
|
|
543
|
+
async get(schema, table) {
|
|
544
|
+
return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "GET", null), 200);
|
|
545
|
+
}
|
|
546
|
+
async create(schema, table, payload) {
|
|
547
|
+
return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "POST", payload), 200);
|
|
548
|
+
}
|
|
549
|
+
async patch(schema, table, payload) {
|
|
550
|
+
return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "PATCH", payload), 200);
|
|
551
|
+
}
|
|
552
|
+
async delete(schema, table) {
|
|
553
|
+
return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "DELETE", null), 204);
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
//#endregion
|
|
558
|
+
//#region src/Api.ts
|
|
559
|
+
async function dispatch(name, args) {
|
|
560
|
+
const rpc = new Rpc();
|
|
561
|
+
const request = {
|
|
562
|
+
jsonrpc: "2.0",
|
|
563
|
+
method: name,
|
|
564
|
+
id: 1,
|
|
565
|
+
params: args
|
|
566
|
+
};
|
|
567
|
+
return (await rpc.call(request)).result.data;
|
|
568
|
+
}
|
|
569
|
+
function createApi() {
|
|
570
|
+
return new Proxy({}, { get(_target, prop) {
|
|
571
|
+
if (typeof prop !== "string") return void 0;
|
|
572
|
+
return (...args) => dispatch(prop, ...args);
|
|
573
|
+
} });
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
//#endregion
|
|
577
|
+
exports.Claims = Claims;
|
|
578
|
+
exports.CodeFlow = CodeFlow;
|
|
579
|
+
exports.Meta = Meta;
|
|
580
|
+
exports.PasswordFlow = PasswordFlow;
|
|
581
|
+
exports.Rpc = Rpc;
|
|
582
|
+
exports.Sql = Sql;
|
|
583
|
+
exports.Stats = Stats;
|
|
584
|
+
exports.Status = Status;
|
|
585
|
+
exports.Tables = Tables;
|
|
586
|
+
exports.Users = Users;
|
|
587
|
+
exports.Ws = Ws;
|
|
588
|
+
exports.createApi = createApi;
|