@putkoff/abstract-utilities 0.1.189 → 0.1.190
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/cjs/index.js +267 -267
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +267 -267
- package/dist/esm/index.js.map +1 -1
- package/dist/functions/config_utils/src/config_utils.d.ts +0 -2
- package/dist/functions/fetch_utils/imports.d.ts +1 -9
- package/dist/functions/fetch_utils/src/fetchIt_utils.d.ts +2 -16
- package/dist/functions/read_utils/src/index.d.ts +1 -1
- package/dist/functions/read_utils/src/read_utils.d.ts +2 -0
- package/dist/functions/read_utils/src/utils.d.ts +8 -0
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -322,6 +322,240 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
322
322
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
323
323
|
};
|
|
324
324
|
|
|
325
|
+
// src/functions/read_utils/src/read_utils.ts
|
|
326
|
+
/**
|
|
327
|
+
* Reads a JSON file, either via Node’s fs (if available)
|
|
328
|
+
* or via window.fetch in the browser. Never throws — returns
|
|
329
|
+
* the parsed object or null on any error.
|
|
330
|
+
*/
|
|
331
|
+
function readJsonFile(relativeOrAbsolutePath) {
|
|
332
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
333
|
+
// 1) Try Node.js fs
|
|
334
|
+
if (typeof process !== 'undefined' &&
|
|
335
|
+
process.versions != null &&
|
|
336
|
+
process.versions.node) {
|
|
337
|
+
try {
|
|
338
|
+
const fs = yield import('fs');
|
|
339
|
+
const path = yield import('path');
|
|
340
|
+
const filePath = path.isAbsolute(relativeOrAbsolutePath)
|
|
341
|
+
? relativeOrAbsolutePath
|
|
342
|
+
: path.resolve(process.cwd(), relativeOrAbsolutePath);
|
|
343
|
+
const text = yield fs.promises.readFile(filePath, 'utf8');
|
|
344
|
+
return JSON.parse(text);
|
|
345
|
+
}
|
|
346
|
+
catch (_a) {
|
|
347
|
+
// swallow and fall back to browser
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// 2) Try browser fetch
|
|
351
|
+
const fetchFn = safeGlobalProp('fetch');
|
|
352
|
+
if (typeof fetchFn !== 'function') {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
// Resolve URL against document.baseURI if possible
|
|
356
|
+
let url = relativeOrAbsolutePath;
|
|
357
|
+
const baseURI = safeGlobalProp('document', 'baseURI');
|
|
358
|
+
if (baseURI) {
|
|
359
|
+
try {
|
|
360
|
+
url = new URL(relativeOrAbsolutePath, baseURI).href;
|
|
361
|
+
}
|
|
362
|
+
catch (_b) {
|
|
363
|
+
// keep url as-is
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
try {
|
|
367
|
+
const res = yield fetchFn(url);
|
|
368
|
+
if (!res.ok)
|
|
369
|
+
return null;
|
|
370
|
+
return (yield res.json());
|
|
371
|
+
}
|
|
372
|
+
catch (_c) {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
function getConfigContent() {
|
|
378
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
379
|
+
try {
|
|
380
|
+
// `readJsonFile` should throw if the file isn’t there or isn’t valid JSON
|
|
381
|
+
const cfg = yield readJsonFile('./config.json');
|
|
382
|
+
return cfg;
|
|
383
|
+
}
|
|
384
|
+
catch (_a) {
|
|
385
|
+
// swallow errors & return null so callers can detect “no config”
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
// 2) Pull a single key out of that object
|
|
391
|
+
function getConfigVar() {
|
|
392
|
+
return __awaiter(this, arguments, void 0, function* (key = null) {
|
|
393
|
+
const cfg = yield getConfigContent();
|
|
394
|
+
if (cfg && typeof cfg === 'object' && key in cfg) {
|
|
395
|
+
return cfg[key];
|
|
396
|
+
}
|
|
397
|
+
return undefined;
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Constructs API URL from endpoint
|
|
402
|
+
/**
|
|
403
|
+
* Unwraps nested { result } fields until you hit a non-object or no more "result" keys.
|
|
404
|
+
*/
|
|
405
|
+
function getResult(obj) {
|
|
406
|
+
let current = obj;
|
|
407
|
+
while (current &&
|
|
408
|
+
typeof current === "object" &&
|
|
409
|
+
Object.prototype.hasOwnProperty.call(current, "result")) {
|
|
410
|
+
current = current.result;
|
|
411
|
+
}
|
|
412
|
+
return current;
|
|
413
|
+
}
|
|
414
|
+
// Determines HTTP method, defaults to GET or POST based on body
|
|
415
|
+
function getMethod(method = null, body = null) {
|
|
416
|
+
const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'PULL'];
|
|
417
|
+
method = (method || '').toUpperCase();
|
|
418
|
+
if (!validMethods.includes(method)) {
|
|
419
|
+
method = body ? 'POST' : 'GET';
|
|
420
|
+
}
|
|
421
|
+
return method;
|
|
422
|
+
}
|
|
423
|
+
// Gets headers, skips JSON headers when body is FormData
|
|
424
|
+
function getHeaders(headers = {}, method = null, body = null) {
|
|
425
|
+
const result = Object.assign({}, headers);
|
|
426
|
+
// inject auth if missing
|
|
427
|
+
if (!result.Authorization) {
|
|
428
|
+
const token = getToken();
|
|
429
|
+
Object.assign(result, getAuthorizationHeader(result, token));
|
|
430
|
+
}
|
|
431
|
+
method = getMethod(method, body);
|
|
432
|
+
// if it’s a multipart FormData, let the browser set the boundary header
|
|
433
|
+
if (body instanceof FormData) {
|
|
434
|
+
return result;
|
|
435
|
+
}
|
|
436
|
+
// otherwise for POST/PUT/PATCH default to JSON
|
|
437
|
+
if (['POST', 'PUT', 'PATCH'].includes(method) && !result['Content-Type']) {
|
|
438
|
+
result['Content-Type'] = 'application/json';
|
|
439
|
+
}
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
// Prepares request body, serializes to JSON for non-GET requests
|
|
443
|
+
function getBody(body = null, method = null) {
|
|
444
|
+
method = getMethod(method, body);
|
|
445
|
+
if (method === 'GET') {
|
|
446
|
+
return undefined;
|
|
447
|
+
}
|
|
448
|
+
if (body) {
|
|
449
|
+
try {
|
|
450
|
+
return JSON.stringify(body);
|
|
451
|
+
}
|
|
452
|
+
catch (err) {
|
|
453
|
+
return body;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return undefined;
|
|
457
|
+
}
|
|
458
|
+
// Prepares fetch variables, passes FormData intact
|
|
459
|
+
function getFetchVars(headers = null, method = null, body = null) {
|
|
460
|
+
method = getMethod(method, body);
|
|
461
|
+
headers = getHeaders(headers || {}, method, body);
|
|
462
|
+
// only JSON-stringify non-FormData bodies
|
|
463
|
+
if (!(body instanceof FormData)) {
|
|
464
|
+
body = getBody(body, method);
|
|
465
|
+
}
|
|
466
|
+
return { method, headers, body };
|
|
467
|
+
}
|
|
468
|
+
/*
|
|
469
|
+
* parseResult no longer needs to worry about JSON vs HTML redirect errors;
|
|
470
|
+
* all 401/403 have already been handled above.
|
|
471
|
+
*/
|
|
472
|
+
function parseResult(res) {
|
|
473
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
474
|
+
// runs checkResponse first, will throw if session is expired
|
|
475
|
+
res = checkResponse(res);
|
|
476
|
+
if (!res.ok) {
|
|
477
|
+
// for any other non-401 errors, you can still surface them
|
|
478
|
+
const errorText = yield res.text();
|
|
479
|
+
throw new Error(errorText || res.statusText);
|
|
480
|
+
}
|
|
481
|
+
// now safely parse JSON
|
|
482
|
+
return res.json();
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Intercept 401/403 and force a clean redirect to login
|
|
487
|
+
* without ever showing an alert.
|
|
488
|
+
*/
|
|
489
|
+
function checkResponse(res) {
|
|
490
|
+
if (res.status === 401 || res.status === 403) {
|
|
491
|
+
// 1) clear out the stale token
|
|
492
|
+
localStorage.removeItem("token");
|
|
493
|
+
// 2) replace history so "back" doesn’t re-trigger the protected route
|
|
494
|
+
window.history.replaceState({}, "", "/secure-files");
|
|
495
|
+
// 3) short-circuit all further fetch logic
|
|
496
|
+
throw new Error("SessionExpired");
|
|
497
|
+
}
|
|
498
|
+
return res;
|
|
499
|
+
}
|
|
500
|
+
function fetchIt(endpoint_1) {
|
|
501
|
+
return __awaiter(this, arguments, void 0, function* (endpoint, body = null, method = null, headers = null, blob = false, configUrl = false, withCredentials = true, returnJson = true, returnReult = true) {
|
|
502
|
+
method = (method || "GET").toUpperCase();
|
|
503
|
+
// 2) choose the URL
|
|
504
|
+
let url = endpoint;
|
|
505
|
+
// 3) prepare headers & body
|
|
506
|
+
headers = Object.assign(Object.assign(Object.assign({}, (body instanceof FormData ? {} : { "Content-Type": "application/json" })), getAuthorizationHeader()), headers);
|
|
507
|
+
const opts = {
|
|
508
|
+
method,
|
|
509
|
+
credentials: withCredentials ? "include" : "same-origin",
|
|
510
|
+
headers,
|
|
511
|
+
body: body instanceof FormData
|
|
512
|
+
? body
|
|
513
|
+
: body != null && method !== "GET"
|
|
514
|
+
? JSON.stringify(body)
|
|
515
|
+
: undefined,
|
|
516
|
+
};
|
|
517
|
+
console.debug("➡️ secureFetchIt →", url, opts);
|
|
518
|
+
const res = yield fetch(url, opts);
|
|
519
|
+
if (!res.ok) {
|
|
520
|
+
const err = yield res.text();
|
|
521
|
+
throw new Error(`HTTP ${res.status}: ${err}`);
|
|
522
|
+
}
|
|
523
|
+
if (blob)
|
|
524
|
+
return res.blob();
|
|
525
|
+
if (returnReult)
|
|
526
|
+
return getResult(res.json());
|
|
527
|
+
if (returnJson)
|
|
528
|
+
return res.json();
|
|
529
|
+
return res;
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
// Constructs HTML directory path
|
|
533
|
+
function getHtmlDirectory(directory, filename) {
|
|
534
|
+
return `${directory}/${filename}.html`;
|
|
535
|
+
}
|
|
536
|
+
// Fetches HTML content
|
|
537
|
+
function fetchIndexHtml(filename_1) {
|
|
538
|
+
return __awaiter(this, arguments, void 0, function* (filename, directory = 'sf_index', base = 'html') {
|
|
539
|
+
const url = `/${base}/${directory}/${filename}.html`;
|
|
540
|
+
const response = yield fetch(url);
|
|
541
|
+
return yield response.text();
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
// Fetches and injects HTML content into container
|
|
545
|
+
function fetchIndexHtmlContainer(filename_1) {
|
|
546
|
+
return __awaiter(this, arguments, void 0, function* (filename, doc = document, directory = 'html') {
|
|
547
|
+
const container = `${filename}-container`;
|
|
548
|
+
const html = yield fetchIndexHtml(filename, directory);
|
|
549
|
+
const el = doc.getElementById(container);
|
|
550
|
+
if (el) {
|
|
551
|
+
el.innerHTML = html;
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
console.warn(`⚠️ No container found for: #${container}`);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
325
559
|
function assertPath(path) {
|
|
326
560
|
if (typeof path !== 'string') {
|
|
327
561
|
throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
|
|
@@ -1154,57 +1388,39 @@ function alertit(obj = null) {
|
|
|
1154
1388
|
alert(msg);
|
|
1155
1389
|
}
|
|
1156
1390
|
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
if (baseURI) {
|
|
1191
|
-
try {
|
|
1192
|
-
url = new URL(relativeOrAbsolutePath, baseURI).href;
|
|
1193
|
-
}
|
|
1194
|
-
catch (_b) {
|
|
1195
|
-
// keep url as-is
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
try {
|
|
1199
|
-
const res = yield fetchFn(url);
|
|
1200
|
-
if (!res.ok)
|
|
1201
|
-
return null;
|
|
1202
|
-
return (yield res.json());
|
|
1203
|
-
}
|
|
1204
|
-
catch (_c) {
|
|
1205
|
-
return null;
|
|
1206
|
-
}
|
|
1207
|
-
});
|
|
1391
|
+
function Button(_a) {
|
|
1392
|
+
var { children, color = 'gray', variant = 'default', className = '' } = _a, rest = __rest(_a, ["children", "color", "variant", "className"]);
|
|
1393
|
+
const base = 'rounded px-3 py-1 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 transition-colors duration-150';
|
|
1394
|
+
const variantStyles = {
|
|
1395
|
+
default: '',
|
|
1396
|
+
icon: 'p-1 bg-transparent hover:bg-gray-100',
|
|
1397
|
+
primary: 'text-white',
|
|
1398
|
+
secondary: '',
|
|
1399
|
+
};
|
|
1400
|
+
const palette = {
|
|
1401
|
+
gray: variant === 'primary'
|
|
1402
|
+
? 'bg-gray-600 hover:bg-gray-700 focus:ring-gray-500'
|
|
1403
|
+
: 'bg-gray-200 hover:bg-gray-300 focus:ring-gray-400',
|
|
1404
|
+
green: 'bg-green-600 text-white hover:bg-green-700 focus:ring-green-500',
|
|
1405
|
+
blue: variant === 'primary'
|
|
1406
|
+
? 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-500'
|
|
1407
|
+
: 'bg-blue-200 hover:bg-blue-300 focus:ring-blue-400',
|
|
1408
|
+
};
|
|
1409
|
+
return (jsxRuntime.jsx("button", Object.assign({ className: `${base} ${variantStyles[variant]} ${palette[color]} ${className}` }, rest, { children: children })));
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
function Checkbox(_a) {
|
|
1413
|
+
var { label } = _a, rest = __rest(_a, ["label"]);
|
|
1414
|
+
return (jsxRuntime.jsxs("label", { className: 'flex items-center gap-2 mb-4', children: [jsxRuntime.jsx("input", Object.assign({ type: 'checkbox' }, rest)), jsxRuntime.jsx("span", { children: label })] }));
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
function Input(_a) {
|
|
1418
|
+
var { label, trailing } = _a, rest = __rest(_a, ["label", "trailing"]);
|
|
1419
|
+
return (jsxRuntime.jsxs("label", { className: 'mb-4 block', children: [jsxRuntime.jsx("span", { className: 'block text-sm font-medium mb-1', children: label }), jsxRuntime.jsxs("div", { className: 'flex gap-2', children: [jsxRuntime.jsx("input", Object.assign({ className: 'flex-1 rounded border px-2 py-1 disabled:bg-gray-100' }, rest)), trailing] })] }));
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
function Spinner() {
|
|
1423
|
+
return (jsxRuntime.jsx("p", { className: 'animate-pulse', children: "Loading\u2026" }));
|
|
1208
1424
|
}
|
|
1209
1425
|
|
|
1210
1426
|
// src/functions/config_utils/src/config_utils.ts
|
|
@@ -1278,222 +1494,6 @@ function getConfig(key) {
|
|
|
1278
1494
|
return key != null ? cfg[key] : cfg;
|
|
1279
1495
|
});
|
|
1280
1496
|
}
|
|
1281
|
-
function getConfigContent() {
|
|
1282
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1283
|
-
try {
|
|
1284
|
-
// `readJsonFile` should throw if the file isn’t there or isn’t valid JSON
|
|
1285
|
-
const cfg = yield readJsonFile('./config.json');
|
|
1286
|
-
return cfg;
|
|
1287
|
-
}
|
|
1288
|
-
catch (_a) {
|
|
1289
|
-
// swallow errors & return null so callers can detect “no config”
|
|
1290
|
-
return null;
|
|
1291
|
-
}
|
|
1292
|
-
});
|
|
1293
|
-
}
|
|
1294
|
-
// 2) Pull a single key out of that object
|
|
1295
|
-
function getConfigVar() {
|
|
1296
|
-
return __awaiter(this, arguments, void 0, function* (key = null) {
|
|
1297
|
-
const cfg = yield getConfigContent();
|
|
1298
|
-
if (cfg && typeof cfg === 'object' && key in cfg) {
|
|
1299
|
-
return cfg[key];
|
|
1300
|
-
}
|
|
1301
|
-
return undefined;
|
|
1302
|
-
});
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
// Constructs API URL from endpoint
|
|
1306
|
-
/**
|
|
1307
|
-
* Unwraps nested { result } fields until you hit a non-object or no more "result" keys.
|
|
1308
|
-
*/
|
|
1309
|
-
function getResult(obj) {
|
|
1310
|
-
let current = obj;
|
|
1311
|
-
while (current &&
|
|
1312
|
-
typeof current === "object" &&
|
|
1313
|
-
Object.prototype.hasOwnProperty.call(current, "result")) {
|
|
1314
|
-
current = current.result;
|
|
1315
|
-
}
|
|
1316
|
-
return current;
|
|
1317
|
-
}
|
|
1318
|
-
// Determines HTTP method, defaults to GET or POST based on body
|
|
1319
|
-
function getMethod(method = null, body = null) {
|
|
1320
|
-
const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'PULL'];
|
|
1321
|
-
method = (method || '').toUpperCase();
|
|
1322
|
-
if (!validMethods.includes(method)) {
|
|
1323
|
-
method = body ? 'POST' : 'GET';
|
|
1324
|
-
}
|
|
1325
|
-
return method;
|
|
1326
|
-
}
|
|
1327
|
-
// Gets headers, skips JSON headers when body is FormData
|
|
1328
|
-
function getHeaders(headers = {}, method = null, body = null) {
|
|
1329
|
-
const result = Object.assign({}, headers);
|
|
1330
|
-
// inject auth if missing
|
|
1331
|
-
if (!result.Authorization) {
|
|
1332
|
-
const token = getToken();
|
|
1333
|
-
Object.assign(result, getAuthorizationHeader(result, token));
|
|
1334
|
-
}
|
|
1335
|
-
method = getMethod(method, body);
|
|
1336
|
-
// if it’s a multipart FormData, let the browser set the boundary header
|
|
1337
|
-
if (body instanceof FormData) {
|
|
1338
|
-
return result;
|
|
1339
|
-
}
|
|
1340
|
-
// otherwise for POST/PUT/PATCH default to JSON
|
|
1341
|
-
if (['POST', 'PUT', 'PATCH'].includes(method) && !result['Content-Type']) {
|
|
1342
|
-
result['Content-Type'] = 'application/json';
|
|
1343
|
-
}
|
|
1344
|
-
return result;
|
|
1345
|
-
}
|
|
1346
|
-
// Prepares request body, serializes to JSON for non-GET requests
|
|
1347
|
-
function getBody(body = null, method = null) {
|
|
1348
|
-
method = getMethod(method, body);
|
|
1349
|
-
if (method === 'GET') {
|
|
1350
|
-
return undefined;
|
|
1351
|
-
}
|
|
1352
|
-
if (body) {
|
|
1353
|
-
try {
|
|
1354
|
-
return JSON.stringify(body);
|
|
1355
|
-
}
|
|
1356
|
-
catch (err) {
|
|
1357
|
-
return body;
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
return undefined;
|
|
1361
|
-
}
|
|
1362
|
-
// Prepares fetch variables, passes FormData intact
|
|
1363
|
-
function getFetchVars(headers = null, method = null, body = null) {
|
|
1364
|
-
method = getMethod(method, body);
|
|
1365
|
-
headers = getHeaders(headers || {}, method, body);
|
|
1366
|
-
// only JSON-stringify non-FormData bodies
|
|
1367
|
-
if (!(body instanceof FormData)) {
|
|
1368
|
-
body = getBody(body, method);
|
|
1369
|
-
}
|
|
1370
|
-
return { method, headers, body };
|
|
1371
|
-
}
|
|
1372
|
-
/*
|
|
1373
|
-
* parseResult no longer needs to worry about JSON vs HTML redirect errors;
|
|
1374
|
-
* all 401/403 have already been handled above.
|
|
1375
|
-
*/
|
|
1376
|
-
function parseResult(res) {
|
|
1377
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1378
|
-
// runs checkResponse first, will throw if session is expired
|
|
1379
|
-
res = checkResponse(res);
|
|
1380
|
-
if (!res.ok) {
|
|
1381
|
-
// for any other non-401 errors, you can still surface them
|
|
1382
|
-
const errorText = yield res.text();
|
|
1383
|
-
throw new Error(errorText || res.statusText);
|
|
1384
|
-
}
|
|
1385
|
-
// now safely parse JSON
|
|
1386
|
-
return res.json();
|
|
1387
|
-
});
|
|
1388
|
-
}
|
|
1389
|
-
/**
|
|
1390
|
-
* Intercept 401/403 and force a clean redirect to login
|
|
1391
|
-
* without ever showing an alert.
|
|
1392
|
-
*/
|
|
1393
|
-
function checkResponse(res) {
|
|
1394
|
-
if (res.status === 401 || res.status === 403) {
|
|
1395
|
-
// 1) clear out the stale token
|
|
1396
|
-
localStorage.removeItem("token");
|
|
1397
|
-
// 2) replace history so "back" doesn’t re-trigger the protected route
|
|
1398
|
-
window.history.replaceState({}, "", "/secure-files");
|
|
1399
|
-
// 3) short-circuit all further fetch logic
|
|
1400
|
-
throw new Error("SessionExpired");
|
|
1401
|
-
}
|
|
1402
|
-
return res;
|
|
1403
|
-
}
|
|
1404
|
-
function fetchIt(endpoint_1) {
|
|
1405
|
-
return __awaiter(this, arguments, void 0, function* (endpoint, body = null, method = null, headers = null, blob = false, configUrl = false, withCredentials = true, returnJson = true, returnReult = true) {
|
|
1406
|
-
method = (method || "GET").toUpperCase();
|
|
1407
|
-
// 2) choose the URL
|
|
1408
|
-
let url = endpoint;
|
|
1409
|
-
// 3) prepare headers & body
|
|
1410
|
-
headers = Object.assign(Object.assign(Object.assign({}, (body instanceof FormData ? {} : { "Content-Type": "application/json" })), getAuthorizationHeader()), headers);
|
|
1411
|
-
const opts = {
|
|
1412
|
-
method,
|
|
1413
|
-
credentials: withCredentials ? "include" : "same-origin",
|
|
1414
|
-
headers,
|
|
1415
|
-
body: body instanceof FormData
|
|
1416
|
-
? body
|
|
1417
|
-
: body != null && method !== "GET"
|
|
1418
|
-
? JSON.stringify(body)
|
|
1419
|
-
: undefined,
|
|
1420
|
-
};
|
|
1421
|
-
console.debug("➡️ secureFetchIt →", url, opts);
|
|
1422
|
-
const res = yield fetch(url, opts);
|
|
1423
|
-
if (!res.ok) {
|
|
1424
|
-
const err = yield res.text();
|
|
1425
|
-
throw new Error(`HTTP ${res.status}: ${err}`);
|
|
1426
|
-
}
|
|
1427
|
-
if (blob)
|
|
1428
|
-
return res.blob();
|
|
1429
|
-
if (returnReult)
|
|
1430
|
-
return getResult(res.json());
|
|
1431
|
-
if (returnJson)
|
|
1432
|
-
return res.json();
|
|
1433
|
-
return res;
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
// Constructs HTML directory path
|
|
1437
|
-
function getHtmlDirectory(directory, filename) {
|
|
1438
|
-
return `${directory}/${filename}.html`;
|
|
1439
|
-
}
|
|
1440
|
-
// Fetches HTML content
|
|
1441
|
-
function fetchIndexHtml(filename_1) {
|
|
1442
|
-
return __awaiter(this, arguments, void 0, function* (filename, directory = 'sf_index', base = 'html') {
|
|
1443
|
-
const url = `/${base}/${directory}/${filename}.html`;
|
|
1444
|
-
const response = yield fetch(url);
|
|
1445
|
-
return yield response.text();
|
|
1446
|
-
});
|
|
1447
|
-
}
|
|
1448
|
-
// Fetches and injects HTML content into container
|
|
1449
|
-
function fetchIndexHtmlContainer(filename_1) {
|
|
1450
|
-
return __awaiter(this, arguments, void 0, function* (filename, doc = document, directory = 'html') {
|
|
1451
|
-
const container = `${filename}-container`;
|
|
1452
|
-
const html = yield fetchIndexHtml(filename, directory);
|
|
1453
|
-
const el = doc.getElementById(container);
|
|
1454
|
-
if (el) {
|
|
1455
|
-
el.innerHTML = html;
|
|
1456
|
-
}
|
|
1457
|
-
else {
|
|
1458
|
-
console.warn(`⚠️ No container found for: #${container}`);
|
|
1459
|
-
}
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
|
|
1463
|
-
function Button(_a) {
|
|
1464
|
-
var { children, color = 'gray', variant = 'default', className = '' } = _a, rest = __rest(_a, ["children", "color", "variant", "className"]);
|
|
1465
|
-
const base = 'rounded px-3 py-1 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 transition-colors duration-150';
|
|
1466
|
-
const variantStyles = {
|
|
1467
|
-
default: '',
|
|
1468
|
-
icon: 'p-1 bg-transparent hover:bg-gray-100',
|
|
1469
|
-
primary: 'text-white',
|
|
1470
|
-
secondary: '',
|
|
1471
|
-
};
|
|
1472
|
-
const palette = {
|
|
1473
|
-
gray: variant === 'primary'
|
|
1474
|
-
? 'bg-gray-600 hover:bg-gray-700 focus:ring-gray-500'
|
|
1475
|
-
: 'bg-gray-200 hover:bg-gray-300 focus:ring-gray-400',
|
|
1476
|
-
green: 'bg-green-600 text-white hover:bg-green-700 focus:ring-green-500',
|
|
1477
|
-
blue: variant === 'primary'
|
|
1478
|
-
? 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-500'
|
|
1479
|
-
: 'bg-blue-200 hover:bg-blue-300 focus:ring-blue-400',
|
|
1480
|
-
};
|
|
1481
|
-
return (jsxRuntime.jsx("button", Object.assign({ className: `${base} ${variantStyles[variant]} ${palette[color]} ${className}` }, rest, { children: children })));
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
function Checkbox(_a) {
|
|
1485
|
-
var { label } = _a, rest = __rest(_a, ["label"]);
|
|
1486
|
-
return (jsxRuntime.jsxs("label", { className: 'flex items-center gap-2 mb-4', children: [jsxRuntime.jsx("input", Object.assign({ type: 'checkbox' }, rest)), jsxRuntime.jsx("span", { children: label })] }));
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
function Input(_a) {
|
|
1490
|
-
var { label, trailing } = _a, rest = __rest(_a, ["label", "trailing"]);
|
|
1491
|
-
return (jsxRuntime.jsxs("label", { className: 'mb-4 block', children: [jsxRuntime.jsx("span", { className: 'block text-sm font-medium mb-1', children: label }), jsxRuntime.jsxs("div", { className: 'flex gap-2', children: [jsxRuntime.jsx("input", Object.assign({ className: 'flex-1 rounded border px-2 py-1 disabled:bg-gray-100' }, rest)), trailing] })] }));
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
function Spinner() {
|
|
1495
|
-
return (jsxRuntime.jsx("p", { className: 'animate-pulse', children: "Loading\u2026" }));
|
|
1496
|
-
}
|
|
1497
1497
|
|
|
1498
1498
|
Object.defineProperty(exports, "useCallback", {
|
|
1499
1499
|
enumerable: true,
|