Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit"
"source.fixAll.biome": "explicit"
},
"tailwindCSS.experimental.classRegex": [
"twc|x\\.[^`]+`([^`]*)`",
Expand Down
4 changes: 4 additions & 0 deletions app/middlewares/auth-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createContext } from 'react-router'
import type { AppUser } from '~/services/auth'

export const authContext = createContext<AppUser | null>()
10 changes: 3 additions & 7 deletions app/middlewares/on-boarding-auth-middleware.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import {
href,
redirect,
type unstable_MiddlewareFunction as MiddlewareFunction,
} from 'react-router'
import { href, type MiddlewareFunction, redirect } from 'react-router'
import { requireAuth } from '~/services/auth'
import { userContext } from './user-context'
import { authContext } from './auth-context'

export const onBoardingAuthMiddleware: MiddlewareFunction = async ({
request,
context,
}) => {
// オンボーディング手続きはログインしていないとアクセスできない
const user = await requireAuth(request, { failureRedirect: href('/') })
context.set(userContext, user)
context.set(authContext, user)

// すでにオンボーディング済みの場合はプロフィールページにリダイレクト
if (user.handle) {
Expand Down
6 changes: 3 additions & 3 deletions app/middlewares/optional-auth-middleware.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { unstable_MiddlewareFunction as MiddlewareFunction } from 'react-router'
import type { MiddlewareFunction } from 'react-router'
import { isAuthenticated } from '~/services/auth'
import { userContext } from './user-context'
import { authContext } from './auth-context'

export const optionalAuthMiddleware: MiddlewareFunction = async ({
request,
context,
}) => {
// ログインしている場合はユーザー情報をセット
const user = await isAuthenticated(request)
context.set(userContext, user)
context.set(authContext, user)
}
4 changes: 0 additions & 4 deletions app/middlewares/user-context.ts

This file was deleted.

6 changes: 3 additions & 3 deletions app/routes/$handle+/_index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
DropdownMenuTrigger,
} from '~/components/ui'
import { dayjs } from '~/libs/dayjs'
import { userContext } from '~/middlewares/user-context'
import { authContext } from '~/middlewares/auth-context'
import { isAccountExistsByHandle } from '~/models/account'
import { addUserPost, listUserPosts, type Post } from '~/models/posts'
import { DeleteAlertDialog } from '~/routes/$handle+/posts.$id.delete/route'
Expand All @@ -26,7 +26,7 @@ export const clientLoader = async ({
const isExist = await isAccountExistsByHandle(handle)
if (!isExist) throw data(null, { status: 404 })

const user = context.get(userContext)
const user = context.get(authContext)
const posts = await listUserPosts(handle)

return { handle, user, posts, isAuthor: handle === user?.handle }
Expand All @@ -36,7 +36,7 @@ export const clientAction = async ({
params: { handle },
context,
}: Route.ClientActionArgs) => {
const user = context.get(userContext)
const user = context.get(authContext)
if (user?.handle !== handle) {
throw new Error('Unauthorized')
}
Expand Down
2 changes: 1 addition & 1 deletion app/routes/$handle+/_layout/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Outlet } from 'react-router'
import { AppFooter } from '~/components/AppFooter'
import { optionalAuthMiddleware } from '~/middlewares/optional-auth-middleware'

export const unstable_clientMiddleware = [optionalAuthMiddleware]
export const clientMiddleware = [optionalAuthMiddleware]

export default function UserPageLayout() {
return (
Expand Down
4 changes: 2 additions & 2 deletions app/routes/$handle+/posts.$id._index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { data, href, Link } from 'react-router'
import { AppHeadingSection } from '~/components/AppHeadingSection'
import { Button } from '~/components/ui'
import { dayjs } from '~/libs/dayjs'
import { userContext } from '~/middlewares/user-context'
import { authContext } from '~/middlewares/auth-context'
import { getUserPostById } from '~/models/posts'
import type { Route } from './+types/route'

Expand All @@ -16,7 +16,7 @@ export const clientLoader = async ({
if (!post) throw data(null, { status: 404 })

// ミドルウェアからセットされたオプショナルのユーザ情報を取得
const user = context.get(userContext)
const user = context.get(authContext)

return { handle, id, post, user }
}
Expand Down
4 changes: 2 additions & 2 deletions app/routes/$handle+/posts.$id.delete/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Button,
DropdownMenuItem,
} from '~/components/ui'
import { userContext } from '~/middlewares/user-context'
import { authContext } from '~/middlewares/auth-context'
import { deleteUserPost, type Post } from '~/models/posts'
import type { Route } from './+types/route'

Expand All @@ -22,7 +22,7 @@ export const clientAction = async ({
const { handle, id } = params

// ミドルウェアからセットされたオプショナルのユーザ情報を取得
const user = context.get(userContext)
const user = context.get(authContext)
if (user?.handle !== handle) {
// 本人でなければ削除できない
throw data(null, { status: 401 })
Expand Down
6 changes: 3 additions & 3 deletions app/routes/$handle+/posts.$id.edit/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { data, Form, href, Link, redirect, useNavigation } from 'react-router'
import { z } from 'zod'
import { AppHeadingSection } from '~/components/AppHeadingSection'
import { Button, Input, Label, Textarea } from '~/components/ui'
import { userContext } from '~/middlewares/user-context'
import { authContext } from '~/middlewares/auth-context'
import { deleteUserPost, getUserPostById, updateUserPost } from '~/models/posts'
import type { Route } from './+types/route'

Expand All @@ -32,7 +32,7 @@ export const clientLoader = async ({
context,
}: Route.ClientLoaderArgs) => {
// ミドルウェアからセットされたオプショナルのユーザ情報を取得
const user = context.get(userContext)
const user = context.get(authContext)
// 本人の投稿以外は編集できない / 存在確認
if (user?.handle !== handle) throw data(null, { status: 403 })

Expand All @@ -48,7 +48,7 @@ export const clientAction = async ({
context,
}: Route.ClientActionArgs) => {
// ミドルウェアからセットされたオプショナルのユーザ情報を取得
const user = context.get(userContext)
const user = context.get(authContext)
// 本人の投稿以外は編集できない / 存在確認
if (user?.handle !== handle) {
throw data(null, { status: 403 })
Expand Down
2 changes: 1 addition & 1 deletion app/routes/welcome+/_layout/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { onBoardingAuthMiddleware } from '~/middlewares/on-boarding-auth-middleware'

// Middleware を設定
export const unstable_clientMiddleware = [onBoardingAuthMiddleware]
export const clientMiddleware = [onBoardingAuthMiddleware]
4 changes: 2 additions & 2 deletions app/routes/welcome+/create_account/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Form, redirect } from 'react-router'
import { z } from 'zod'
import { AppHeadingSection } from '~/components/AppHeadingSection'
import { Alert, AlertDescription, Button, Input, toast } from '~/components/ui'
import { userContext } from '~/middlewares/user-context'
import { authContext } from '~/middlewares/auth-context'
import { createAccount } from '~/models/account'
import { useSignOut } from '~/routes/auth+/sign_out/route'
import type { Route } from './+types/route'
Expand All @@ -26,7 +26,7 @@ export const clientAction = async ({
context,
}: Route.ClientActionArgs) => {
// Middleware でセットされたユーザ情報を取得
const user = context.get(userContext)
const user = context.get(authContext)
if (!user) {
throw new Error('システムエラー: ユーザ情報がありません')
}
Expand Down
5 changes: 4 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"$schema": "https://biomejs.dev/schemas/2.1.3/schema.json",
"$schema": "https://biomejs.dev/schemas/2.2.4/schema.json",
"files": {
"includes": ["**", "!app/styles/globals.css"]
},
"assist": { "actions": { "source": { "organizeImports": "on" } } },
"vcs": {
"enabled": true,
Expand Down
44 changes: 22 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,58 +8,58 @@
"dev": "react-router dev",
"preview": "vite preview",
"lint": "biome lint .",
"format": "prettier --cache -c .",
"format:fix": "prettier --cache -w .",
"format": "prettier --cache -c --experimental-cli .",
"format:fix": "prettier --cache -w --experimental-cli .",
"typecheck": "react-router typegen && tsc",
"validate": "pnpm run lint && pnpm run format && pnpm run typecheck",
"start": "npx sirv-cli build/client/ --single"
},
"dependencies": {
"@conform-to/react": "^1.9.1",
"@conform-to/zod": "^1.9.1",
"@react-router/node": "7.7.1",
"@tailwindcss/vite": "^4.1.11",
"@react-router/node": "7.9.1",
"@tailwindcss/vite": "^4.1.13",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"firebase": "^12.0.0",
"isbot": "^5.1.29",
"lucide-react": "^0.534.0",
"marked": "^16.1.1",
"dayjs": "^1.11.18",
"firebase": "^12.2.1",
"isbot": "^5.1.30",
"lucide-react": "^0.544.0",
"marked": "^16.2.1",
"next-themes": "^0.4.6",
"pure-uuid": "^1.8.1",
"radix-ui": "latest",
"react": "19.1.1",
"react-dom": "19.1.1",
"react-markdown": "^10.1.0",
"react-router": "7.7.1",
"react-router-dom": "7.7.1",
"react-router": "7.9.1",
"react-router-dom": "7.9.1",
"react-twc": "^1.5.1",
"remix-flat-routes": "^0.8.5",
"sonner": "^2.0.6",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tailwindcss-animate": "^1.0.7",
"zod": "^4.1.8"
},
"devDependencies": {
"@biomejs/biome": "^2.1.3",
"@mdx-js/rollup": "^3.1.0",
"@react-router/dev": "7.7.1",
"@react-router/remix-routes-option-adapter": "^7.7.1",
"@biomejs/biome": "^2.2.4",
"@mdx-js/rollup": "^3.1.1",
"@react-router/dev": "7.9.1",
"@react-router/remix-routes-option-adapter": "^7.9.1",
"@tailwindcss/typography": "^0.5.16",
"@types/react": "^19.1.9",
"@types/react-dom": "^19.1.7",
"firebase-tools": "^14.11.1",
"@types/react": "^19.1.13",
"@types/react-dom": "^19.1.9",
"firebase-tools": "^14.16.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.6.2",
"prettier-plugin-organize-imports": "^4.2.0",
"prettier-plugin-tailwindcss": "^0.6.14",
"remark-frontmatter": "^5.0.0",
"remark-mdx-frontmatter": "^5.2.0",
"rollup-plugin-visualizer": "^6.0.3",
"tailwindcss": "^4.1.11",
"typescript": "^5.8.3",
"vite": "^7.0.6",
"tailwindcss": "^4.1.13",
"typescript": "^5.9.2",
"vite": "^7.1.5",
"vite-tsconfig-paths": "^5.1.4"
},
"engines": {
Expand Down
Loading