diff --git a/components/common/Calendar.js b/components/common/Calendar.js index 077382d1..d68465be 100644 --- a/components/common/Calendar.js +++ b/components/common/Calendar.js @@ -17,9 +17,9 @@ import { isAfter, } from 'date-fns'; import { Button, Icon } from 'react-basics'; +import { chunkArray } from 'next-basics'; import useLocale from 'hooks/useLocale'; import { dateFormat } from 'lib/date'; -import { chunk } from 'lib/array'; import { getDateLocale } from 'lib/lang'; import Chevron from 'assets/chevron-down.svg'; import Cross from 'assets/times.svg'; @@ -142,7 +142,7 @@ const DaySelector = ({ date, minDate, maxDate, locale, onSelect }) => { - {chunk(days, 7).map((week, i) => ( + {chunkArray(days, 7).map((week, i) => ( {week.map((day, j) => { const disabled = isBefore(day, minDate) || isAfter(day, maxDate); @@ -181,7 +181,7 @@ const MonthSelector = ({ date, minDate, maxDate, locale, onSelect }) => { return ( - {chunk(months, 3).map((row, i) => ( + {chunkArray(months, 3).map((row, i) => ( {row.map((month, j) => { const disabled = @@ -246,7 +246,7 @@ const YearSelector = ({ date, minDate, maxDate, onSelect }) => {
- {chunk(years, 5).map((row, i) => ( + {chunkArray(years, 5).map((row, i) => ( {row.map((n, j) => (
{ mutate(data, { onSuccess: async ({ token, user }) => { - setAuthToken(token); + setClientAuthToken(token); setUser(user); await router.push('/websites'); diff --git a/components/forms/ShareUrlForm.js b/components/forms/ShareUrlForm.js index d4eb5c8e..aa1e1a46 100644 --- a/components/forms/ShareUrlForm.js +++ b/components/forms/ShareUrlForm.js @@ -1,5 +1,5 @@ import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import { getRandomChars, useApi } from 'next-basics'; import { useEffect, useMemo, useRef, useState } from 'react'; import { @@ -16,7 +16,7 @@ import { export default function ShareUrlForm({ websiteId, data, onSave }) { const { name, shareId } = data; const [id, setId] = useState(shareId); - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error } = useMutation(({ shareId }) => post(`/websites/${websiteId}`, { shareId }), ); diff --git a/components/forms/TeamAddForm.js b/components/forms/TeamAddForm.js index a18fc769..79543511 100644 --- a/components/forms/TeamAddForm.js +++ b/components/forms/TeamAddForm.js @@ -1,12 +1,12 @@ import { useRef } from 'react'; import { Form, FormInput, FormButtons, TextField, Button } from 'react-basics'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; import styles from './Form.module.css'; import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; export default function TeamAddForm({ onSave, onClose }) { - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error, isLoading } = useMutation(data => post('/teams', data)); const ref = useRef(null); diff --git a/components/forms/TeamEditForm.js b/components/forms/TeamEditForm.js index 769ccf61..474fa866 100644 --- a/components/forms/TeamEditForm.js +++ b/components/forms/TeamEditForm.js @@ -1,11 +1,11 @@ import { SubmitButton, Form, FormInput, FormRow, FormButtons, TextField } from 'react-basics'; import { useMutation } from '@tanstack/react-query'; import { useRef } from 'react'; -import { useApi } from 'next-basics'; -import { getAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; +import { getClientAuthToken } from 'lib/client'; export default function TeamEditForm({ teamId, data, onSave }) { - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error } = useMutation(data => post(`/teams/${teamId}`, data)); const ref = useRef(null); diff --git a/components/forms/UserDeleteForm.js b/components/forms/UserDeleteForm.js index 99bea443..0f6353a5 100644 --- a/components/forms/UserDeleteForm.js +++ b/components/forms/UserDeleteForm.js @@ -1,13 +1,13 @@ import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; -import { useApi } from 'next-basics'; +import { getClientAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; import { Button, Form, FormButtons, FormInput, SubmitButton, TextField } from 'react-basics'; import styles from './Form.module.css'; const CONFIRM_VALUE = 'DELETE'; export default function UserDeleteForm({ userId, onSave, onClose }) { - const { del } = useApi(getAuthToken()); + const { del } = useApi(getClientAuthToken()); const { mutate, error, isLoading } = useMutation(data => del(`/users/${userId}`, data)); const handleSubmit = async data => { diff --git a/components/forms/UserEditForm.js b/components/forms/UserEditForm.js index 7fb6e5c6..26d805d0 100644 --- a/components/forms/UserEditForm.js +++ b/components/forms/UserEditForm.js @@ -9,8 +9,8 @@ import { } from 'react-basics'; import { useRef } from 'react'; import { useMutation } from '@tanstack/react-query'; -import { useApi } from 'next-basics'; -import { getAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; +import { getClientAuthToken } from 'lib/client'; import { ROLES } from 'lib/constants'; import styles from './UserForm.module.css'; @@ -27,7 +27,7 @@ const items = [ export default function UserEditForm({ data, onSave }) { const { id } = data; - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error } = useMutation(({ username }) => post(`/user/${id}`, { username })); const ref = useRef(null); diff --git a/components/forms/UserPasswordForm.js b/components/forms/UserPasswordForm.js index f386da0a..748f462b 100644 --- a/components/forms/UserPasswordForm.js +++ b/components/forms/UserPasswordForm.js @@ -1,8 +1,8 @@ import { useRef } from 'react'; import { Form, FormInput, FormButtons, PasswordField, Button } from 'react-basics'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import styles from './UserPasswordForm.module.css'; import useUser from 'hooks/useUser'; @@ -13,7 +13,7 @@ export default function UserPasswordForm({ onSave, userId }) { const isCurrentUser = !userId || id === userId; const url = isCurrentUser ? `/users/${id}/password` : `/users/${id}`; - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error, isLoading } = useMutation(data => post(url, data)); const ref = useRef(null); diff --git a/components/forms/WebsiteAddForm.js b/components/forms/WebsiteAddForm.js index f14b8b74..c3fea4b2 100644 --- a/components/forms/WebsiteAddForm.js +++ b/components/forms/WebsiteAddForm.js @@ -1,13 +1,13 @@ import { useRef } from 'react'; import { Form, FormInput, FormButtons, TextField, Button, SubmitButton } from 'react-basics'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; import styles from './Form.module.css'; import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import { DOMAIN_REGEX } from 'lib/constants'; export default function WebsiteAddForm({ onSave, onClose }) { - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error, isLoading } = useMutation(data => post('/websites', data)); const ref = useRef(null); diff --git a/components/forms/WebsiteDeleteForm.js b/components/forms/WebsiteDeleteForm.js index d90e88a4..623a4aff 100644 --- a/components/forms/WebsiteDeleteForm.js +++ b/components/forms/WebsiteDeleteForm.js @@ -1,13 +1,13 @@ import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; -import { useApi } from 'next-basics'; +import { getClientAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; import { Button, Form, FormButtons, FormInput, SubmitButton, TextField } from 'react-basics'; import styles from './Form.module.css'; const CONFIRM_VALUE = 'DELETE'; export default function WebsiteDeleteForm({ websiteId, onSave, onClose }) { - const { del } = useApi(getAuthToken()); + const { del } = useApi(getClientAuthToken()); const { mutate, error, isLoading } = useMutation(data => del(`/websites/${websiteId}`, data)); const handleSubmit = async data => { diff --git a/components/forms/WebsiteEditForm.js b/components/forms/WebsiteEditForm.js index 8e1abc10..1678fea8 100644 --- a/components/forms/WebsiteEditForm.js +++ b/components/forms/WebsiteEditForm.js @@ -1,12 +1,12 @@ import { SubmitButton, Form, FormInput, FormRow, FormButtons, TextField } from 'react-basics'; import { useMutation } from '@tanstack/react-query'; import { useRef } from 'react'; -import { useApi } from 'next-basics'; -import { getAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; +import { getClientAuthToken } from 'lib/client'; import { DOMAIN_REGEX } from 'lib/constants'; export default function WebsiteEditForm({ websiteId, data, onSave }) { - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error } = useMutation(data => post(`/websites/${websiteId}`, data)); const ref = useRef(null); diff --git a/components/forms/WebsiteResetForm.js b/components/forms/WebsiteResetForm.js index 7dda5f04..b8032a55 100644 --- a/components/forms/WebsiteResetForm.js +++ b/components/forms/WebsiteResetForm.js @@ -1,13 +1,13 @@ import { useMutation } from '@tanstack/react-query'; -import { getAuthToken } from 'lib/client'; -import { useApi } from 'next-basics'; +import { getClientAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; import { Button, Form, FormButtons, FormInput, SubmitButton, TextField } from 'react-basics'; import styles from './Form.module.css'; const CONFIRM_VALUE = 'RESET'; export default function WebsiteResetForm({ websiteId, onSave, onClose }) { - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, error, isLoading } = useMutation(data => post(`/websites/${websiteId}/reset`, data), ); diff --git a/components/pages/TeamDetails.js b/components/pages/TeamDetails.js index 30d54a9b..96b71a41 100644 --- a/components/pages/TeamDetails.js +++ b/components/pages/TeamDetails.js @@ -1,18 +1,18 @@ import { useEffect, useState } from 'react'; import { Breadcrumbs, Item, Tabs, useToast } from 'react-basics'; import { useQuery } from '@tanstack/react-query'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; import Link from 'next/link'; import Page from 'components/layout/Page'; import TeamEditForm from 'components/forms/TeamEditForm'; import PageHeader from 'components/layout/PageHeader'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import TeamMembersTable from '../tables/TeamMembersTable'; export default function TeamDetails({ teamId }) { const [values, setValues] = useState(null); const [tab, setTab] = useState('general'); - const { get } = useApi(getAuthToken()); + const { get } = useApi(getClientAuthToken()); const { toast, showToast } = useToast(); const { data, isLoading } = useQuery( ['team', teamId], diff --git a/components/pages/TeamsList.js b/components/pages/TeamsList.js index 30a21b95..7aae1f3a 100644 --- a/components/pages/TeamsList.js +++ b/components/pages/TeamsList.js @@ -1,18 +1,18 @@ import { useState } from 'react'; import { Button, Icon, Modal, useToast, Flexbox } from 'react-basics'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import TeamAddForm from 'components/forms/TeamAddForm'; import PageHeader from 'components/layout/PageHeader'; import TeamsTable from 'components/tables/TeamsTable'; import Page from 'components/layout/Page'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import { useQuery } from '@tanstack/react-query'; export default function TeamsList() { const [edit, setEdit] = useState(false); const [update, setUpdate] = useState(0); - const { get } = useApi(getAuthToken()); + const { get } = useApi(getClientAuthToken()); const { data, isLoading, error } = useQuery(['teams', update], () => get(`/teams`)); const hasData = data && data.length !== 0; const { toast, showToast } = useToast(); diff --git a/components/pages/UserSettings.js b/components/pages/UserSettings.js index 80705133..b74164a9 100644 --- a/components/pages/UserSettings.js +++ b/components/pages/UserSettings.js @@ -4,8 +4,8 @@ import UserEditForm from 'components/forms/UserEditForm'; import UserPasswordForm from 'components/forms/UserPasswordForm'; import Page from 'components/layout/Page'; import PageHeader from 'components/layout/PageHeader'; -import { getAuthToken } from 'lib/client'; -import { useApi } from 'next-basics'; +import { getClientAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; @@ -14,7 +14,7 @@ import { Breadcrumbs, Item, Tabs, useToast } from 'react-basics'; export default function UserSettings({ userId }) { const [values, setValues] = useState(null); const [tab, setTab] = useState('general'); - const { get } = useApi(getAuthToken()); + const { get } = useApi(getClientAuthToken()); const { toast, showToast } = useToast(); const router = useRouter(); const { data, isLoading } = useQuery( diff --git a/components/pages/UsersList.js b/components/pages/UsersList.js index 726a1cdc..e1260387 100644 --- a/components/pages/UsersList.js +++ b/components/pages/UsersList.js @@ -3,15 +3,15 @@ import PageHeader from 'components/layout/PageHeader'; import UsersTable from 'components/tables/UsersTable'; import { useState } from 'react'; import { Button, Icon, useToast } from 'react-basics'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import { useMutation } from '@tanstack/react-query'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; export default function UsersList() { const [loading, setLoading] = useState(false); const [error, setError] = useState(); const { toast, showToast } = useToast(); - const { post } = useApi(getAuthToken()); + const { post } = useApi(getClientAuthToken()); const { mutate, isLoading } = useMutation(data => post('/api-key', data)); const handleSave = () => { diff --git a/components/pages/WebsiteSettings.js b/components/pages/WebsiteSettings.js index 3dcd8a59..d9d0b139 100644 --- a/components/pages/WebsiteSettings.js +++ b/components/pages/WebsiteSettings.js @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { Breadcrumbs, Item, Tabs, useToast, Button, Icon } from 'react-basics'; import { useQuery } from '@tanstack/react-query'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; import Link from 'next/link'; import Page from 'components/layout/Page'; import WebsiteEditForm from 'components/forms/WebsiteEditForm'; @@ -9,13 +9,13 @@ import WebsiteReset from 'components/forms/WebsiteReset'; import PageHeader from 'components/layout/PageHeader'; import TrackingCodeForm from 'components/forms/TrackingCodeForm'; import ShareUrlForm from 'components/forms/ShareUrlForm'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import ExternalLink from 'assets/external-link.svg'; export default function Websites({ websiteId }) { const [values, setValues] = useState(null); const [tab, setTab] = useState('general'); - const { get } = useApi(getAuthToken()); + const { get } = useApi(getClientAuthToken()); const { toast, showToast } = useToast(); const { data, isLoading } = useQuery( ['website', websiteId], diff --git a/components/pages/WebsitesList.js b/components/pages/WebsitesList.js index 0bb5f854..ead1217f 100644 --- a/components/pages/WebsitesList.js +++ b/components/pages/WebsitesList.js @@ -1,19 +1,19 @@ import { useState } from 'react'; import { Button, Icon, Modal, useToast, Flexbox } from 'react-basics'; -import { useApi } from 'next-basics'; +import useApi from 'hooks/useApi'; import { useQuery } from '@tanstack/react-query'; import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import WebsiteAddForm from 'components/forms/WebsiteAddForm'; import PageHeader from 'components/layout/PageHeader'; import WebsitesTable from 'components/tables/WebsitesTable'; import Page from 'components/layout/Page'; -import { getAuthToken } from 'lib/client'; +import { getClientAuthToken } from 'lib/client'; import useUser from 'hooks/useUser'; export default function WebsitesList() { const [edit, setEdit] = useState(false); const [update, setUpdate] = useState(0); - const { get } = useApi(getAuthToken()); + const { get } = useApi(getClientAuthToken()); const { user } = useUser(); const { data, isLoading, error } = useQuery(['websites', update], () => get(`/users/${user.id}/websites`), diff --git a/components/tables/UsersTable.js b/components/tables/UsersTable.js index 9baf04e3..ee5de9b3 100644 --- a/components/tables/UsersTable.js +++ b/components/tables/UsersTable.js @@ -1,8 +1,8 @@ import { useQuery } from '@tanstack/react-query'; import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import { formatDistance } from 'date-fns'; -import { getAuthToken } from 'lib/client'; -import { useApi } from 'next-basics'; +import { getClientAuthToken } from 'lib/client'; +import useApi from 'hooks/useApi'; import Link from 'next/link'; import { useEffect, useState } from 'react'; import { @@ -26,7 +26,7 @@ const defaultColumns = [ export default function UsersTable({ columns = defaultColumns, onLoading, onAddKeyClick }) { const [values, setValues] = useState(null); - const { get } = useApi(getAuthToken()); + const { get } = useApi(getClientAuthToken()); const { data, isLoading, error } = useQuery(['user'], () => get(`/users`)); const hasData = data && data.length !== 0; diff --git a/lib/array.js b/lib/array.js deleted file mode 100644 index c468168d..00000000 --- a/lib/array.js +++ /dev/null @@ -1,18 +0,0 @@ -export function chunk(arr, size) { - const chunks = []; - - let index = 0; - while (index < arr.length) { - chunks.push(arr.slice(index, size + index)); - index += size; - } - - return chunks; -} - -export function sortArrayByMap(arr, map = [], key) { - if (!arr) return []; - if (map.length === 0) return arr; - - return map.map(id => arr.find(item => item[key] === id)); -} diff --git a/lib/client.ts b/lib/client.ts index df68c6f8..8c69d23d 100644 --- a/lib/client.ts +++ b/lib/client.ts @@ -1,14 +1,14 @@ import { getItem, setItem, removeItem } from 'next-basics'; import { AUTH_TOKEN } from './constants'; -export function getAuthToken() { +export function getClientAuthToken() { return getItem(AUTH_TOKEN); } -export function setAuthToken(token) { +export function setClientAuthToken(token) { setItem(AUTH_TOKEN, token); } -export function removeAuthToken() { +export function removeClientAuthToken() { removeItem(AUTH_TOKEN); } diff --git a/lib/request.js b/lib/detect.js similarity index 100% rename from lib/request.js rename to lib/detect.js diff --git a/lib/middleware.js b/lib/middleware.ts similarity index 93% rename from lib/middleware.js rename to lib/middleware.ts index 1d8ff807..ce6aea25 100644 --- a/lib/middleware.js +++ b/lib/middleware.ts @@ -21,7 +21,7 @@ export const useSession = createMiddleware(async (req, res, next) => { return badRequest(res); } - req.session = session; + (req as any).session = session; next(); }); @@ -50,6 +50,6 @@ export const useAuth = createMiddleware(async (req, res, next) => { user.isAdmin = user.role === ROLES.admin; } - req.auth = { user, token, shareToken, key }; + (req as any).auth = { user, token, shareToken, key }; next(); }); diff --git a/lib/session.js b/lib/session.js index 153b524c..f6698480 100644 --- a/lib/session.js +++ b/lib/session.js @@ -3,7 +3,7 @@ import { validate } from 'uuid'; import { secret, uuid } from 'lib/crypto'; import cache from 'lib/cache'; import clickhouse from 'lib/clickhouse'; -import { getClientInfo, getJsonBody } from 'lib/request'; +import { getClientInfo, getJsonBody } from 'lib/detect'; import { createSession, getSession, getWebsite } from 'queries'; export async function findSession(req) { diff --git a/pages/api/collect.ts b/pages/api/collect.ts index 4c989e9b..ab817ef1 100644 --- a/pages/api/collect.ts +++ b/pages/api/collect.ts @@ -4,7 +4,7 @@ import ipaddr from 'ipaddr.js'; import { createToken, unauthorized, send, badRequest, forbidden } from 'next-basics'; import { savePageView, saveEvent } from 'queries'; import { useCors, useSession } from 'lib/middleware'; -import { getJsonBody, getIpAddress } from 'lib/request'; +import { getJsonBody, getIpAddress } from 'lib/detect'; import { secret } from 'lib/crypto'; import { NextApiRequest, NextApiResponse } from 'next'; diff --git a/pages/logout.js b/pages/logout.js index a91205a4..6d486022 100644 --- a/pages/logout.js +++ b/pages/logout.js @@ -1,8 +1,8 @@ import { useEffect } from 'react'; import { useRouter } from 'next/router'; -import { removeItem, useApi } from 'next-basics'; -import { AUTH_TOKEN } from 'lib/constants'; +import useApi from 'hooks/useApi'; import { setUser } from 'store/app'; +import { removeClientAuthToken } from 'lib/client'; export default function LogoutPage() { const router = useRouter(); @@ -13,7 +13,7 @@ export default function LogoutPage() { await post('/logout'); } - removeItem(AUTH_TOKEN); + removeClientAuthToken(); logout();