Compare commits
8 Commits
3847fd1896
...
06672714b7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06672714b7 | ||
|
|
2f8b5dbe0f | ||
|
|
09f8669553 | ||
|
|
731b36ef70 | ||
|
|
305c2cf140 | ||
|
|
6edca07fa6 | ||
|
|
d65aed6828 | ||
|
|
ab3f748195 |
@ -29,19 +29,27 @@ const dataResponseSchema = z.object({
|
||||
})
|
||||
|
||||
export type TNewsResponse = z.infer<typeof newsResponseSchema>
|
||||
export type TNewsResponseData = z.infer<typeof dataResponseSchema>
|
||||
export type TAuthorResponse = z.infer<typeof authorSchema>
|
||||
type TParameters = {
|
||||
categories?: string[]
|
||||
tags?: string[]
|
||||
active?: boolean
|
||||
limit?: number
|
||||
page?: number
|
||||
} & THttpServer
|
||||
|
||||
export const getNews = async (parameters?: TParameters) => {
|
||||
const { categories, tags, ...restParameters } = parameters || {}
|
||||
const { categories, tags, active, limit, page, ...restParameters } =
|
||||
parameters || {}
|
||||
try {
|
||||
const { data } = await HttpServer(restParameters).get(`/api/news`, {
|
||||
params: {
|
||||
...(categories && { categories: categories.join('+') }),
|
||||
...(tags && { tags: tags.join('+') }),
|
||||
...(active && { active }),
|
||||
...(limit && { limit }),
|
||||
...(page && { page }),
|
||||
},
|
||||
})
|
||||
return dataResponseSchema.parse(data)
|
||||
|
||||
10
app/components/error/await.tsx
Normal file
10
app/components/error/await.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { useAsyncError } from 'react-router'
|
||||
|
||||
export const ErrorAwait = () => {
|
||||
const error = useAsyncError()
|
||||
return (
|
||||
<p>
|
||||
{error instanceof Error ? error.message : 'An unexpected error occurred.'}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
@ -1,15 +1,17 @@
|
||||
import useEmblaCarousel from 'embla-carousel-react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useRouteLoaderData } from 'react-router'
|
||||
import { Suspense, useCallback, useEffect, useState } from 'react'
|
||||
import { Await, useRouteLoaderData } from 'react-router'
|
||||
import { stripHtml } from 'string-strip-html'
|
||||
|
||||
import { Button } from '~/components/ui/button'
|
||||
import { ErrorAwait } from '~/components/error/await'
|
||||
import { CarouselButton } from '~/components/ui/button-slide'
|
||||
import { useNewsContext } from '~/contexts/news'
|
||||
import type { loader } from '~/routes/_news'
|
||||
import type { TNews } from '~/types/news'
|
||||
import { getPremiumAttribute } from '~/utils/render'
|
||||
|
||||
import { Button } from './button'
|
||||
|
||||
export const CarouselHero = (properties: TNews) => {
|
||||
const { setIsSuccessOpen } = useNewsContext()
|
||||
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
|
||||
@ -72,43 +74,55 @@ export const CarouselHero = (properties: TNews) => {
|
||||
ref={emblaReference}
|
||||
>
|
||||
<div className="embla__container hero flex sm:gap-x-8">
|
||||
{items.map(
|
||||
({ featured_image, title, content, slug, is_premium }, index) => (
|
||||
<div
|
||||
className="embla__slide hero w-full min-w-0 flex-none"
|
||||
key={index}
|
||||
>
|
||||
<div className="max-sm:mt-2 sm:flex">
|
||||
<img
|
||||
className="col-span-2 aspect-[174/100] object-cover"
|
||||
src={featured_image}
|
||||
alt={title}
|
||||
/>
|
||||
<div className="flex h-full flex-col justify-between gap-7 sm:px-5">
|
||||
<div>
|
||||
<h3 className="mt-2 w-full text-2xl font-bold sm:mt-0 sm:text-4xl">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="text-md mt-5 line-clamp-10 text-[#777777] sm:text-xl">
|
||||
{stripHtml(content).result}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
size="block"
|
||||
{...getPremiumAttribute({
|
||||
isPremium: is_premium,
|
||||
slug,
|
||||
onClick: () => setIsSuccessOpen('warning'),
|
||||
userData,
|
||||
})}
|
||||
<Suspense fallback={<div>Loading...</div>}>
|
||||
<Await
|
||||
resolve={items}
|
||||
errorElement={<ErrorAwait />}
|
||||
>
|
||||
{(value) =>
|
||||
value.data.map(
|
||||
(
|
||||
{ featured_image, title, content, slug, is_premium },
|
||||
index,
|
||||
) => (
|
||||
<div
|
||||
className="embla__slide hero w-full min-w-0 flex-none"
|
||||
key={index}
|
||||
>
|
||||
View More
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
<div className="max-sm:mt-2 sm:flex">
|
||||
<img
|
||||
className="col-span-2 aspect-[174/100] object-cover"
|
||||
src={featured_image}
|
||||
alt={title}
|
||||
/>
|
||||
<div className="flex h-full flex-col justify-between gap-7 sm:px-5">
|
||||
<div>
|
||||
<h3 className="mt-2 w-full text-2xl font-bold sm:mt-0 sm:text-4xl">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="text-md mt-5 line-clamp-10 text-[#777777] sm:text-xl">
|
||||
{stripHtml(content).result}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
size="block"
|
||||
{...getPremiumAttribute({
|
||||
isPremium: is_premium,
|
||||
slug,
|
||||
onClick: () => setIsSuccessOpen('warning'),
|
||||
userData,
|
||||
})}
|
||||
>
|
||||
View More
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
)
|
||||
}
|
||||
</Await>
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import useEmblaCarousel from 'embla-carousel-react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useRouteLoaderData } from 'react-router'
|
||||
import { Suspense, useCallback, useEffect, useState } from 'react'
|
||||
import { Await, useRouteLoaderData } from 'react-router'
|
||||
import { stripHtml } from 'string-strip-html'
|
||||
|
||||
import { Button } from '~/components/ui/button'
|
||||
import { ErrorAwait } from '~/components/error/await'
|
||||
import { CarouselButton } from '~/components/ui/button-slide'
|
||||
import { useNewsContext } from '~/contexts/news'
|
||||
import type { loader } from '~/routes/_news'
|
||||
import type { TNews } from '~/types/news'
|
||||
import { getPremiumAttribute } from '~/utils/render'
|
||||
|
||||
import { Button } from './button'
|
||||
import { Tags } from './tags'
|
||||
|
||||
export const CarouselSection = (properties: TNews) => {
|
||||
@ -79,50 +80,59 @@ export const CarouselSection = (properties: TNews) => {
|
||||
ref={emblaReference}
|
||||
>
|
||||
<div className="embla__container col-span-3 flex max-h-[586px] sm:gap-x-8">
|
||||
{items.map(
|
||||
(
|
||||
{ featured_image, title, content, tags, slug, is_premium },
|
||||
index,
|
||||
) => (
|
||||
<div
|
||||
className="embla__slide w-full min-w-0 flex-none sm:w-1/3"
|
||||
key={index}
|
||||
>
|
||||
<div className="flex flex-col justify-between gap-3">
|
||||
<img
|
||||
className="aspect-[174/100] max-h-[280px] w-full rounded-md object-cover sm:aspect-[5/4]"
|
||||
src={featured_image}
|
||||
alt={title}
|
||||
/>
|
||||
<div className={'flex flex-col justify-between gap-4'}>
|
||||
<div className="flex h-28 flex-col items-start justify-center gap-4">
|
||||
<Tags
|
||||
tags={tags || []}
|
||||
is_premium={is_premium}
|
||||
/>
|
||||
<h3 className="mt-2 line-clamp-2 w-full text-xl font-bold sm:text-2xl lg:mt-0">
|
||||
{title}
|
||||
</h3>
|
||||
</div>
|
||||
<p className="text-md line-clamp-3 text-[#777777] sm:text-xl">
|
||||
{stripHtml(content).result}
|
||||
</p>
|
||||
<Button
|
||||
size="block"
|
||||
{...getPremiumAttribute({
|
||||
isPremium: is_premium,
|
||||
slug,
|
||||
onClick: () => setIsSuccessOpen('warning'),
|
||||
userData,
|
||||
})}
|
||||
<Suspense fallback={<div>Loading...</div>}>
|
||||
<Await
|
||||
resolve={items}
|
||||
errorElement={<ErrorAwait />}
|
||||
>
|
||||
{(value) =>
|
||||
value.data.map(
|
||||
(
|
||||
{ featured_image, title, content, tags, slug, is_premium },
|
||||
index,
|
||||
) => (
|
||||
<div
|
||||
className="embla__slide w-full min-w-0 flex-none sm:w-1/3"
|
||||
key={index}
|
||||
>
|
||||
View More
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
<div className="flex flex-col justify-between gap-3">
|
||||
<img
|
||||
className="aspect-[174/100] max-h-[280px] w-full rounded-md object-cover sm:aspect-[5/4]"
|
||||
src={featured_image}
|
||||
alt={title}
|
||||
/>
|
||||
<div className={'flex flex-col justify-between gap-4'}>
|
||||
<div className="flex h-28 flex-col items-start justify-center gap-4">
|
||||
<Tags
|
||||
tags={tags || []}
|
||||
is_premium={is_premium}
|
||||
/>
|
||||
<h3 className="mt-2 line-clamp-2 w-full text-xl font-bold sm:text-2xl lg:mt-0">
|
||||
{title}
|
||||
</h3>
|
||||
</div>
|
||||
<p className="text-md line-clamp-3 text-[#777777] sm:text-xl">
|
||||
{stripHtml(content).result}
|
||||
</p>
|
||||
<Button
|
||||
size="block"
|
||||
{...getPremiumAttribute({
|
||||
isPremium: is_premium,
|
||||
slug,
|
||||
onClick: () => setIsSuccessOpen('warning'),
|
||||
userData,
|
||||
})}
|
||||
>
|
||||
View More
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
)
|
||||
}
|
||||
</Await>
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,23 +1,19 @@
|
||||
import { useRouteLoaderData } from 'react-router'
|
||||
import { Suspense } from 'react'
|
||||
import { Await, useRouteLoaderData } from 'react-router'
|
||||
import { stripHtml } from 'string-strip-html'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
import type { TNewsResponse } from '~/apis/common/get-news'
|
||||
import { ErrorAwait } from '~/components/error/await'
|
||||
import { CarouselNextIcon } from '~/components/icons/carousel-next'
|
||||
import { CarouselPreviousIcon } from '~/components/icons/carousel-previous'
|
||||
import { Button } from '~/components/ui/button'
|
||||
import { useNewsContext } from '~/contexts/news'
|
||||
import type { loader } from '~/routes/_news'
|
||||
import type { TNews } from '~/types/news'
|
||||
import { getPremiumAttribute } from '~/utils/render'
|
||||
|
||||
import { Tags } from './tags'
|
||||
|
||||
type TNews = {
|
||||
title: string
|
||||
description: string
|
||||
items: TNewsResponse[]
|
||||
}
|
||||
|
||||
export const CategorySection = (properties: TNews) => {
|
||||
const { setIsSuccessOpen } = useNewsContext()
|
||||
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
|
||||
@ -47,56 +43,67 @@ export const CategorySection = (properties: TNews) => {
|
||||
</div>
|
||||
|
||||
<div className="grid sm:grid-cols-3 sm:gap-x-8">
|
||||
{items.map(
|
||||
(
|
||||
{ featured_image, title, content, tags, slug, is_premium },
|
||||
index,
|
||||
) => (
|
||||
<div
|
||||
key={index}
|
||||
className={twMerge('grid gap-3 sm:gap-x-8')}
|
||||
>
|
||||
<img
|
||||
className={twMerge(
|
||||
'aspect-[174/100] w-full rounded-md object-cover sm:aspect-[5/4]',
|
||||
)}
|
||||
src={featured_image}
|
||||
alt={title}
|
||||
/>
|
||||
<div className={twMerge('flex flex-col justify-between gap-4')}>
|
||||
<Tags
|
||||
tags={tags}
|
||||
is_premium={is_premium}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<h3
|
||||
className={twMerge(
|
||||
'mt-2 w-full text-xl font-bold sm:mt-0 sm:text-2xl',
|
||||
)}
|
||||
<Suspense fallback={<div>Loading...</div>}>
|
||||
<Await
|
||||
resolve={items}
|
||||
errorElement={<ErrorAwait />}
|
||||
>
|
||||
{(value) =>
|
||||
value.data.map(
|
||||
(
|
||||
{ featured_image, title, content, tags, slug, is_premium },
|
||||
index,
|
||||
) => (
|
||||
<div
|
||||
key={index}
|
||||
className={twMerge('grid gap-3 sm:gap-x-8')}
|
||||
>
|
||||
{title}
|
||||
</h3>
|
||||
<p className="text-md mt-5 line-clamp-3 text-[#777777] sm:text-xl">
|
||||
{stripHtml(content).result}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
size="block"
|
||||
{...getPremiumAttribute({
|
||||
isPremium: is_premium,
|
||||
slug,
|
||||
onClick: () => setIsSuccessOpen('warning'),
|
||||
userData,
|
||||
})}
|
||||
className="mb-5"
|
||||
>
|
||||
View More
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
<img
|
||||
className={twMerge(
|
||||
'aspect-[174/100] w-full rounded-md object-cover sm:aspect-[5/4]',
|
||||
)}
|
||||
src={featured_image}
|
||||
alt={title}
|
||||
/>
|
||||
<div
|
||||
className={twMerge('flex flex-col justify-between gap-4')}
|
||||
>
|
||||
<Tags
|
||||
tags={tags}
|
||||
is_premium={is_premium}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<h3
|
||||
className={twMerge(
|
||||
'mt-2 w-full text-xl font-bold sm:mt-0 sm:text-2xl',
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</h3>
|
||||
<p className="text-md mt-5 line-clamp-3 text-[#777777] sm:text-xl">
|
||||
{stripHtml(content).result}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
size="block"
|
||||
{...getPremiumAttribute({
|
||||
isPremium: is_premium,
|
||||
slug,
|
||||
onClick: () => setIsSuccessOpen('warning'),
|
||||
userData,
|
||||
})}
|
||||
className="mb-5"
|
||||
>
|
||||
View More
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
)
|
||||
}
|
||||
</Await>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
<div className="my-5 mt-5 flex flex-row-reverse">
|
||||
|
||||
@ -2,10 +2,14 @@ import xior, { merge } from 'xior'
|
||||
|
||||
const baseURL = import.meta.env.VITE_API_URL
|
||||
|
||||
export type THttpServer = { accessToken?: string }
|
||||
export type THttpServer = {
|
||||
accessToken?: string
|
||||
ipAddress?: string | null
|
||||
userAgent?: string | null
|
||||
}
|
||||
|
||||
export const HttpServer = (parameters?: THttpServer) => {
|
||||
const { accessToken } = parameters || {}
|
||||
const { accessToken, ipAddress, userAgent } = parameters || {}
|
||||
const instance = xior.create({
|
||||
baseURL,
|
||||
})
|
||||
@ -16,6 +20,8 @@ export const HttpServer = (parameters?: THttpServer) => {
|
||||
return merge(config, {
|
||||
headers: {
|
||||
...(accessToken && { Authorization: `Bearer ${accessToken}` }),
|
||||
...(ipAddress && { 'X-Ip-Address': ipAddress }),
|
||||
...(userAgent && { 'X-User-Agent': userAgent }),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@ -17,7 +17,7 @@ export const NewsCategoriesPage = () => {
|
||||
<CategorySection
|
||||
title={name || ''}
|
||||
description={description || ''}
|
||||
items={newsData || []}
|
||||
items={newsData || Promise.resolve({ data: [] })}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
@ -21,7 +21,7 @@ export const NewsDetailPage = () => {
|
||||
const berita: TNews = {
|
||||
title: loaderData?.beritaCategory?.name || '',
|
||||
description: loaderData?.beritaCategory?.description || '',
|
||||
items: loaderData?.beritaNews || [],
|
||||
items: loaderData?.beritaData || Promise.resolve({ data: [] }),
|
||||
}
|
||||
const currentUrl = globalThis.location
|
||||
const { title, content, featured_image, author, live_at, tags } =
|
||||
|
||||
@ -12,17 +12,17 @@ export const NewsPage = () => {
|
||||
const spotlight: TNews = {
|
||||
title: loaderData?.spotlightCategory?.name || '',
|
||||
description: loaderData?.spotlightCategory?.description || '',
|
||||
items: loaderData?.spotlightNews || [],
|
||||
items: loaderData?.spotlightData || Promise.resolve({ data: [] }),
|
||||
}
|
||||
const berita: TNews = {
|
||||
title: loaderData?.beritaCategory?.name || '',
|
||||
description: loaderData?.beritaCategory?.description || '',
|
||||
items: loaderData?.beritaNews || [],
|
||||
items: loaderData?.beritaData || Promise.resolve({ data: [] }),
|
||||
}
|
||||
const kajian: TNews = {
|
||||
title: loaderData?.kajianCategory?.name || '',
|
||||
description: loaderData?.kajianCategory?.description || '',
|
||||
items: loaderData?.kajianNews || [],
|
||||
items: loaderData?.kajianData || Promise.resolve({ data: [] }),
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -25,31 +25,25 @@ export const loader = async ({}: Route.LoaderArgs) => {
|
||||
(category) => category.code === kajianCode,
|
||||
)
|
||||
|
||||
let { data: spotlightNews } = await getNews({
|
||||
const spotlightData = getNews({
|
||||
categories: [spotlightCode],
|
||||
active: true,
|
||||
})
|
||||
spotlightNews = spotlightNews.filter(
|
||||
(news) => new Date(news.live_at) <= new Date(),
|
||||
)
|
||||
let { data: beritaNews } = await getNews({
|
||||
const beritaData = getNews({
|
||||
categories: [beritaCode],
|
||||
active: true,
|
||||
})
|
||||
beritaNews = beritaNews.filter((news) => new Date(news.live_at) <= new Date())
|
||||
let { data: kajianNews } = await getNews({
|
||||
const kajianData = getNews({
|
||||
categories: [kajianCode],
|
||||
active: true,
|
||||
})
|
||||
kajianNews = kajianNews.filter((news) => new Date(news.live_at) <= new Date())
|
||||
|
||||
return {
|
||||
spotlightCategory,
|
||||
spotlightCode,
|
||||
beritaCategory,
|
||||
beritaCode,
|
||||
kajianCategory,
|
||||
kajianCode,
|
||||
spotlightNews,
|
||||
beritaNews,
|
||||
kajianNews,
|
||||
spotlightData,
|
||||
beritaData,
|
||||
kajianData,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,7 @@ export const loader = async ({ params }: Route.LoaderArgs) => {
|
||||
const { data: categoriesData } = await getCategories()
|
||||
const { code } = params
|
||||
const categoryData = categoriesData.find((category) => category.code === code)
|
||||
let { data: newsData } = await getNews({ categories: [code] })
|
||||
newsData = newsData.filter((news) => new Date(news.live_at) <= new Date())
|
||||
const newsData = getNews({ categories: [code], active: true })
|
||||
return { categoryData, newsData }
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { isRouteErrorResponse } from 'react-router'
|
||||
import { getClientIPAddress } from 'remix-utils/get-client-ip-address'
|
||||
import { stripHtml } from 'string-strip-html'
|
||||
|
||||
import { getCategories } from '~/apis/common/get-categories'
|
||||
@ -12,6 +13,8 @@ import { NewsDetailPage } from '~/pages/news-detail'
|
||||
import type { Route } from './+types/_news.detail.$slug'
|
||||
|
||||
export const loader = async ({ request, params }: Route.LoaderArgs) => {
|
||||
const userAgent = request.headers.get('user-agent')
|
||||
const ipAddress = getClientIPAddress(request) || 'localhost'
|
||||
const { userToken: accessToken } = await handleCookie(request)
|
||||
let userData
|
||||
if (accessToken) {
|
||||
@ -19,7 +22,12 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
|
||||
userData = data
|
||||
}
|
||||
const { slug } = params
|
||||
let { data: newsDetailData } = await getNewsBySlug({ slug, accessToken })
|
||||
let { data: newsDetailData } = await getNewsBySlug({
|
||||
slug,
|
||||
accessToken,
|
||||
userAgent,
|
||||
ipAddress,
|
||||
})
|
||||
const shouldSubscribe =
|
||||
(!accessToken || userData?.subscribe?.subscribe_plan?.code === 'basic') &&
|
||||
newsDetailData?.is_premium
|
||||
@ -34,13 +42,12 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
|
||||
const beritaCategory = categoriesData.find(
|
||||
(category) => category.code === beritaCode,
|
||||
)
|
||||
let { data: beritaNews } = await getNews({ categories: [beritaCode] })
|
||||
beritaNews = beritaNews.filter((news) => new Date(news.live_at) <= new Date())
|
||||
const beritaData = getNews({ categories: [beritaCode], active: true })
|
||||
|
||||
return {
|
||||
newsDetailData,
|
||||
beritaCategory,
|
||||
beritaNews,
|
||||
beritaData,
|
||||
shouldSubscribe,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { data } from 'react-router'
|
||||
import { getClientIPAddress } from 'remix-utils/get-client-ip-address'
|
||||
import { XiorError } from 'xior'
|
||||
|
||||
import { createLogAdsRequest } from '~/apis/news/create-log-ads'
|
||||
@ -7,12 +8,16 @@ import { handleCookie } from '~/libs/cookies'
|
||||
import type { Route } from './+types/actions.log.ads.$id'
|
||||
|
||||
export const action = async ({ request, params }: Route.ActionArgs) => {
|
||||
const userAgent = request.headers.get('user-agent')
|
||||
const ipAddress = getClientIPAddress(request) || 'localhost'
|
||||
const { userToken: accessToken } = await handleCookie(request)
|
||||
const { id } = params
|
||||
try {
|
||||
const { data: logsData } = await createLogAdsRequest({
|
||||
id,
|
||||
accessToken,
|
||||
userAgent,
|
||||
ipAddress,
|
||||
})
|
||||
|
||||
return data(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { TNewsResponse } from '~/apis/common/get-news'
|
||||
import type { TNewsResponseData } from '~/apis/common/get-news'
|
||||
|
||||
export type TNews = {
|
||||
title: string
|
||||
description: string
|
||||
items: TNewsResponse[]
|
||||
items: Promise<TNewsResponseData>
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { decodeJwt } from 'jose'
|
||||
import { JWT } from '@edgefirst-dev/jwt'
|
||||
|
||||
import {
|
||||
staffTokenCookieConfig,
|
||||
@ -12,10 +12,10 @@ type TTokenCookie = {
|
||||
export const generateUserTokenCookie = (parameters: TTokenCookie) => {
|
||||
const { accessToken } = parameters
|
||||
|
||||
const decodedToken = decodeJwt(accessToken)
|
||||
const decodedToken = JWT.decode(accessToken)
|
||||
const decodedTokenExp = decodedToken.exp
|
||||
const expirationDate = decodedTokenExp
|
||||
? new Date(decodedTokenExp * 1000)
|
||||
? new Date(Number(decodedTokenExp) * 1000)
|
||||
: undefined
|
||||
|
||||
return userTokenCookieConfig.serialize(accessToken, {
|
||||
@ -26,10 +26,10 @@ export const generateUserTokenCookie = (parameters: TTokenCookie) => {
|
||||
export const generateStaffTokenCookie = (parameters: TTokenCookie) => {
|
||||
const { accessToken } = parameters
|
||||
|
||||
const decodedToken = decodeJwt(accessToken)
|
||||
const decodedToken = JWT.decode(accessToken)
|
||||
const decodedTokenExp = decodedToken.exp
|
||||
const expirationDate = decodedTokenExp
|
||||
? new Date(decodedTokenExp * 1000)
|
||||
? new Date(Number(decodedTokenExp) * 1000)
|
||||
: undefined
|
||||
|
||||
return staffTokenCookieConfig.serialize(accessToken, {
|
||||
|
||||
@ -14,10 +14,15 @@
|
||||
"validate": "pnpm lint && pnpm typecheck && pnpm knip"
|
||||
},
|
||||
"dependencies": {
|
||||
"@edgefirst-dev/batcher": "^1.0.1",
|
||||
"@edgefirst-dev/jwt": "^1.2.0",
|
||||
"@edgefirst-dev/server-timing": "^0.0.1",
|
||||
"@headlessui/react": "^2.2.0",
|
||||
"@heroicons/react": "^2.2.0",
|
||||
"@hookform/resolvers": "^4.1.1",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@oslojs/crypto": "^1.0.1",
|
||||
"@oslojs/encoding": "^1.1.0",
|
||||
"@react-router/fs-routes": "^7.1.3",
|
||||
"@react-router/node": "^7.1.3",
|
||||
"@react-router/serve": "^7.1.3",
|
||||
@ -37,8 +42,9 @@
|
||||
"embla-carousel-autoplay": "^8.5.2",
|
||||
"embla-carousel-react": "^8.5.2",
|
||||
"html-react-parser": "^5.2.2",
|
||||
"intl-parse-accept-language": "^1.0.0",
|
||||
"is-ip": "^5.0.1",
|
||||
"isbot": "^5.1.17",
|
||||
"jose": "^6.0.8",
|
||||
"react": "^19.0.0",
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
"react-colorful": "^5.6.1",
|
||||
@ -49,6 +55,7 @@
|
||||
"react-router": "^7.1.3",
|
||||
"react-share": "^5.2.2",
|
||||
"remix-hook-form": "^6.1.3",
|
||||
"remix-utils": "^8.5.0",
|
||||
"string-strip-html": "^13.4.12",
|
||||
"tailwind-merge": "^3.0.1",
|
||||
"xior": "^0.6.3",
|
||||
|
||||
225
pnpm-lock.yaml
generated
225
pnpm-lock.yaml
generated
@ -8,6 +8,15 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@edgefirst-dev/batcher':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
'@edgefirst-dev/jwt':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
'@edgefirst-dev/server-timing':
|
||||
specifier: ^0.0.1
|
||||
version: 0.0.1
|
||||
'@headlessui/react':
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
@ -20,6 +29,12 @@ importers:
|
||||
'@monaco-editor/react':
|
||||
specifier: ^4.7.0
|
||||
version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
'@oslojs/crypto':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
'@oslojs/encoding':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0
|
||||
'@react-router/fs-routes':
|
||||
specifier: ^7.1.3
|
||||
version: 7.1.3(@react-router/dev@7.1.3(@react-router/serve@7.1.3(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3))(@types/node@20.17.16)(babel-plugin-macros@3.1.0)(lightningcss@1.29.1)(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3)(vite@5.4.14(@types/node@20.17.16)(lightningcss@1.29.1)))(typescript@5.7.3)
|
||||
@ -77,12 +92,15 @@ importers:
|
||||
html-react-parser:
|
||||
specifier: ^5.2.2
|
||||
version: 5.2.2(@types/react@19.0.8)(react@19.0.0)
|
||||
intl-parse-accept-language:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
is-ip:
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.1
|
||||
isbot:
|
||||
specifier: ^5.1.17
|
||||
version: 5.1.22
|
||||
jose:
|
||||
specifier: ^6.0.8
|
||||
version: 6.0.8
|
||||
react:
|
||||
specifier: ^19.0.0
|
||||
version: 19.0.0
|
||||
@ -113,6 +131,9 @@ importers:
|
||||
remix-hook-form:
|
||||
specifier: ^6.1.3
|
||||
version: 6.1.3(react-dom@19.0.0(react@19.0.0))(react-hook-form@7.54.2(react@19.0.0))(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
|
||||
remix-utils:
|
||||
specifier: ^8.5.0
|
||||
version: 8.5.0(@edgefirst-dev/batcher@1.0.1)(@edgefirst-dev/jwt@1.2.0)(@edgefirst-dev/server-timing@0.0.1)(@oslojs/crypto@1.0.1)(@oslojs/encoding@1.1.0)(intl-parse-accept-language@1.0.0)(is-ip@5.0.1)(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(zod@3.24.2)
|
||||
string-strip-html:
|
||||
specifier: ^13.4.12
|
||||
version: 13.4.12
|
||||
@ -448,6 +469,22 @@ packages:
|
||||
resolution: {integrity: sha512-DSHae2obMSMkAtTBSOulg5X7/z+rGLxcXQIkg3OmWvY6wifojge5uVMydfhUvs7yQj+V7jNmRZ2Xzl8GJyqRgg==}
|
||||
engines: {node: '>=v18'}
|
||||
|
||||
'@edgefirst-dev/batcher@1.0.1':
|
||||
resolution: {integrity: sha512-9AsnqLSIbO0mK7Du6lRp3v7hCJuercNo7t16leZeMCnI3QReZDE2IEtbLpDwrIrcOS7xt1vgdonKYU9GQqittw==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@edgefirst-dev/data@0.0.4':
|
||||
resolution: {integrity: sha512-VLhlvEPDJ0Sd0pE6sAYTQkIqZCXVonaWlgRJIQQHzfjTXCadF77qqHj5NxaPSc4wCul0DJO/0MnejVqJAXUiRg==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@edgefirst-dev/jwt@1.2.0':
|
||||
resolution: {integrity: sha512-MnNceBAmJYhoctIAGYivh0/sSsKYXfEPfwGZ8tsoX96+vSRuoeLrBi4p2L9NHCjqxMafd4KMKk+93SfX3sW7dQ==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@edgefirst-dev/server-timing@0.0.1':
|
||||
resolution: {integrity: sha512-WlvF/dhgM7CE9SOb3Ji6Wj4PsIk21CHvXzRVdQwmeS1eVEVimWqagiYuV5e8/7Owt7SDFpeVnuF0q2CtONch0g==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@emotion/babel-plugin@11.13.5':
|
||||
resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==}
|
||||
|
||||
@ -747,6 +784,12 @@ packages:
|
||||
'@kurkle/color@0.3.4':
|
||||
resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==}
|
||||
|
||||
'@mjackson/file-storage@0.6.1':
|
||||
resolution: {integrity: sha512-H3GEVpmfmNryNoYloddIOba5OAwckfVGMvutPeI94Shbv/R+NVh89gIYa8SK3Vfa+ky9PitclP+5XQ6/zlSdQQ==}
|
||||
|
||||
'@mjackson/lazy-file@3.3.1':
|
||||
resolution: {integrity: sha512-BxpNT1KmLx0OLYfgQESx/AKGD2czwfZXh9c0SaDUQY2DRAaVYtAvSQE5EkpATFdQQKqfL+iXVoaQ/SN+w7/CDA==}
|
||||
|
||||
'@mjackson/node-fetch-server@0.2.0':
|
||||
resolution: {integrity: sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==}
|
||||
|
||||
@ -803,6 +846,18 @@ packages:
|
||||
'@one-ini/wasm@0.1.1':
|
||||
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
||||
|
||||
'@oslojs/asn1@1.0.0':
|
||||
resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==}
|
||||
|
||||
'@oslojs/binary@1.0.0':
|
||||
resolution: {integrity: sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==}
|
||||
|
||||
'@oslojs/crypto@1.0.1':
|
||||
resolution: {integrity: sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==}
|
||||
|
||||
'@oslojs/encoding@1.1.0':
|
||||
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
@ -2001,6 +2056,10 @@ packages:
|
||||
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
clone-regexp@3.0.0:
|
||||
resolution: {integrity: sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
clone@1.0.4:
|
||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
||||
engines: {node: '>=0.8'}
|
||||
@ -2081,6 +2140,10 @@ packages:
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
convert-hrtime@5.0.0:
|
||||
resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
convert-source-map@1.9.0:
|
||||
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
||||
|
||||
@ -2712,6 +2775,10 @@ packages:
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
function-timeout@0.1.1:
|
||||
resolution: {integrity: sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
function.prototype.name@1.1.8:
|
||||
resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2937,6 +3004,14 @@ packages:
|
||||
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
intl-parse-accept-language@1.0.0:
|
||||
resolution: {integrity: sha512-YFMSV91JNBOSjw1cOfw2tup6hDP7mkz+2AUV7W1L1AM6ntgI75qC1ZeFpjPGMrWp+upmBRTX2fJWQ8c7jsUWpA==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
ip-regex@5.0.0:
|
||||
resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@ -3018,6 +3093,10 @@ packages:
|
||||
resolution: {integrity: sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-ip@5.0.1:
|
||||
resolution: {integrity: sha512-FCsGHdlrOnZQcp0+XT5a+pYowf33itBalCl+7ovNXC/7o5BhIpG14M3OrpPPdBSIQJCm+0M5+9mO7S9VVTTCFw==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
is-map@2.0.3:
|
||||
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3042,6 +3121,10 @@ packages:
|
||||
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-regexp@3.1.0:
|
||||
resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
is-set@2.0.3:
|
||||
resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3463,6 +3546,10 @@ packages:
|
||||
motion-utils@11.18.1:
|
||||
resolution: {integrity: sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==}
|
||||
|
||||
mrmime@2.0.1:
|
||||
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
ms@2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
|
||||
@ -4096,6 +4183,42 @@ packages:
|
||||
react-hook-form: ^7.51.0
|
||||
react-router: '>=7.0.0'
|
||||
|
||||
remix-utils@8.5.0:
|
||||
resolution: {integrity: sha512-Wf9OGSJveBaVHKptbEgxc+DwKRUUGOH+aiaBlsrAA2b4F+gNtCkvaZzA7Tp+1esBElRcRvMZQq/0aSSWFMP18A==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
peerDependencies:
|
||||
'@edgefirst-dev/batcher': ^1.0.0
|
||||
'@edgefirst-dev/jwt': ^1.2.0
|
||||
'@edgefirst-dev/server-timing': ^0.0.1
|
||||
'@oslojs/crypto': ^1.0.1
|
||||
'@oslojs/encoding': ^1.1.0
|
||||
intl-parse-accept-language: ^1.0.0
|
||||
is-ip: ^5.0.1
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
react-router: ^7.0.0
|
||||
zod: ^3.22.4
|
||||
peerDependenciesMeta:
|
||||
'@edgefirst-dev/batcher':
|
||||
optional: true
|
||||
'@edgefirst-dev/jwt':
|
||||
optional: true
|
||||
'@edgefirst-dev/server-timing':
|
||||
optional: true
|
||||
'@oslojs/crypto':
|
||||
optional: true
|
||||
'@oslojs/encoding':
|
||||
optional: true
|
||||
intl-parse-accept-language:
|
||||
optional: true
|
||||
is-ip:
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
react-router:
|
||||
optional: true
|
||||
zod:
|
||||
optional: true
|
||||
|
||||
require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -4403,6 +4526,10 @@ packages:
|
||||
summary@2.1.0:
|
||||
resolution: {integrity: sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw==}
|
||||
|
||||
super-regex@0.2.0:
|
||||
resolution: {integrity: sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
supports-color@7.2.0:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
@ -4437,6 +4564,10 @@ packages:
|
||||
through@2.3.8:
|
||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||
|
||||
time-span@5.1.0:
|
||||
resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
tiny-invariant@1.3.3:
|
||||
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
|
||||
|
||||
@ -4507,6 +4638,10 @@ packages:
|
||||
resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
type-fest@4.37.0:
|
||||
resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
type-is@1.6.18:
|
||||
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -5105,6 +5240,21 @@ snapshots:
|
||||
'@types/conventional-commits-parser': 5.0.1
|
||||
chalk: 5.4.1
|
||||
|
||||
'@edgefirst-dev/batcher@1.0.1':
|
||||
dependencies:
|
||||
type-fest: 4.37.0
|
||||
|
||||
'@edgefirst-dev/data@0.0.4': {}
|
||||
|
||||
'@edgefirst-dev/jwt@1.2.0':
|
||||
dependencies:
|
||||
'@edgefirst-dev/data': 0.0.4
|
||||
'@mjackson/file-storage': 0.6.1
|
||||
jose: 6.0.8
|
||||
type-fest: 4.37.0
|
||||
|
||||
'@edgefirst-dev/server-timing@0.0.1': {}
|
||||
|
||||
'@emotion/babel-plugin@11.13.5':
|
||||
dependencies:
|
||||
'@babel/helper-module-imports': 7.25.9
|
||||
@ -5391,6 +5541,14 @@ snapshots:
|
||||
|
||||
'@kurkle/color@0.3.4': {}
|
||||
|
||||
'@mjackson/file-storage@0.6.1':
|
||||
dependencies:
|
||||
'@mjackson/lazy-file': 3.3.1
|
||||
|
||||
'@mjackson/lazy-file@3.3.1':
|
||||
dependencies:
|
||||
mrmime: 2.0.1
|
||||
|
||||
'@mjackson/node-fetch-server@0.2.0': {}
|
||||
|
||||
'@monaco-editor/loader@1.5.0':
|
||||
@ -5461,6 +5619,19 @@ snapshots:
|
||||
|
||||
'@one-ini/wasm@0.1.1': {}
|
||||
|
||||
'@oslojs/asn1@1.0.0':
|
||||
dependencies:
|
||||
'@oslojs/binary': 1.0.0
|
||||
|
||||
'@oslojs/binary@1.0.0': {}
|
||||
|
||||
'@oslojs/crypto@1.0.1':
|
||||
dependencies:
|
||||
'@oslojs/asn1': 1.0.0
|
||||
'@oslojs/binary': 1.0.0
|
||||
|
||||
'@oslojs/encoding@1.1.0': {}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
@ -6698,6 +6869,10 @@ snapshots:
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 7.0.0
|
||||
|
||||
clone-regexp@3.0.0:
|
||||
dependencies:
|
||||
is-regexp: 3.1.0
|
||||
|
||||
clone@1.0.4:
|
||||
optional: true
|
||||
|
||||
@ -6779,6 +6954,8 @@ snapshots:
|
||||
meow: 12.1.1
|
||||
split2: 4.2.0
|
||||
|
||||
convert-hrtime@5.0.0: {}
|
||||
|
||||
convert-source-map@1.9.0: {}
|
||||
|
||||
convert-source-map@2.0.0: {}
|
||||
@ -7576,6 +7753,8 @@ snapshots:
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
function-timeout@0.1.1: {}
|
||||
|
||||
function.prototype.name@1.1.8:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
@ -7805,6 +7984,10 @@ snapshots:
|
||||
hasown: 2.0.2
|
||||
side-channel: 1.1.0
|
||||
|
||||
intl-parse-accept-language@1.0.0: {}
|
||||
|
||||
ip-regex@5.0.0: {}
|
||||
|
||||
ipaddr.js@1.9.1: {}
|
||||
|
||||
is-array-buffer@3.0.5:
|
||||
@ -7886,6 +8069,11 @@ snapshots:
|
||||
|
||||
is-gzip@1.0.0: {}
|
||||
|
||||
is-ip@5.0.1:
|
||||
dependencies:
|
||||
ip-regex: 5.0.0
|
||||
super-regex: 0.2.0
|
||||
|
||||
is-map@2.0.3: {}
|
||||
|
||||
is-number-object@1.1.1:
|
||||
@ -7906,6 +8094,8 @@ snapshots:
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
is-regexp@3.1.0: {}
|
||||
|
||||
is-set@2.0.3: {}
|
||||
|
||||
is-shared-array-buffer@1.0.4:
|
||||
@ -8291,6 +8481,8 @@ snapshots:
|
||||
|
||||
motion-utils@11.18.1: {}
|
||||
|
||||
mrmime@2.0.1: {}
|
||||
|
||||
ms@2.0.0: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
@ -8936,6 +9128,21 @@ snapshots:
|
||||
react-hook-form: 7.54.2(react@19.0.0)
|
||||
react-router: 7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
|
||||
remix-utils@8.5.0(@edgefirst-dev/batcher@1.0.1)(@edgefirst-dev/jwt@1.2.0)(@edgefirst-dev/server-timing@0.0.1)(@oslojs/crypto@1.0.1)(@oslojs/encoding@1.1.0)(intl-parse-accept-language@1.0.0)(is-ip@5.0.1)(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(zod@3.24.2):
|
||||
dependencies:
|
||||
type-fest: 4.37.0
|
||||
optionalDependencies:
|
||||
'@edgefirst-dev/batcher': 1.0.1
|
||||
'@edgefirst-dev/jwt': 1.2.0
|
||||
'@edgefirst-dev/server-timing': 0.0.1
|
||||
'@oslojs/crypto': 1.0.1
|
||||
'@oslojs/encoding': 1.1.0
|
||||
intl-parse-accept-language: 1.0.0
|
||||
is-ip: 5.0.1
|
||||
react: 19.0.0
|
||||
react-router: 7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
zod: 3.24.2
|
||||
|
||||
require-directory@2.1.1: {}
|
||||
|
||||
require-from-string@2.0.2: {}
|
||||
@ -9300,6 +9507,12 @@ snapshots:
|
||||
|
||||
summary@2.1.0: {}
|
||||
|
||||
super-regex@0.2.0:
|
||||
dependencies:
|
||||
clone-regexp: 3.0.0
|
||||
function-timeout: 0.1.1
|
||||
time-span: 5.1.0
|
||||
|
||||
supports-color@7.2.0:
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
@ -9325,6 +9538,10 @@ snapshots:
|
||||
|
||||
through@2.3.8: {}
|
||||
|
||||
time-span@5.1.0:
|
||||
dependencies:
|
||||
convert-hrtime: 5.0.0
|
||||
|
||||
tiny-invariant@1.3.3: {}
|
||||
|
||||
tiny-lru@11.2.11: {}
|
||||
@ -9377,6 +9594,8 @@ snapshots:
|
||||
|
||||
type-fest@0.8.1: {}
|
||||
|
||||
type-fest@4.37.0: {}
|
||||
|
||||
type-is@1.6.18:
|
||||
dependencies:
|
||||
media-typer: 0.3.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user