@opexa/portal-components 0.1.80 → 0.1.83
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/README.md +238 -0
- package/dist/client/hooks/useMarkGameAsFavoriteMutation.js +9 -1
- package/dist/client/hooks/useUnmarkGameAsFavoriteMutation.js +1 -1
- package/dist/components/ForgotPassword/Crazywin/ForgotPassword.module.css +42 -42
- package/dist/components/Jackpots/Jackpots.module.css +288 -288
- package/dist/components/KYC/KYCDefault/KYCVerificationStatus.lazy.js +2 -2
- package/dist/components/KYC/KYCNonPagCor/KYCVerificationStatus.lazy.js +2 -2
- package/dist/components/Promos/PromoCardClassNames.d.ts +11 -0
- package/dist/components/Promos/PromoCardClassNames.js +6 -0
- package/dist/components/SignUp/SignUpDefault/SignUpDefaultForm.js +1 -4
- package/dist/components/Tournaments/TournamentsCarousel/TournamentsCarouselItem.module.css +184 -184
- package/dist/components/Tournaments/TournamentsList/TournamentItem.module.css +184 -184
- package/dist/images/phone-icon.svg +10 -10
- package/dist/services/queries.js +3613 -3613
- package/dist/styles/theme.css +776 -776
- package/dist/ui/AlertDialog/AlertDialog.d.ts +121 -121
- package/dist/ui/AlertDialog/alertDialog.recipe.d.ts +11 -11
- package/dist/ui/Carousel/Carousel.d.ts +45 -45
- package/dist/ui/Carousel/carousel.recipe.d.ts +5 -5
- package/dist/ui/Clipboard/Clipboard.d.ts +18 -18
- package/dist/ui/Clipboard/clipboard.recipe.d.ts +3 -3
- package/dist/ui/Collapsible/Collapsible.d.ts +20 -20
- package/dist/ui/Collapsible/collapsible.recipe.d.ts +5 -5
- package/dist/ui/Combobox/Combobox.d.ts +42 -42
- package/dist/ui/Combobox/combobox.recipe.d.ts +3 -3
- package/dist/ui/DatePicker/DatePicker.d.ts +72 -72
- package/dist/ui/DatePicker/datePicker.recipe.d.ts +3 -3
- package/dist/ui/Dialog/Dialog.d.ts +33 -33
- package/dist/ui/Dialog/dialog.recipe.d.ts +3 -3
- package/dist/ui/Drawer/Drawer.d.ts +33 -33
- package/dist/ui/Drawer/drawer.recipe.d.ts +3 -3
- package/dist/ui/Menu/Menu.d.ts +306 -306
- package/dist/ui/Menu/menu.recipe.d.ts +17 -17
- package/dist/ui/Popover/Popover.d.ts +88 -88
- package/dist/ui/Popover/popover.recipe.d.ts +8 -8
- package/dist/ui/Progress/Progress.d.ts +27 -27
- package/dist/ui/Progress/progress.recipe.d.ts +3 -3
- package/dist/ui/SegmentGroup/SegmentGroup.d.ts +18 -18
- package/dist/ui/SegmentGroup/segmentGroup.recipe.d.ts +3 -3
- package/dist/ui/Select/Select.d.ts +45 -45
- package/dist/ui/Select/select.recipe.d.ts +3 -3
- package/dist/ui/Table/Table.d.ts +21 -21
- package/dist/ui/Table/table.anatomy.d.ts +1 -1
- package/dist/ui/Table/table.recipe.d.ts +3 -3
- package/dist/ui/Tabs/Tabs.d.ts +15 -15
- package/dist/ui/Tabs/tabs.recipe.d.ts +3 -3
- package/dist/ui/Tooltip/Tooltip.d.ts +30 -30
- package/dist/ui/Tooltip/tooltip.recipe.d.ts +5 -5
- package/package.json +4 -1
- package/dist/components/BetDepositLimit/betDepositLimitStore.d.ts +0 -24
- package/dist/components/BetDepositLimit/betDepositLimitStore.js +0 -51
- package/dist/components/ResponsibleGamingLimits/ResponsibleGamingLimits.lazy.d.ts +0 -1
- package/dist/components/ResponsibleGamingLimits/ResponsibleGamingLimits.lazy.js +0 -117
- package/dist/components/UpdateMobilePhoneNumber/hooks/useAutoOpenWhenUnverified.d.ts +0 -6
- package/dist/components/UpdateMobilePhoneNumber/hooks/useAutoOpenWhenUnverified.js +0 -31
- package/dist/handlers/v4Cookies.d.ts +0 -9
- package/dist/handlers/v4Cookies.js +0 -49
- package/dist/images/game-providers/SEXYCASINO.webp +0 -0
- package/dist/utils/get-fingerprint.d.ts +0 -8
- package/dist/utils/get-fingerprint.js +0 -37
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opexa/portal-components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.83",
|
|
4
4
|
"exports": {
|
|
5
5
|
"./ui/*": {
|
|
6
6
|
"types": "./dist/ui/*/index.d.ts",
|
|
@@ -165,6 +165,9 @@
|
|
|
165
165
|
"publish": false
|
|
166
166
|
},
|
|
167
167
|
"hooks": {
|
|
168
|
+
"before:init": [
|
|
169
|
+
"npm whoami"
|
|
170
|
+
],
|
|
168
171
|
"after:bump": [
|
|
169
172
|
"pnpm build"
|
|
170
173
|
],
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export type LimitType = 'bet' | 'deposit';
|
|
2
|
-
export type LimitPeriod = 'daily' | 'monthly';
|
|
3
|
-
export interface BetDepositLimitState {
|
|
4
|
-
isOpen: boolean;
|
|
5
|
-
type: LimitType;
|
|
6
|
-
period: LimitPeriod;
|
|
7
|
-
currentLimit: number;
|
|
8
|
-
requestedLimit: number;
|
|
9
|
-
setIsOpen: (isOpen: boolean) => void;
|
|
10
|
-
setType: (type: LimitType) => void;
|
|
11
|
-
setPeriod: (period: LimitPeriod) => void;
|
|
12
|
-
setCurrentLimit: (limit: number) => void;
|
|
13
|
-
setRequestedLimit: (limit: number) => void;
|
|
14
|
-
openModal: (type: LimitType, period: LimitPeriod, currentLimit: number, requestedLimit: number) => void;
|
|
15
|
-
}
|
|
16
|
-
export declare const useBetDepositLimitStore: import("zustand").UseBoundStore<import("zustand").StoreApi<BetDepositLimitState>>;
|
|
17
|
-
export declare const betDepositLimitStore: {
|
|
18
|
-
isOpen: boolean;
|
|
19
|
-
type: LimitType;
|
|
20
|
-
period: LimitPeriod;
|
|
21
|
-
currentLimit: number;
|
|
22
|
-
requestedLimit: number;
|
|
23
|
-
openModal(newType: LimitType, newPeriod: LimitPeriod, currentLimit: number, requestedLimit: number): void;
|
|
24
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand';
|
|
2
|
-
export const useBetDepositLimitStore = create((set) => ({
|
|
3
|
-
isOpen: false,
|
|
4
|
-
type: 'bet',
|
|
5
|
-
period: 'daily',
|
|
6
|
-
currentLimit: 0,
|
|
7
|
-
requestedLimit: 0,
|
|
8
|
-
setIsOpen: (isOpen) => set({ isOpen }),
|
|
9
|
-
setType: (type) => set({ type }),
|
|
10
|
-
setPeriod: (period) => set({ period }),
|
|
11
|
-
setCurrentLimit: (currentLimit) => set({ currentLimit }),
|
|
12
|
-
setRequestedLimit: (requestedLimit) => set({ requestedLimit }),
|
|
13
|
-
openModal: (type, period, currentLimit, requestedLimit) => set({ type, period, currentLimit, requestedLimit, isOpen: true }),
|
|
14
|
-
}));
|
|
15
|
-
export const betDepositLimitStore = {
|
|
16
|
-
get isOpen() {
|
|
17
|
-
return useBetDepositLimitStore.getState().isOpen;
|
|
18
|
-
},
|
|
19
|
-
set isOpen(value) {
|
|
20
|
-
useBetDepositLimitStore.setState({ isOpen: value });
|
|
21
|
-
},
|
|
22
|
-
get type() {
|
|
23
|
-
return useBetDepositLimitStore.getState().type;
|
|
24
|
-
},
|
|
25
|
-
set type(value) {
|
|
26
|
-
useBetDepositLimitStore.setState({ type: value });
|
|
27
|
-
},
|
|
28
|
-
get period() {
|
|
29
|
-
return useBetDepositLimitStore.getState().period;
|
|
30
|
-
},
|
|
31
|
-
set period(value) {
|
|
32
|
-
useBetDepositLimitStore.setState({ period: value });
|
|
33
|
-
},
|
|
34
|
-
get currentLimit() {
|
|
35
|
-
return useBetDepositLimitStore.getState().currentLimit;
|
|
36
|
-
},
|
|
37
|
-
set currentLimit(value) {
|
|
38
|
-
useBetDepositLimitStore.setState({ currentLimit: value });
|
|
39
|
-
},
|
|
40
|
-
get requestedLimit() {
|
|
41
|
-
return useBetDepositLimitStore.getState().requestedLimit;
|
|
42
|
-
},
|
|
43
|
-
set requestedLimit(value) {
|
|
44
|
-
useBetDepositLimitStore.setState({ requestedLimit: value });
|
|
45
|
-
},
|
|
46
|
-
openModal(newType, newPeriod, currentLimit, requestedLimit) {
|
|
47
|
-
useBetDepositLimitStore
|
|
48
|
-
.getState()
|
|
49
|
-
.openModal(newType, newPeriod, currentLimit, requestedLimit);
|
|
50
|
-
},
|
|
51
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function ResponsibleGamingLimits(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { Tabs } from '../../ui/Tabs/index.js';
|
|
4
|
-
import Link from 'next/link';
|
|
5
|
-
import { useCallback, useState } from 'react';
|
|
6
|
-
import { useForm } from 'react-hook-form';
|
|
7
|
-
import { twMerge } from 'tailwind-merge';
|
|
8
|
-
import { useShallow } from 'zustand/shallow';
|
|
9
|
-
import { BetDepositLimitModal } from '@opexa/portal-components/BetDepositLimit';
|
|
10
|
-
import { RefreshCcw01Icon } from '../../icons/RefreshCcw01Icon.js';
|
|
11
|
-
import { InfoCircleIcon } from '../../icons/InfoCircleIcon.js';
|
|
12
|
-
import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
|
|
13
|
-
import { Progress } from '../../ui/Progress/index.js';
|
|
14
|
-
import { Tooltip } from '../../ui/Tooltip/index.js';
|
|
15
|
-
import { Field } from '../../ui/Field/index.js';
|
|
16
|
-
import { Button } from '../../ui/Button/index.js';
|
|
17
|
-
const INITIAL_BET_LIMITS = [
|
|
18
|
-
{
|
|
19
|
-
period: 'daily',
|
|
20
|
-
label: 'Daily Bet Limit',
|
|
21
|
-
limit: 5000,
|
|
22
|
-
used: 3000,
|
|
23
|
-
resetsLabel: 'Resets daily',
|
|
24
|
-
active: true,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
period: 'monthly',
|
|
28
|
-
label: 'Monthly Bet Limit',
|
|
29
|
-
limit: 50000,
|
|
30
|
-
used: 0,
|
|
31
|
-
resetsLabel: 'Resets May 30, 2026',
|
|
32
|
-
active: false,
|
|
33
|
-
},
|
|
34
|
-
];
|
|
35
|
-
const INITIAL_DEPOSIT_LIMITS = [
|
|
36
|
-
{
|
|
37
|
-
period: 'daily',
|
|
38
|
-
label: 'Daily Deposit Limit',
|
|
39
|
-
limit: 10000,
|
|
40
|
-
used: 0,
|
|
41
|
-
resetsLabel: 'Resets daily',
|
|
42
|
-
active: false,
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
period: 'monthly',
|
|
46
|
-
label: 'Monthly Deposit Limit',
|
|
47
|
-
limit: 100000,
|
|
48
|
-
used: 0,
|
|
49
|
-
resetsLabel: 'Resets May 30, 2026',
|
|
50
|
-
active: false,
|
|
51
|
-
},
|
|
52
|
-
];
|
|
53
|
-
function getNewLimitKey(tab, period) {
|
|
54
|
-
return `${tab}-${period}`;
|
|
55
|
-
}
|
|
56
|
-
function formatPeso(amount) {
|
|
57
|
-
return `₱${amount.toLocaleString('en-PH')}`;
|
|
58
|
-
}
|
|
59
|
-
function getUsedPercent(used, limit) {
|
|
60
|
-
if (limit === 0)
|
|
61
|
-
return 0;
|
|
62
|
-
return Math.min(Math.round((used / limit) * 100), 100);
|
|
63
|
-
}
|
|
64
|
-
function getProgressColor(pct) {
|
|
65
|
-
if (pct >= 80)
|
|
66
|
-
return 'bg-[#D92D20]';
|
|
67
|
-
if (pct >= 50)
|
|
68
|
-
return 'bg-[#F79009]';
|
|
69
|
-
return 'bg-[#FAC515]';
|
|
70
|
-
}
|
|
71
|
-
function tabToLimitType(tab) {
|
|
72
|
-
return tab === 'Bet' ? 'bet' : 'deposit';
|
|
73
|
-
}
|
|
74
|
-
export function ResponsibleGamingLimits() {
|
|
75
|
-
const openModal = useGlobalStore(useShallow((state) => state.betDepositLimit.openModal));
|
|
76
|
-
const form = useForm({
|
|
77
|
-
defaultValues: {},
|
|
78
|
-
});
|
|
79
|
-
const [activeTab, setActiveTab] = useState('Deposit');
|
|
80
|
-
const [betLimits, setBetLimits] = useState(INITIAL_BET_LIMITS);
|
|
81
|
-
const [depositLimits, setDepositLimits] = useState(INITIAL_DEPOSIT_LIMITS);
|
|
82
|
-
const limits = activeTab === 'Bet' ? betLimits : depositLimits;
|
|
83
|
-
const applyConfirmedLimit = useCallback(() => {
|
|
84
|
-
const { type, period, requestedLimit } = useGlobalStore.getState().betDepositLimit;
|
|
85
|
-
const updateLimits = (cards) => cards.map((card) => card.period === period ? { ...card, limit: requestedLimit } : card);
|
|
86
|
-
if (type === 'bet') {
|
|
87
|
-
setBetLimits(updateLimits);
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
setDepositLimits(updateLimits);
|
|
91
|
-
}
|
|
92
|
-
}, []);
|
|
93
|
-
const saveLimit = useCallback((card, inputValue) => {
|
|
94
|
-
const key = getNewLimitKey(activeTab, card.period);
|
|
95
|
-
const parsed = parseFloat(String(inputValue).replace(/[^0-9.]/g, ''));
|
|
96
|
-
if (Number.isNaN(parsed) || parsed <= 0) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
openModal(tabToLimitType(activeTab), card.period, card.limit, parsed);
|
|
100
|
-
form.setValue(key, '');
|
|
101
|
-
}, [activeTab, form, openModal]);
|
|
102
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "bg-bg-secondary m-5 mx-auto my-10 rounded-xl px-4 py-6 lg:px-8 lg:py-10", children: [_jsxs("div", { className: "mb-6", children: [_jsx("h1", { className: "text-text-primary-brand text-3xl font-bold lg:block", children: "Responsible Gaming" }), _jsxs("p", { className: "text-text-disabled mt-1 text-sm", children: ["Set limits for your gaming activity, including how much you can bet or deposit.", _jsx("br", { className: "hidden sm:inline" }), "These limits help you stay within the boundaries you choose."] })] }), _jsxs("div", { className: "bg-bg-primary border-border-dark mb-6 flex flex-col items-start justify-between gap-3 rounded-xl border px-4 py-4 shadow-xs sm:flex-row sm:items-center", children: [_jsxs("div", { children: [_jsx("p", { className: "text-text-primary-brand text-sm font-semibold", children: "Learn More About Responsible Gaming" }), _jsx("p", { className: "text-text-disabled mt-0.5 text-sm", children: "Find helpful tips, safety reminders, and support resources to help you stay informed and in control while playing." })] }), _jsx(Link, { href: "/responsible-gaming", className: twMerge('border-border-dark text-text-primary-brand inline-flex shrink-0 items-center justify-center gap-1.5 rounded-lg border px-4 py-2.5 text-sm font-semibold shadow-xs transition-colors'), children: "Visit Responsible Gaming" })] }), _jsx(Tabs.Root, { value: activeTab, onValueChange: (details) => setActiveTab(details.value), className: "mb-6 w-fit", children: _jsxs(Tabs.List, { children: [_jsx(Tabs.Trigger, { value: "Deposit", children: "Deposit" }), _jsx(Tabs.Trigger, { value: "Bet", children: "Bet" }), _jsx(Tabs.Indicator, {})] }) }), _jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: limits.map((card) => {
|
|
103
|
-
const pct = getUsedPercent(card.used, card.limit);
|
|
104
|
-
const key = getNewLimitKey(activeTab, card.period);
|
|
105
|
-
return (_jsxs("div", { className: "border-border-dark bg-bg-primary flex flex-col gap-4 rounded-xl border p-5 shadow-xs", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("span", { className: twMerge('inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium', card.active
|
|
106
|
-
? 'border border-[#085D3A] bg-[#053321] text-[#75E0A7]'
|
|
107
|
-
: 'border border-[#912018] bg-[#55160c] text-[#FDA29B]'), children: [_jsx("span", { className: twMerge('size-1.5 rounded-full', card.active ? 'bg-[#17B26A]' : 'bg-[#F04438]') }), card.active ? 'Active' : 'Inactive'] }), _jsxs("span", { className: "inline-flex items-center gap-1 rounded-full border border-[#b0841f] bg-[#191304] px-2.5 py-1 text-xs font-medium text-[#e2aa28]", children: [_jsx(RefreshCcw01Icon, { className: "size-3" }), card.resetsLabel] })] }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-semibold text-text-primary-brand", children: card.label }), _jsx("p", { className: "mt-1 text-2xl font-bold text-button-primary-bg", children: formatPeso(card.limit) })] }), _jsxs("div", { children: [_jsxs("div", { className: "text-text-disabled flex items-center justify-between text-xs", children: [_jsxs("span", { children: [formatPeso(card.used), " used"] }), _jsxs("span", { children: [pct, "%"] })] }), _jsx(Progress.Root, { value: pct, max: 100, variant: "unstyled", className: "relative mt-1.5 h-2 w-full", children: _jsx(Progress.Track, { className: "bg-bg-dark h-2 w-full rounded-full", children: _jsx(Progress.Range, { className: twMerge('h-full rounded-full transition-all duration-700 ease-in-out', getProgressColor(pct)) }) }) }), _jsxs("p", { className: "text-text-disabled mt-1.5 text-xs", children: ["Remaining: ", formatPeso(card.limit - card.used)] })] }), _jsxs("div", { children: [_jsxs("div", { className: "mb-2 flex items-center gap-1 text-sm font-medium text-text-primary-brand", children: [_jsx("span", { children: "Set new limit" }), _jsxs(Tooltip.Root, { openDelay: 0, closeDelay: 100, children: [_jsx(Tooltip.Trigger, { type: "button", className: "inline-flex", "aria-label": "Limit change information", children: _jsx(InfoCircleIcon, { className: "size-4 text-text-disabled" }) }), _jsx(Tooltip.Positioner, { children: _jsxs(Tooltip.Content, { className: "max-w-64 rounded-lg bg-[#0C111D] px-2.5 py-2 text-xs font-medium text-text-primary-brand", children: [_jsx(Tooltip.Arrow, {}), "Enter a new limit amount. Limits can only be lowered immediately. Limit increases take 24 hours to apply."] }) })] })] }), _jsxs("form", { className: "flex w-full items-center gap-2", onSubmit: form.handleSubmit((values) => {
|
|
108
|
-
console.log({
|
|
109
|
-
component: 'ResponsibleGamingLimits',
|
|
110
|
-
activeTab,
|
|
111
|
-
card,
|
|
112
|
-
values,
|
|
113
|
-
});
|
|
114
|
-
saveLimit(card, values[key] ?? '');
|
|
115
|
-
}), children: [_jsxs(Field.Root, { className: "relative w-full", children: [_jsx("span", { className: "text-text-disabled absolute top-1/2 left-2 shrink-0 -translate-y-1/2 text-sm", children: "\u20B1" }), _jsx(Field.Input, { className: "pl-6", type: "number", min: 0, placeholder: "0", ...form.register(key) })] }), _jsx(Button, { size: "md", variant: "solid", colorScheme: "primary", type: "submit", className: "w-fit shrink-0", children: "Save" })] })] })] }, card.period));
|
|
116
|
-
}) })] }), _jsx(BetDepositLimitModal, { onConfirm: applyConfirmedLimit })] }));
|
|
117
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { useEffect, useRef } from 'react';
|
|
3
|
-
import { useShallow } from 'zustand/shallow';
|
|
4
|
-
import { useAccountQuery } from '../../../client/hooks/useAccountQuery.js';
|
|
5
|
-
import { useGlobalStore } from '../../../client/hooks/useGlobalStore.js';
|
|
6
|
-
/**
|
|
7
|
-
* Opens the UpdateMobilePhoneNumber dialog automatically (once per mount) if
|
|
8
|
-
* the account has finished loading and the user's mobile number is not yet
|
|
9
|
-
* verified. Closes it if it is verified.
|
|
10
|
-
*/
|
|
11
|
-
export function useAutoOpenWhenUnverified() {
|
|
12
|
-
const { setOpen } = useGlobalStore(useShallow((ctx) => ({
|
|
13
|
-
setOpen: ctx.updateMobilePhoneNumber.setOpen,
|
|
14
|
-
})));
|
|
15
|
-
const accountQuery = useAccountQuery();
|
|
16
|
-
const account = accountQuery.data;
|
|
17
|
-
const isAccountLoading = accountQuery.isLoading;
|
|
18
|
-
const isMobileNumberVerified = account?.mobileNumberVerified === true;
|
|
19
|
-
const hasExecuted = useRef(false);
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (!isAccountLoading && !!account && !hasExecuted.current) {
|
|
22
|
-
if (!isMobileNumberVerified) {
|
|
23
|
-
setOpen(true);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
setOpen(false);
|
|
27
|
-
}
|
|
28
|
-
hasExecuted.current = true;
|
|
29
|
-
}
|
|
30
|
-
}, [isAccountLoading, account, isMobileNumberVerified, setOpen]);
|
|
31
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { NextResponse } from 'next/server';
|
|
2
|
-
/**
|
|
3
|
-
* Proxies AUTH `Set-Cookie` headers (the v4 refresh cookie) onto the outgoing
|
|
4
|
-
* Next.js response. In the proxy model the browser never talks to AUTH
|
|
5
|
-
* directly, so the cookie is re-scoped to the app domain (the `Domain`
|
|
6
|
-
* attribute from AUTH is dropped) and the route handler forwards it back to
|
|
7
|
-
* AUTH on subsequent requests via the `Cookie` header.
|
|
8
|
-
*/
|
|
9
|
-
export declare function applyV4SetCookie(response: NextResponse, setCookie: string[]): void;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Proxies AUTH `Set-Cookie` headers (the v4 refresh cookie) onto the outgoing
|
|
3
|
-
* Next.js response. In the proxy model the browser never talks to AUTH
|
|
4
|
-
* directly, so the cookie is re-scoped to the app domain (the `Domain`
|
|
5
|
-
* attribute from AUTH is dropped) and the route handler forwards it back to
|
|
6
|
-
* AUTH on subsequent requests via the `Cookie` header.
|
|
7
|
-
*/
|
|
8
|
-
export function applyV4SetCookie(response, setCookie) {
|
|
9
|
-
for (const raw of setCookie) {
|
|
10
|
-
const parsed = parseSetCookie(raw);
|
|
11
|
-
if (!parsed)
|
|
12
|
-
continue;
|
|
13
|
-
response.cookies.set(parsed.name, parsed.value, parsed.options);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function parseSetCookie(raw) {
|
|
17
|
-
const [pair, ...attrs] = raw.split(';');
|
|
18
|
-
const eq = pair.indexOf('=');
|
|
19
|
-
if (eq < 0)
|
|
20
|
-
return null;
|
|
21
|
-
const name = pair.slice(0, eq).trim();
|
|
22
|
-
const value = pair.slice(eq + 1).trim();
|
|
23
|
-
const options = {};
|
|
24
|
-
for (const attr of attrs) {
|
|
25
|
-
const [k, v] = attr.split('=').map((s) => s.trim());
|
|
26
|
-
const key = k.toLowerCase();
|
|
27
|
-
if (key === 'path')
|
|
28
|
-
options.path = v;
|
|
29
|
-
else if (key === 'max-age')
|
|
30
|
-
options.maxAge = Number(v);
|
|
31
|
-
else if (key === 'expires') {
|
|
32
|
-
const d = new Date(v);
|
|
33
|
-
if (!Number.isNaN(d.getTime()))
|
|
34
|
-
options.expires = d;
|
|
35
|
-
}
|
|
36
|
-
else if (key === 'httponly')
|
|
37
|
-
options.httpOnly = true;
|
|
38
|
-
else if (key === 'secure')
|
|
39
|
-
options.secure = true;
|
|
40
|
-
else if (key === 'samesite') {
|
|
41
|
-
const lv = (v ?? '').toLowerCase();
|
|
42
|
-
if (lv === 'strict' || lv === 'lax' || lv === 'none') {
|
|
43
|
-
options.sameSite = lv;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// `Domain` is intentionally dropped so the cookie scopes to the app.
|
|
47
|
-
}
|
|
48
|
-
return { name, value, options };
|
|
49
|
-
}
|
|
Binary file
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export declare function getFingerPrint(): Promise<string | null>;
|
|
2
|
-
/**
|
|
3
|
-
* Reads the session-version cookie (set by the `/api/sessions` route on
|
|
4
|
-
* sign-in). Used by the client to decide whether v4-only headers (e.g.
|
|
5
|
-
* `Fingerprint`) must accompany a request. The cookie is intentionally
|
|
6
|
-
* non-HttpOnly so it can be read here.
|
|
7
|
-
*/
|
|
8
|
-
export declare function getSessionVersion(): string | null;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Thumbmark } from '@thumbmarkjs/thumbmarkjs';
|
|
2
|
-
import { SESSION_VERSION_COOKIE_NAME } from '../constants/index.js';
|
|
3
|
-
let thumbmark_instance;
|
|
4
|
-
export async function getFingerPrint() {
|
|
5
|
-
if (typeof window === 'undefined')
|
|
6
|
-
return null;
|
|
7
|
-
if (!thumbmark_instance) {
|
|
8
|
-
thumbmark_instance = new Thumbmark({
|
|
9
|
-
logging: false,
|
|
10
|
-
timeout: 30000,
|
|
11
|
-
cache_lifetime_in_ms: 1 * 60 * 60 * 1000 /* 1h */,
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
try {
|
|
15
|
-
const cached = sessionStorage.getItem('fingerprint');
|
|
16
|
-
if (cached)
|
|
17
|
-
return cached;
|
|
18
|
-
const result = await thumbmark_instance.get();
|
|
19
|
-
sessionStorage.setItem('fingerprint', result.thumbmark);
|
|
20
|
-
return result.thumbmark;
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Reads the session-version cookie (set by the `/api/sessions` route on
|
|
28
|
-
* sign-in). Used by the client to decide whether v4-only headers (e.g.
|
|
29
|
-
* `Fingerprint`) must accompany a request. The cookie is intentionally
|
|
30
|
-
* non-HttpOnly so it can be read here.
|
|
31
|
-
*/
|
|
32
|
-
export function getSessionVersion() {
|
|
33
|
-
if (typeof document === 'undefined')
|
|
34
|
-
return null;
|
|
35
|
-
const match = document.cookie.match(`(?:^|; )${SESSION_VERSION_COOKIE_NAME}=([^;]*)`);
|
|
36
|
-
return match ? decodeURIComponent(match[1]) : null;
|
|
37
|
-
}
|