add data table to saladeaula
This commit is contained in:
@@ -59,7 +59,7 @@ export async function loader({ context, request, params }: Route.LoaderArgs) {
|
|||||||
|
|
||||||
export default function Route({ loaderData: { data } }) {
|
export default function Route({ loaderData: { data } }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<Suspense fallback={<Skeleton />}>
|
||||||
<div className="space-y-0.5 mb-8">
|
<div className="space-y-0.5 mb-8">
|
||||||
<h1 className="text-2xl font-bold tracking-tight">Gestores</h1>
|
<h1 className="text-2xl font-bold tracking-tight">Gestores</h1>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
@@ -67,52 +67,50 @@ export default function Route({ loaderData: { data } }) {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Suspense fallback={<Skeleton />}>
|
<Await resolve={data}>
|
||||||
<Await resolve={data}>
|
{({ items }) => {
|
||||||
{({ items }) => {
|
return (
|
||||||
return (
|
<div className="grid gap-4 lg:gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<div className="grid gap-4 lg:gap-8 md:grid-cols-2 lg:grid-cols-3">
|
{items.map(({ sk, name, email }: Admin) => {
|
||||||
{items.map(({ sk, name, email }: Admin) => {
|
const [_, id] = sk.split('#')
|
||||||
const [_, id] = sk.split('#')
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
key={id}
|
key={id}
|
||||||
className="bg-card border-border/50 hover:shadow-muted-foreground/10 hover:border-muted group
|
className="bg-card border-border/50 hover:shadow-muted-foreground/10 hover:border-muted group
|
||||||
relative overflow-hidden rounded-2xl border p-8 transition-all duration-300 hover:shadow-2xl"
|
relative overflow-hidden rounded-2xl border p-8 transition-all duration-300 hover:shadow-2xl"
|
||||||
>
|
>
|
||||||
<ActionMenu id={id} />
|
<ActionMenu id={id} />
|
||||||
<div
|
<div
|
||||||
className="from-muted-foreground/5 absolute inset-0 bg-gradient-to-br to-transparent
|
className="from-muted-foreground/5 absolute inset-0 bg-gradient-to-br to-transparent
|
||||||
opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
<div className="relative flex flex-col items-center text-center">
|
<div className="relative flex flex-col items-center text-center">
|
||||||
<div className="relative mb-6">
|
<div className="relative mb-6">
|
||||||
<Avatar className="size-24 lg:size-28">
|
<Avatar className="size-24 lg:size-28">
|
||||||
<AvatarFallback className="text-2xl">
|
<AvatarFallback className="text-2xl">
|
||||||
{initials(name)}
|
{initials(name)}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-6">
|
|
||||||
<h1 className="mb-2 text-xl font-bold">
|
|
||||||
<Abbr>{name}</Abbr>
|
|
||||||
</h1>
|
|
||||||
<p className="text-muted-foreground bg-muted/50 inline-block rounded-full px-4 py-1.5 text-sm font-medium">
|
|
||||||
<Abbr>{email}</Abbr>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
)
|
<div className="mb-6">
|
||||||
})}
|
<h1 className="mb-2 text-xl font-bold">
|
||||||
</div>
|
<Abbr>{name}</Abbr>
|
||||||
)
|
</h1>
|
||||||
}}
|
<p className="text-muted-foreground bg-muted/50 inline-block rounded-full px-4 py-1.5 text-sm font-medium">
|
||||||
</Await>
|
<Abbr>{email}</Abbr>
|
||||||
</Suspense>
|
</p>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</Await>
|
||||||
|
</Suspense>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export async function loader({ context, request, params }: Route.LoaderArgs) {
|
|||||||
|
|
||||||
export default function Route({ loaderData: { data } }) {
|
export default function Route({ loaderData: { data } }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<Suspense fallback={<Skeleton />}>
|
||||||
<div className="space-y-0.5 mb-8">
|
<div className="space-y-0.5 mb-8">
|
||||||
<h1 className="text-2xl font-bold tracking-tight">
|
<h1 className="text-2xl font-bold tracking-tight">
|
||||||
Importações de colaboradores
|
Importações de colaboradores
|
||||||
@@ -45,31 +45,29 @@ export default function Route({ loaderData: { data } }) {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Suspense fallback={<Skeleton />}>
|
<Await resolve={data}>
|
||||||
<Await resolve={data}>
|
{(resolved) => (
|
||||||
{(resolved) => (
|
<>
|
||||||
<>
|
<Empty className="border border-dasheds">
|
||||||
<Empty className="border border-dasheds">
|
<EmptyHeader>
|
||||||
<EmptyHeader>
|
<EmptyMedia variant="icon">
|
||||||
<EmptyMedia variant="icon">
|
<UploadIcon />
|
||||||
<UploadIcon />
|
</EmptyMedia>
|
||||||
</EmptyMedia>
|
<EmptyTitle>Nenhum importação ainda</EmptyTitle>
|
||||||
<EmptyTitle>Nenhum importação ainda</EmptyTitle>
|
<EmptyDescription>
|
||||||
<EmptyDescription>
|
Importe seus colaboradores para gerenciar, segmentar e
|
||||||
Importe seus colaboradores para gerenciar, segmentar e
|
facilitar sua gestão.
|
||||||
facilitar sua gestão.
|
</EmptyDescription>
|
||||||
</EmptyDescription>
|
</EmptyHeader>
|
||||||
</EmptyHeader>
|
<EmptyContent>
|
||||||
<EmptyContent>
|
<Button>
|
||||||
<Button>
|
<PlusIcon /> Importar
|
||||||
<PlusIcon /> Importar
|
</Button>
|
||||||
</Button>
|
</EmptyContent>
|
||||||
</EmptyContent>
|
</Empty>
|
||||||
</Empty>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
</Await>
|
||||||
</Await>
|
</Suspense>
|
||||||
</Suspense>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,8 @@ export async function loader({ params, request, context }: Route.LoaderArgs) {
|
|||||||
return { data: enrollment }
|
return { data: enrollment }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function UserModal({ loaderData }: Route.ComponentProps) {
|
export default function UserModal({}: Route.ComponentProps) {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { enrollment } = loaderData
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default [
|
|||||||
layout('routes/layout.tsx', [
|
layout('routes/layout.tsx', [
|
||||||
index('routes/index.tsx'),
|
index('routes/index.tsx'),
|
||||||
route('certs', 'routes/certs.tsx'),
|
route('certs', 'routes/certs.tsx'),
|
||||||
route('payments', 'routes/payments.tsx'),
|
route('payments', 'routes/payments/route.tsx'),
|
||||||
route('settings', 'routes/settings.tsx'),
|
route('settings', 'routes/settings.tsx'),
|
||||||
route('konviva', 'routes/konviva.ts'),
|
route('konviva', 'routes/konviva.ts'),
|
||||||
route('player/:id', 'routes/player.tsx'),
|
route('player/:id', 'routes/player.tsx'),
|
||||||
|
|||||||
@@ -1,6 +1,37 @@
|
|||||||
import { redirect } from 'react-router'
|
import { redirect } from 'react-router'
|
||||||
import type { Route } from './+types'
|
import type { Route } from './+types'
|
||||||
|
import { userContext } from '@repo/auth/context'
|
||||||
|
import type { User } from '@repo/auth/auth'
|
||||||
|
|
||||||
export async function loader({ params, context }: Route.LoaderArgs) {
|
const konvivaApi = 'https://lms.saladeaula.digital'
|
||||||
return redirect('https://lms.saladeaula.digital')
|
|
||||||
|
export async function loader({ context }: Route.LoaderArgs) {
|
||||||
|
const user = context.get(userContext) as User
|
||||||
|
const secretKey = context.cloudflare.env.KONVIVA_SECRET_KEY
|
||||||
|
const token = await getToken(user.email, secretKey)
|
||||||
|
|
||||||
|
const url = new URL('/action/acessoExterno', konvivaApi)
|
||||||
|
url.search = new URLSearchParams(token).toString()
|
||||||
|
|
||||||
|
return redirect(url.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getToken(
|
||||||
|
email: string,
|
||||||
|
secretKey: string
|
||||||
|
): Promise<Record<string, string>> {
|
||||||
|
const headers = new Headers({
|
||||||
|
Authorization: `KONVIVA ${secretKey}`,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
})
|
||||||
|
const url = new URL(`/action/api/usuarios/token`, konvivaApi)
|
||||||
|
url.search = new URLSearchParams({ login: email }).toString()
|
||||||
|
|
||||||
|
const r = await fetch(url.toString(), { method: 'GET', headers })
|
||||||
|
|
||||||
|
if (!r.ok) {
|
||||||
|
throw new Error(await r.text())
|
||||||
|
}
|
||||||
|
|
||||||
|
return await r.json()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
import type { Route } from './+types'
|
|
||||||
|
|
||||||
import { MeiliSearchFilterBuilder } from 'meilisearch-helper'
|
|
||||||
import { Await, Link } from 'react-router'
|
|
||||||
|
|
||||||
import { type User } from '@repo/auth/auth'
|
|
||||||
import { userContext } from '@repo/auth/context'
|
|
||||||
import {
|
|
||||||
Breadcrumb,
|
|
||||||
BreadcrumbItem,
|
|
||||||
BreadcrumbLink,
|
|
||||||
BreadcrumbList,
|
|
||||||
BreadcrumbPage,
|
|
||||||
BreadcrumbSeparator
|
|
||||||
} from '@repo/ui/components/ui/breadcrumb'
|
|
||||||
import { createSearch } from '@repo/util/meili'
|
|
||||||
|
|
||||||
import { Container } from '@/components/container'
|
|
||||||
import { Skeleton } from '@repo/ui/components/skeleton'
|
|
||||||
import { Card, CardContent } from '@repo/ui/components/ui/card'
|
|
||||||
import { Suspense } from 'react'
|
|
||||||
|
|
||||||
export function meta({}: Route.MetaArgs) {
|
|
||||||
return [{ title: 'Histórico de compras' }]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const loader = async ({ request, context }: Route.ActionArgs) => {
|
|
||||||
const user = context.get(userContext) as User
|
|
||||||
const { searchParams } = new URL(request.url)
|
|
||||||
const status = searchParams.getAll('status') || []
|
|
||||||
let builder = new MeiliSearchFilterBuilder().where('user_id', '=', user.sub)
|
|
||||||
|
|
||||||
if (status.length) {
|
|
||||||
builder = builder.where('status', 'in', status)
|
|
||||||
}
|
|
||||||
|
|
||||||
const payments = createSearch({
|
|
||||||
index: 'betaeducacao-prod-orders',
|
|
||||||
filter: builder.build(),
|
|
||||||
sort: ['create_date:desc'],
|
|
||||||
env: context.cloudflare.env
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: payments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Component({ loaderData: { data } }) {
|
|
||||||
return (
|
|
||||||
<Container className="space-y-2.5">
|
|
||||||
<Suspense fallback={<Skeleton />}>
|
|
||||||
<Await resolve={data}>
|
|
||||||
{({ hits }) => (
|
|
||||||
<>
|
|
||||||
<Breadcrumb>
|
|
||||||
<BreadcrumbList>
|
|
||||||
<BreadcrumbItem>
|
|
||||||
<BreadcrumbLink asChild>
|
|
||||||
<Link to="..">Meus cursos</Link>
|
|
||||||
</BreadcrumbLink>
|
|
||||||
</BreadcrumbItem>
|
|
||||||
<BreadcrumbSeparator />
|
|
||||||
<BreadcrumbItem>
|
|
||||||
<BreadcrumbPage>Histórico de compras</BreadcrumbPage>
|
|
||||||
</BreadcrumbItem>
|
|
||||||
</BreadcrumbList>
|
|
||||||
</Breadcrumb>
|
|
||||||
|
|
||||||
<div className="space-y-0.5 mb-8">
|
|
||||||
<h1 className="text-2xl font-bold tracking-tight">
|
|
||||||
Histórico de compras
|
|
||||||
</h1>
|
|
||||||
<p className="text-muted-foreground">
|
|
||||||
Acompanhe todos as compras realizadas, visualize pagamentos e
|
|
||||||
mantenha o controle financeiro.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardContent>
|
|
||||||
<table className="table-fixed">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Forma de pag.</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Total</th>
|
|
||||||
<th>Comprador em</th>
|
|
||||||
<th>Vencimento em</th>
|
|
||||||
</tr>
|
|
||||||
{hits.map(({ payment_method, status }) => {
|
|
||||||
return (
|
|
||||||
<tr>
|
|
||||||
<td>{payment_method}</td>
|
|
||||||
<td>{status}</td>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</thead>
|
|
||||||
</table>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Await>
|
|
||||||
</Suspense>
|
|
||||||
</Container>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
63
apps/saladeaula.digital/app/routes/payments/columns.tsx
Normal file
63
apps/saladeaula.digital/app/routes/payments/columns.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import {
|
||||||
|
DataTableColumnDatetime,
|
||||||
|
DataTableColumnCurrency,
|
||||||
|
DataTableColumnHeader
|
||||||
|
} from '@repo/ui/components/data-table'
|
||||||
|
import { type ColumnDef } from '@tanstack/react-table'
|
||||||
|
|
||||||
|
// This type is used to define the shape of our data.
|
||||||
|
// You can use a Zod schema here if you want.
|
||||||
|
export type Order = {
|
||||||
|
id: string
|
||||||
|
total: number
|
||||||
|
status: 'pending' | 'processing' | 'success' | 'failed'
|
||||||
|
payment_method: 'PIX' | 'CREDIT_CARD' | 'MANUAL' | 'failed'
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const columns: ColumnDef<Order>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: 'payment_method',
|
||||||
|
header: 'Forma de pag.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'status',
|
||||||
|
header: 'Status'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'total',
|
||||||
|
header: 'Valor total',
|
||||||
|
cell: ({ row, column }) => (
|
||||||
|
<DataTableColumnCurrency row={row} column={column} />
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'create_date',
|
||||||
|
enableSorting: true,
|
||||||
|
meta: { title: 'Comprado em' },
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} />,
|
||||||
|
cell: ({ row, column }) => (
|
||||||
|
<DataTableColumnDatetime row={row} column={column} />
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'due_date',
|
||||||
|
enableSorting: true,
|
||||||
|
meta: { title: 'Vencimento em' },
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} />,
|
||||||
|
cell: ({ row, column }) => (
|
||||||
|
<DataTableColumnDatetime row={row} column={column} />
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'payment_date',
|
||||||
|
enableSorting: true,
|
||||||
|
meta: { title: 'Pago em' },
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} />,
|
||||||
|
cell: ({ row, column }) => (
|
||||||
|
<DataTableColumnDatetime row={row} column={column} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
101
apps/saladeaula.digital/app/routes/payments/route.tsx
Normal file
101
apps/saladeaula.digital/app/routes/payments/route.tsx
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import type { Route } from '../+types'
|
||||||
|
|
||||||
|
import { MeiliSearchFilterBuilder } from 'meilisearch-helper'
|
||||||
|
import { Await, Link } from 'react-router'
|
||||||
|
import { Suspense } from 'react'
|
||||||
|
|
||||||
|
import { type User } from '@repo/auth/auth'
|
||||||
|
import { userContext } from '@repo/auth/context'
|
||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
BreadcrumbItem,
|
||||||
|
BreadcrumbLink,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbPage,
|
||||||
|
BreadcrumbSeparator
|
||||||
|
} from '@repo/ui/components/ui/breadcrumb'
|
||||||
|
import { createSearch } from '@repo/util/meili'
|
||||||
|
import { Skeleton } from '@repo/ui/components/skeleton'
|
||||||
|
import { DataTable } from '@repo/ui/components/data-table'
|
||||||
|
|
||||||
|
import { Container } from '@/components/container'
|
||||||
|
import { columns, type Order } from './columns'
|
||||||
|
|
||||||
|
export function meta({}: Route.MetaArgs) {
|
||||||
|
return [{ title: 'Histórico de compras' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loader = async ({ request, context }: Route.ActionArgs) => {
|
||||||
|
const user = context.get(userContext) as User
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
const status = searchParams.getAll('status') || []
|
||||||
|
const sort = searchParams.get('sort') || 'create_date:desc'
|
||||||
|
const page = Number(searchParams.get('p')) + 1
|
||||||
|
const hitsPerPage = Number(searchParams.get('perPage')) || 25
|
||||||
|
|
||||||
|
let builder = new MeiliSearchFilterBuilder().where('user_id', '=', user.sub)
|
||||||
|
|
||||||
|
if (status.length) {
|
||||||
|
builder = builder.where('status', 'in', status)
|
||||||
|
}
|
||||||
|
|
||||||
|
const payments = createSearch({
|
||||||
|
index: 'betaeducacao-prod-orders',
|
||||||
|
filter: builder.build(),
|
||||||
|
sort: [sort],
|
||||||
|
page,
|
||||||
|
hitsPerPage,
|
||||||
|
env: context.cloudflare.env
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: payments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Component({ loaderData: { data } }) {
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<Skeleton />}>
|
||||||
|
<Container className="space-y-2.5">
|
||||||
|
<Breadcrumb>
|
||||||
|
<BreadcrumbList>
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<BreadcrumbLink asChild>
|
||||||
|
<Link to="..">Meus cursos</Link>
|
||||||
|
</BreadcrumbLink>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
<BreadcrumbSeparator />
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<BreadcrumbPage>Histórico de compras</BreadcrumbPage>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
</BreadcrumbList>
|
||||||
|
</Breadcrumb>
|
||||||
|
|
||||||
|
<div className="space-y-0.5 mb-8">
|
||||||
|
<h1 className="text-2xl font-bold tracking-tight">
|
||||||
|
Histórico de compras
|
||||||
|
</h1>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Acompanhe todos as compras realizadas, visualize pagamentos e
|
||||||
|
mantenha o controle financeiro.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Await resolve={data}>
|
||||||
|
{({ hits, page, hitsPerPage, totalHits }) => {
|
||||||
|
return (
|
||||||
|
<DataTable
|
||||||
|
sort={[{ id: 'create_date', desc: true }]}
|
||||||
|
columns={columns}
|
||||||
|
data={hits as Order[]}
|
||||||
|
pageIndex={page - 1}
|
||||||
|
pageSize={hitsPerPage}
|
||||||
|
rowCount={totalHits}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</Await>
|
||||||
|
</Container>
|
||||||
|
</Suspense>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
// Generated by Wrangler by running `wrangler types` (hash: a901705264ceb3e725e174d55b20e764)
|
// Generated by Wrangler by running `wrangler types` (hash: 46c0a3878ceeb71c97bee6d456de6815)
|
||||||
// Runtime types generated with workerd@1.20251113.0 2025-04-04 nodejs_compat
|
// Runtime types generated with workerd@1.20251113.0 2025-04-04 nodejs_compat
|
||||||
declare namespace Cloudflare {
|
declare namespace Cloudflare {
|
||||||
interface GlobalProps {
|
interface GlobalProps {
|
||||||
@@ -17,6 +17,7 @@ declare namespace Cloudflare {
|
|||||||
REDIRECT_URI: string;
|
REDIRECT_URI: string;
|
||||||
SESSION_SECRET: string;
|
SESSION_SECRET: string;
|
||||||
MEILI_API_KEY: string;
|
MEILI_API_KEY: string;
|
||||||
|
KONVIVA_SECRET_KEY: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interface Env extends Cloudflare.Env {}
|
interface Env extends Cloudflare.Env {}
|
||||||
@@ -24,7 +25,7 @@ type StringifyValues<EnvType extends Record<string, unknown>> = {
|
|||||||
[Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
|
[Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
|
||||||
};
|
};
|
||||||
declare namespace NodeJS {
|
declare namespace NodeJS {
|
||||||
interface ProcessEnv extends StringifyValues<Pick<Cloudflare.Env, "CLIENT_ID" | "SCOPE" | "API_URL" | "ISSUER_URL" | "BUCKET_NAME" | "BUCKET_ENDPOINT" | "MEILI_HOST" | "CLIENT_SECRET" | "REDIRECT_URI" | "SESSION_SECRET" | "MEILI_API_KEY">> {}
|
interface ProcessEnv extends StringifyValues<Pick<Cloudflare.Env, "CLIENT_ID" | "SCOPE" | "API_URL" | "ISSUER_URL" | "BUCKET_NAME" | "BUCKET_ENDPOINT" | "MEILI_HOST" | "CLIENT_SECRET" | "REDIRECT_URI" | "SESSION_SECRET" | "MEILI_API_KEY" | "KONVIVA_SECRET_KEY">> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin runtime types
|
// Begin runtime types
|
||||||
|
|||||||
Reference in New Issue
Block a user