update cloudflare context
This commit is contained in:
@@ -13,10 +13,10 @@
|
||||
"remix-auth-oauth2": "^3.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-router": "^7.10.1",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"react-router": "^7.10.1",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,16 @@ export type User = {
|
||||
refreshToken: string
|
||||
}
|
||||
|
||||
export function createAuth(env, redirectURI = null) {
|
||||
export function createAuth(
|
||||
env: Record<string, any>,
|
||||
redirectURI: string | null = null
|
||||
) {
|
||||
const authenticator = new Authenticator()
|
||||
const strategy = new OAuth2Strategy(
|
||||
{
|
||||
clientId: env.CLIENT_ID,
|
||||
clientSecret: env.CLIENT_SECRET,
|
||||
redirectURI: redirectURI ?? env.REDIRECT_URI,
|
||||
redirectURI: (env?.REDIRECT_URI ?? redirectURI) || undefined,
|
||||
authorizationEndpoint: `${env.ISSUER_URL}/authorize`,
|
||||
tokenEndpoint: `${env.ISSUER_URL}/token`,
|
||||
tokenRevocationEndpoint: `${env.ISSUER_URL}/revoke`,
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
import type { User } from '@/auth'
|
||||
import { createContext } from 'react-router'
|
||||
|
||||
import type { User } from './auth'
|
||||
|
||||
export const userContext = createContext<User | null>(null)
|
||||
export const requestIdContext = createContext<string | null>(null)
|
||||
|
||||
export interface CloudflareEnv {}
|
||||
export interface CloudflareCtx {}
|
||||
|
||||
export type CloudflareContextType = {
|
||||
env: CloudflareEnv extends Record<string, never>
|
||||
? Record<string, unknown>
|
||||
: CloudflareEnv
|
||||
ctx: CloudflareCtx extends Record<string, never> ? unknown : CloudflareCtx
|
||||
}
|
||||
|
||||
export const cloudflareContext = createContext<CloudflareContextType>()
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { requestIdContext, userContext } from '@/context'
|
||||
import { createSessionStorage } from '@/session'
|
||||
|
||||
import { createAuth, type User } from '@/auth'
|
||||
import { decodeJwt } from 'jose'
|
||||
import { redirect, type LoaderFunctionArgs } from 'react-router'
|
||||
import type { OAuth2Strategy } from 'remix-auth-oauth2'
|
||||
|
||||
import { requestIdContext, userContext, cloudflareContext } from '../context'
|
||||
import { createSessionStorage } from '../session'
|
||||
import { createAuth, type User } from '../auth'
|
||||
|
||||
export const authMiddleware = async (
|
||||
{ request, context }: LoaderFunctionArgs,
|
||||
next: () => Promise<Response>
|
||||
): Promise<Response> => {
|
||||
const sessionStorage = createSessionStorage(context.cloudflare.env)
|
||||
const authenticator = createAuth(context.cloudflare.env)
|
||||
const cloudflare = context.get(cloudflareContext)
|
||||
const sessionStorage = createSessionStorage(cloudflare.env)
|
||||
const authenticator = createAuth(cloudflare.env)
|
||||
const strategy = authenticator.get<OAuth2Strategy<User>>('oidc')
|
||||
const session = await sessionStorage.getSession(request.headers.get('cookie'))
|
||||
const requestId = context.get(requestIdContext)
|
||||
@@ -51,6 +52,7 @@ export const authMiddleware = async (
|
||||
session.set('user', user)
|
||||
}
|
||||
} catch (error) {
|
||||
// @ts-ignore
|
||||
console.error(`[${requestId}]`, error?.stack)
|
||||
|
||||
// If refreshing the token fails, remove the user from the current session
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { requestIdContext } from '@/context'
|
||||
import { type LoaderFunctionArgs } from 'react-router'
|
||||
|
||||
import { requestIdContext } from '../context'
|
||||
|
||||
export const loggingMiddleware = async (
|
||||
{ request, context }: LoaderFunctionArgs,
|
||||
next
|
||||
) => {
|
||||
next: () => Promise<Response>
|
||||
): Promise<Response> => {
|
||||
const requestId = crypto.randomUUID()
|
||||
context.set(requestIdContext, requestId)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createCookieSessionStorage } from 'react-router'
|
||||
|
||||
import { type User } from './auth'
|
||||
|
||||
type SessionData = {
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2022"],
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
|
||||
27
packages/ui/src/components/currency.tsx
Normal file
27
packages/ui/src/components/currency.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
type CurrencyProps = {
|
||||
children: number
|
||||
options?: Intl.NumberFormatOptions
|
||||
locale?: string
|
||||
currency?: string
|
||||
}
|
||||
|
||||
export function Currency({
|
||||
children,
|
||||
options,
|
||||
locale = 'pt-BR',
|
||||
currency = 'BRL'
|
||||
}: CurrencyProps): ReactNode {
|
||||
const optionsInit: Intl.NumberFormatOptions = {
|
||||
style: 'currency',
|
||||
currency
|
||||
}
|
||||
|
||||
const formatter = new Intl.NumberFormat(locale, {
|
||||
...optionsInit,
|
||||
...options
|
||||
})
|
||||
|
||||
return formatter.format(children)
|
||||
}
|
||||
33
packages/ui/src/components/datetime.tsx
Normal file
33
packages/ui/src/components/datetime.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { ComponentPropsWithoutRef } from 'react'
|
||||
|
||||
type DateTimeProps = {
|
||||
children: string
|
||||
options?: Intl.DateTimeFormatOptions
|
||||
locale?: string
|
||||
} & ComponentPropsWithoutRef<'time'>
|
||||
|
||||
export function DateTime({
|
||||
children,
|
||||
options,
|
||||
locale = 'pt-BR',
|
||||
...props
|
||||
}: DateTimeProps) {
|
||||
const optionsInit: Intl.DateTimeFormatOptions = {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}
|
||||
|
||||
const datetime = new Intl.DateTimeFormat(locale, {
|
||||
...optionsInit,
|
||||
...options
|
||||
})
|
||||
|
||||
return (
|
||||
<time dateTime={children} {...props}>
|
||||
{datetime.format(new Date(children))}
|
||||
</time>
|
||||
)
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react-router": "^5.1.20",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { User } from '@repo/auth/auth'
|
||||
import { requestIdContext, userContext } from '@repo/auth/context'
|
||||
import {
|
||||
cloudflareContext,
|
||||
requestIdContext,
|
||||
userContext
|
||||
} from '@repo/auth/context'
|
||||
|
||||
import type { LoaderFunctionArgs } from 'react-router'
|
||||
|
||||
@@ -28,9 +31,10 @@ export function request({
|
||||
request: { signal },
|
||||
context
|
||||
}: RequestArgs): Promise<Response> {
|
||||
const requestId = context.get(requestIdContext) as string
|
||||
const user = context.get(userContext) as User
|
||||
const url_ = new URL(url, context.cloudflare.env.API_URL)
|
||||
const requestId = context.get(requestIdContext)
|
||||
const user = context.get(userContext)
|
||||
const cloudflare = context.get(cloudflareContext)
|
||||
const url_ = new URL(url, cloudflare.env.API_URL)
|
||||
const headers = new Headers({
|
||||
Authorization: `Bearer ${user.accessToken}`
|
||||
})
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2022", "DOM"],
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
|
||||
Reference in New Issue
Block a user