@centia-io/sdk 0.0.23

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