@koloseum/utils 0.3.0 → 0.3.1
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/client.d.ts +7 -1
- package/dist/client.js +31 -0
- package/dist/formatting.d.ts +6 -0
- package/dist/formatting.js +14 -0
- package/dist/general.d.ts +4 -0
- package/dist/general.js +5 -1
- package/dist/platform.d.ts +25 -1
- package/dist/platform.js +73 -13
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BrowserInfo, Microservice, MicroserviceFeature, MicroserviceGroup, MicroserviceObject, MicroserviceRole, UserWithCustomMetadata } from "@koloseum/types/general";
|
|
2
2
|
import type { PronounsCheckboxes } from "@koloseum/types/public-auth";
|
|
3
3
|
import type { IOptions } from "@suprsend/web-components/dist/types/interface.d.ts";
|
|
4
|
-
import type { Page } from "@sveltejs/kit";
|
|
4
|
+
import type { Page, SubmitFunction } from "@sveltejs/kit";
|
|
5
5
|
export declare const Browser: {
|
|
6
6
|
/**
|
|
7
7
|
* Checks if a specific feature is supported by the browser.
|
|
@@ -93,6 +93,12 @@ export declare const Access: {
|
|
|
93
93
|
roleHasAccessToFeature: (role: MicroserviceRole, feature: MicroserviceFeature, type: "backroom" | "lounges") => boolean;
|
|
94
94
|
};
|
|
95
95
|
export declare const Interface: {
|
|
96
|
+
/**
|
|
97
|
+
* Progressive-enhancement submit function for SvelteKit.
|
|
98
|
+
* Disables the submit button and shows a loading spinner; navigates via `goto` on redirect, otherwise calls `update` and restores the button.
|
|
99
|
+
* Buttons with class `otp-button` are not restored on failure/error so OTP flows can keep the loading state.
|
|
100
|
+
*/
|
|
101
|
+
formEnhance: SubmitFunction;
|
|
96
102
|
/**
|
|
97
103
|
* Returns the URL for a menu item based on the slug.
|
|
98
104
|
* @param {string} base - The base URL
|
package/dist/client.js
CHANGED
|
@@ -445,6 +445,37 @@ export const Access = {
|
|
|
445
445
|
};
|
|
446
446
|
/* INTERFACE HELPERS */
|
|
447
447
|
export const Interface = {
|
|
448
|
+
/**
|
|
449
|
+
* Progressive-enhancement submit function for SvelteKit.
|
|
450
|
+
* Disables the submit button and shows a loading spinner; navigates via `goto` on redirect, otherwise calls `update` and restores the button.
|
|
451
|
+
* Buttons with class `otp-button` are not restored on failure/error so OTP flows can keep the loading state.
|
|
452
|
+
*/
|
|
453
|
+
formEnhance: (({ submitter }) => {
|
|
454
|
+
if (submitter) {
|
|
455
|
+
const button = submitter;
|
|
456
|
+
const innerHTML = button.innerHTML;
|
|
457
|
+
// Disable button and show loading spinner if not an OTP button
|
|
458
|
+
if (!button.classList.contains("otp-button")) {
|
|
459
|
+
button.disabled = true;
|
|
460
|
+
button.innerHTML = `<span class="loading loading-bars loading-sm"></span>`;
|
|
461
|
+
}
|
|
462
|
+
// Handle form submission
|
|
463
|
+
return async ({ update, result }) => {
|
|
464
|
+
// Navigate via `goto` on redirect
|
|
465
|
+
if (result.type === "redirect" && result.location) {
|
|
466
|
+
const { goto } = await import("$app/navigation");
|
|
467
|
+
await goto(result.location);
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
// Update form and restore button if not an OTP button
|
|
471
|
+
await update();
|
|
472
|
+
if (result.type === "failure" || result.type === "error" || !button.classList.contains("otp-button")) {
|
|
473
|
+
button.disabled = false;
|
|
474
|
+
button.innerHTML = innerHTML;
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
}),
|
|
448
479
|
/**
|
|
449
480
|
* Returns the URL for a menu item based on the slug.
|
|
450
481
|
* @param {string} base - The base URL
|
package/dist/formatting.d.ts
CHANGED
|
@@ -99,6 +99,12 @@ export declare const Validate: {
|
|
|
99
99
|
* - at least one symbol
|
|
100
100
|
*/
|
|
101
101
|
passwordRegex: RegExp;
|
|
102
|
+
/**
|
|
103
|
+
* Returns a regular expression for a Koloseum platform ID.
|
|
104
|
+
* @param {string} type - The type of platform ID to return
|
|
105
|
+
* @returns A regular expression for the platform ID, or `null` if the type is invalid
|
|
106
|
+
*/
|
|
107
|
+
platformIdRegex: (type: "lounge" | "loungeBranch" | "player") => RegExp | null;
|
|
102
108
|
/**
|
|
103
109
|
* A regular expression for social media handles, without a leading slash or @ character.
|
|
104
110
|
*
|
package/dist/formatting.js
CHANGED
|
@@ -333,6 +333,20 @@ export const Validate = {
|
|
|
333
333
|
* - at least one symbol
|
|
334
334
|
*/
|
|
335
335
|
passwordRegex: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()\-_+=|{}\[\]:;'<>,.?/~]).{8,}$/,
|
|
336
|
+
/**
|
|
337
|
+
* Returns a regular expression for a Koloseum platform ID.
|
|
338
|
+
* @param {string} type - The type of platform ID to return
|
|
339
|
+
* @returns A regular expression for the platform ID, or `null` if the type is invalid
|
|
340
|
+
*/
|
|
341
|
+
platformIdRegex: (type) => {
|
|
342
|
+
if (type === "lounge")
|
|
343
|
+
return /^KL\d{7}$/;
|
|
344
|
+
if (type === "loungeBranch")
|
|
345
|
+
return /^KLB\d{7}$/;
|
|
346
|
+
if (type === "player")
|
|
347
|
+
return /^KP\d{7}$/;
|
|
348
|
+
return null;
|
|
349
|
+
},
|
|
336
350
|
/**
|
|
337
351
|
* A regular expression for social media handles, without a leading slash or @ character.
|
|
338
352
|
*
|
package/dist/general.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ export declare const Status: {
|
|
|
11
11
|
* A generic password reset request message.
|
|
12
12
|
*/
|
|
13
13
|
PASSWORD_RESET_REQUESTED: string;
|
|
14
|
+
/**
|
|
15
|
+
* A generic password reset confirmation message.
|
|
16
|
+
*/
|
|
17
|
+
PASSWORD_RESET_COMPLETED: string;
|
|
14
18
|
};
|
|
15
19
|
export declare const Cache: {
|
|
16
20
|
/**
|
package/dist/general.js
CHANGED
|
@@ -11,7 +11,11 @@ export const Status = {
|
|
|
11
11
|
/**
|
|
12
12
|
* A generic password reset request message.
|
|
13
13
|
*/
|
|
14
|
-
PASSWORD_RESET_REQUESTED: "If the provided email address is registered, you will receive a password reset link shortly."
|
|
14
|
+
PASSWORD_RESET_REQUESTED: "If the provided email address is registered, you will receive a password reset link shortly.",
|
|
15
|
+
/**
|
|
16
|
+
* A generic password reset confirmation message.
|
|
17
|
+
*/
|
|
18
|
+
PASSWORD_RESET_COMPLETED: "Your password has been reset successfully. You can now log in with your new password."
|
|
15
19
|
};
|
|
16
20
|
/* CACHE HELPERS */
|
|
17
21
|
export const Cache = {
|
package/dist/platform.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MicroserviceGroup, MicroserviceObject, UserWithCustomMetadata } from "@koloseum/types/general";
|
|
1
|
+
import type { CustomError, MicroserviceGroup, MicroserviceObject, UserWithCustomMetadata } from "@koloseum/types/general";
|
|
2
2
|
import type { BranchAddressObject, County } from "@koloseum/types/public-auth";
|
|
3
3
|
export declare const Config: {
|
|
4
4
|
/**
|
|
@@ -45,6 +45,23 @@ export declare const Resource: {
|
|
|
45
45
|
url?: string;
|
|
46
46
|
error?: any;
|
|
47
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Processes a redirect URI and returns a validated, safe redirect URL. Callers in SvelteKit can pass `dev` from `$app/environment`.
|
|
50
|
+
* @param uri - The URI to process (e.g. `players:competitions/leagues`)
|
|
51
|
+
* @param dev - Whether the environment is development/test; defaults to `false`
|
|
52
|
+
* @returns An object with the safe redirect `url`, or an `error` if the URI or URL is invalid or unsafe
|
|
53
|
+
*/
|
|
54
|
+
getSafeRedirectUrl: (uri: string, dev?: boolean) => {
|
|
55
|
+
url?: string;
|
|
56
|
+
error?: CustomError;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Returns whether the given URL points to a local Supabase instance (localhost or 127.0.0.1, any port).
|
|
60
|
+
* Use for cookie domain, redirects, and MSW so non-default local ports (e.g. 54621) behave like default (54321).
|
|
61
|
+
* @param url - Supabase API URL (e.g. PUBLIC_SUPABASE_URL)
|
|
62
|
+
* @returns `true` if the URL host is localhost or 127.0.0.1, `false` otherwise
|
|
63
|
+
*/
|
|
64
|
+
isLocalSupabase: (url: string | undefined) => boolean;
|
|
48
65
|
/**
|
|
49
66
|
* Parses a resource request and returns the URL and path.
|
|
50
67
|
* @param request - The request to parse.
|
|
@@ -63,4 +80,11 @@ export declare const Resource: {
|
|
|
63
80
|
address?: BranchAddressObject;
|
|
64
81
|
error?: any;
|
|
65
82
|
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Validates that a redirect URL is safe and allowed. Callers in SvelteKit can pass `dev` from `$app/environment`.
|
|
85
|
+
* @param url - The URL to validate
|
|
86
|
+
* @param dev - Whether the environment is development/test. Defaults to `false`
|
|
87
|
+
* @returns `true` if the URL is safe, `false` otherwise
|
|
88
|
+
*/
|
|
89
|
+
validateRedirectUrl: (url: string, dev?: boolean) => boolean;
|
|
66
90
|
};
|
package/dist/platform.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Transform } from "./formatting.js";
|
|
2
|
+
import { Exception } from "./server.js";
|
|
2
3
|
import { v4 as uuidv4 } from "uuid";
|
|
3
4
|
import validator from "validator";
|
|
4
5
|
/* HELPERS */
|
|
@@ -597,26 +598,36 @@ export const Resource = {
|
|
|
597
598
|
if (env === "development")
|
|
598
599
|
path = path.replace("account", "");
|
|
599
600
|
}
|
|
600
|
-
if (path.startsWith("
|
|
601
|
+
if (path.startsWith("sessions")) {
|
|
601
602
|
port = 5178;
|
|
602
603
|
if (env === "development")
|
|
603
|
-
path = path.replace("
|
|
604
|
+
path = path.replace("sessions", "");
|
|
604
605
|
}
|
|
605
|
-
if (path.startsWith("
|
|
606
|
+
if (path.startsWith("competitions")) {
|
|
606
607
|
port = 5179;
|
|
608
|
+
if (env === "development")
|
|
609
|
+
path = path.replace("competitions", "");
|
|
610
|
+
}
|
|
611
|
+
if (path.startsWith("commerce")) {
|
|
612
|
+
port = 5180;
|
|
607
613
|
if (env === "development")
|
|
608
614
|
path = path.replace("commerce", "");
|
|
609
615
|
}
|
|
610
616
|
}
|
|
611
617
|
// Handle Lounges microservices
|
|
612
618
|
if (microserviceGroup === "lounges") {
|
|
613
|
-
if (path.startsWith("
|
|
619
|
+
if (path.startsWith("account")) {
|
|
614
620
|
port = 5181;
|
|
615
621
|
if (env === "development")
|
|
616
|
-
path = path.replace("
|
|
622
|
+
path = path.replace("account", "");
|
|
623
|
+
}
|
|
624
|
+
if (path.startsWith("operations")) {
|
|
625
|
+
port = 5182;
|
|
626
|
+
if (env === "development")
|
|
627
|
+
path = path.replace("operations", "");
|
|
617
628
|
}
|
|
618
629
|
if (path.startsWith("staff")) {
|
|
619
|
-
port =
|
|
630
|
+
port = 5183;
|
|
620
631
|
if (env === "development")
|
|
621
632
|
path = path.replace("staff", "");
|
|
622
633
|
}
|
|
@@ -628,18 +639,13 @@ export const Resource = {
|
|
|
628
639
|
if (env === "development")
|
|
629
640
|
path = path.replace("compliance", "");
|
|
630
641
|
}
|
|
631
|
-
if (path.startsWith("competitions")) {
|
|
632
|
-
port = 5177;
|
|
633
|
-
if (env === "development")
|
|
634
|
-
path = path.replace("competitions", "");
|
|
635
|
-
}
|
|
636
642
|
if (path.startsWith("commerce")) {
|
|
637
|
-
port =
|
|
643
|
+
port = 5184;
|
|
638
644
|
if (env === "development")
|
|
639
645
|
path = path.replace("commerce", "");
|
|
640
646
|
}
|
|
641
647
|
if (path.startsWith("staff")) {
|
|
642
|
-
port =
|
|
648
|
+
port = 5185;
|
|
643
649
|
if (env === "development")
|
|
644
650
|
path = path.replace("staff", "");
|
|
645
651
|
}
|
|
@@ -651,6 +657,39 @@ export const Resource = {
|
|
|
651
657
|
: `http://127.0.0.1:${port}${path || ""}`
|
|
652
658
|
};
|
|
653
659
|
},
|
|
660
|
+
/**
|
|
661
|
+
* Processes a redirect URI and returns a validated, safe redirect URL. Callers in SvelteKit can pass `dev` from `$app/environment`.
|
|
662
|
+
* @param uri - The URI to process (e.g. `players:competitions/leagues`)
|
|
663
|
+
* @param dev - Whether the environment is development/test; defaults to `false`
|
|
664
|
+
* @returns An object with the safe redirect `url`, or an `error` if the URI or URL is invalid or unsafe
|
|
665
|
+
*/
|
|
666
|
+
getSafeRedirectUrl: (uri, dev = false) => {
|
|
667
|
+
const { url, error } = Resource.getRedirectUrl(uri, dev ? "development" : "production");
|
|
668
|
+
if (error)
|
|
669
|
+
return {
|
|
670
|
+
error: Exception.customError(error.code ?? 400, error.message ?? "Redirect URI is invalid.")
|
|
671
|
+
};
|
|
672
|
+
if (!url || !Resource.validateRedirectUrl(url, dev))
|
|
673
|
+
return { error: Exception.customError(400, "Redirect URL is invalid or unsafe.") };
|
|
674
|
+
return { url };
|
|
675
|
+
},
|
|
676
|
+
/**
|
|
677
|
+
* Returns whether the given URL points to a local Supabase instance (localhost or 127.0.0.1, any port).
|
|
678
|
+
* Use for cookie domain, redirects, and MSW so non-default local ports (e.g. 54621) behave like default (54321).
|
|
679
|
+
* @param url - Supabase API URL (e.g. PUBLIC_SUPABASE_URL)
|
|
680
|
+
* @returns `true` if the URL host is localhost or 127.0.0.1, `false` otherwise
|
|
681
|
+
*/
|
|
682
|
+
isLocalSupabase: (url) => {
|
|
683
|
+
if (!url || typeof url !== "string")
|
|
684
|
+
return false;
|
|
685
|
+
try {
|
|
686
|
+
const host = new URL(url).hostname;
|
|
687
|
+
return host === "localhost" || host === "127.0.0.1";
|
|
688
|
+
}
|
|
689
|
+
catch {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
},
|
|
654
693
|
/**
|
|
655
694
|
* Parses a resource request and returns the URL and path.
|
|
656
695
|
* @param request - The request to parse.
|
|
@@ -760,5 +799,26 @@ export const Resource = {
|
|
|
760
799
|
};
|
|
761
800
|
// Return data
|
|
762
801
|
return { address };
|
|
802
|
+
},
|
|
803
|
+
/**
|
|
804
|
+
* Validates that a redirect URL is safe and allowed. Callers in SvelteKit can pass `dev` from `$app/environment`.
|
|
805
|
+
* @param url - The URL to validate
|
|
806
|
+
* @param dev - Whether the environment is development/test. Defaults to `false`
|
|
807
|
+
* @returns `true` if the URL is safe, `false` otherwise
|
|
808
|
+
*/
|
|
809
|
+
validateRedirectUrl: (url, dev = false) => {
|
|
810
|
+
try {
|
|
811
|
+
const parsedUrl = new URL(url);
|
|
812
|
+
if (!dev && parsedUrl.protocol !== "https:")
|
|
813
|
+
return false;
|
|
814
|
+
if (dev && parsedUrl.hostname === "127.0.0.1")
|
|
815
|
+
return true;
|
|
816
|
+
if (!parsedUrl.hostname.endsWith(".koloseum.ke") && parsedUrl.hostname !== "koloseum.ke")
|
|
817
|
+
return false;
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
catch {
|
|
821
|
+
return false;
|
|
822
|
+
}
|
|
763
823
|
}
|
|
764
824
|
};
|
package/dist/server.js
CHANGED
|
@@ -36,7 +36,7 @@ export const Instance = {
|
|
|
36
36
|
const errorData = await error.context.json();
|
|
37
37
|
message = errorData.message || message;
|
|
38
38
|
// Assign attempt ID to context if present
|
|
39
|
-
if (path.includes("verify-id") && errorData.attemptId)
|
|
39
|
+
if ((path.includes("verify-id") || path.includes("smile-id")) && errorData.attemptId)
|
|
40
40
|
context.attemptId = errorData.attemptId;
|
|
41
41
|
}
|
|
42
42
|
catch (jsonError) {
|