create-restack-pattern 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/package.json +1 -1
- package/template/{AGENTS.md → DEVELOPMENT.md} +2 -2
- package/template/backend/src/domains/auth/auth.repo.ts +1 -1
- package/template/backend/src/domains/auth/auth.routes.ts +1 -1
- package/template/backend/src/domains/user/user.repo.ts +1 -1
- package/template/backend/src/domains/user/user.routes.test.ts +1 -1
- package/template/backend/src/domains/user/user.routes.ts +2 -2
- package/template/backend/src/hono-app.ts +1 -1
- package/template/backend/src/index.ts +1 -1
- package/template/backend/src/{shared → infra}/middlewares/require-auth.ts +1 -1
- package/template/backend/src/{shared/logger → utils}/logger.ts +2 -2
- package/template/frontend/app/dashboard/page.tsx +1 -1
- package/template/frontend/{shared/components → components}/require-auth.tsx +1 -1
- package/template/frontend/components.json +1 -1
- package/template/frontend/domains/auth/hooks/use-login.ts +1 -1
- package/template/frontend/domains/auth/hooks/use-register.ts +1 -1
- package/template/frontend/domains/auth/services/auth.api.ts +1 -1
- package/template/frontend/domains/user/services/user.api.ts +1 -1
- package/template/frontend/{shared/lib → lib}/api-client.ts +1 -1
- package/template/gitignore +1 -2
- package/template/CLAUDE.md +0 -62
- package/template/frontend/shared/components/ui/.gitkeep +0 -0
- package/template/frontend/shared/hooks/.gitkeep +0 -0
- package/template/frontend/shared/lib/.gitkeep +0 -0
- /package/template/backend/src/{shared → infra}/db/.gitkeep +0 -0
- /package/template/backend/src/{shared → infra}/db/index.ts +0 -0
- /package/template/backend/src/{shared → infra}/middlewares/.gitkeep +0 -0
- /package/template/backend/src/{shared → infra}/middlewares/require-auth.test.ts +0 -0
- /package/template/frontend/{shared/hooks → hooks}/use-auth-mutation.ts +0 -0
package/README.md
CHANGED
|
@@ -15,11 +15,13 @@ npx create-restack-pattern my-app
|
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Or run it without arguments to be prompted for a project name:
|
|
18
|
+
|
|
18
19
|
```bash
|
|
19
20
|
npx create-restack-pattern
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
### Prerequisites
|
|
24
|
+
|
|
23
25
|
- **Node.js**: version 20 or higher
|
|
24
26
|
- **pnpm**: package manager installed (run `npm install -g pnpm` if needed)
|
|
25
27
|
- **PostgreSQL**: a running database (either a local instance or a free hosted instance on [Neon](https://neon.tech))
|
|
@@ -31,26 +33,32 @@ npx create-restack-pattern
|
|
|
31
33
|
Once the CLI finishes scaffolding your project, follow these three simple steps to get started:
|
|
32
34
|
|
|
33
35
|
### 1. Configure Environment Variables
|
|
36
|
+
|
|
34
37
|
```bash
|
|
35
38
|
cd my-app
|
|
36
39
|
cp backend/.env.example backend/.env
|
|
37
40
|
cp frontend/.env.example frontend/.env
|
|
38
41
|
```
|
|
42
|
+
|
|
39
43
|
- Open `backend/.env` and set:
|
|
40
44
|
- `DATABASE_URL` (format: `postgresql://user:password@localhost:5432/dbname`; you can use a local Postgres database or a free hosted instance on [Neon](https://neon.tech))
|
|
41
45
|
- `JWT_SECRET` (generate a secure 32-character key by running: `openssl rand -base64 32`)
|
|
42
|
-
-
|
|
46
|
+
- _(Optional)_ Open `frontend/.env` to override `NEXT_PUBLIC_API_URL` (defaults to `http://localhost:3001` for local Hono API).
|
|
43
47
|
|
|
44
48
|
### 2. Push Database Tables
|
|
49
|
+
|
|
45
50
|
This creates the required `users` and `auth_sessions` tables in your database:
|
|
51
|
+
|
|
46
52
|
```bash
|
|
47
53
|
pnpm --filter backend db:push
|
|
48
54
|
```
|
|
49
55
|
|
|
50
56
|
### 3. Start Development Servers
|
|
57
|
+
|
|
51
58
|
```bash
|
|
52
59
|
pnpm dev
|
|
53
60
|
```
|
|
61
|
+
|
|
54
62
|
- **Backend API**: runs at [http://localhost:3001](http://localhost:3001)
|
|
55
63
|
- **Frontend App**: runs at [http://localhost:3000](http://localhost:3000)
|
|
56
64
|
|
|
@@ -95,5 +103,5 @@ Before testing your CLI changes locally or publishing, follow the standard workf
|
|
|
95
103
|
```
|
|
96
104
|
|
|
97
105
|
For detailed guides, workflow explanations, and lessons learned:
|
|
106
|
+
|
|
98
107
|
- Check out the [Development Guide](../../docs/en/development-guide.md) (Indonesian: [Panduan Kontribusi](../../docs/id/development-guide.md))
|
|
99
|
-
- Check out the [Building a Scaffolding CLI Tutorial](../../docs/tutorial.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DEVELOPMENT.md
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This document outlines the architecture, build guidelines, and code conventions for the Restack Pattern monorepo. All developers and automated tools contributing to this project must follow these rules.
|
|
4
4
|
|
|
5
5
|
## Project Stack
|
|
6
6
|
- **Frontend**: Next.js 16 (App Router)
|
|
@@ -5,7 +5,7 @@ import { zValidator } from "@hono/zod-validator"
|
|
|
5
5
|
import { LoginSchema, RegisterSchema } from "@restack/shared"
|
|
6
6
|
import { authService, ACCESS_TOKEN_TTL_SECONDS, REFRESH_TOKEN_TTL_SECONDS } from "./auth.service.js"
|
|
7
7
|
import { env } from "../../config/env.js"
|
|
8
|
-
import { logger, type AppVariables } from "../../
|
|
8
|
+
import { logger, type AppVariables } from "../../utils/logger.js"
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Routing layer for the Auth domain.
|
|
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeAll, afterAll } from "vitest"
|
|
|
2
2
|
import { eq } from "drizzle-orm"
|
|
3
3
|
import { userRoutes } from "./user.routes.js"
|
|
4
4
|
import { authService } from "../auth/auth.service.js"
|
|
5
|
-
import { db } from "../../
|
|
5
|
+
import { db } from "../../infra/db/index.js"
|
|
6
6
|
import { usersTable } from "./user.model.js"
|
|
7
7
|
|
|
8
8
|
const TEST_EMAIL = `user-routes-test-${Date.now()}@example.com`
|
|
@@ -2,9 +2,9 @@ import { Hono } from "hono"
|
|
|
2
2
|
import type { Context } from "hono"
|
|
3
3
|
import { zValidator } from "@hono/zod-validator"
|
|
4
4
|
import { UpdateProfileSchema } from "@restack/shared"
|
|
5
|
-
import { requireAuth } from "../../
|
|
5
|
+
import { requireAuth } from "../../infra/middlewares/require-auth.js"
|
|
6
6
|
import { userService, UserNotFoundError } from "./user.service.js"
|
|
7
|
-
import { logger, type AppVariables } from "../../
|
|
7
|
+
import { logger, type AppVariables } from "../../utils/logger.js"
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Routing layer for the User domain.
|
|
@@ -4,7 +4,7 @@ import { csrf } from "hono/csrf"
|
|
|
4
4
|
import { logger as honoLogger } from "hono/logger"
|
|
5
5
|
import { requestId } from "hono/request-id"
|
|
6
6
|
import { env } from "./config/env.js"
|
|
7
|
-
import { logger, type AppVariables } from "./
|
|
7
|
+
import { logger, type AppVariables } from "./utils/logger.js"
|
|
8
8
|
import { authRoutes } from "./domains/auth/auth.routes.js"
|
|
9
9
|
import { userRoutes } from "./domains/user/user.routes.js"
|
|
10
10
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MiddlewareHandler } from "hono"
|
|
2
2
|
import { getCookie } from "hono/cookie"
|
|
3
3
|
import { authService } from "../../domains/auth/auth.service.js"
|
|
4
|
-
import type { AppVariables } from "
|
|
4
|
+
import type { AppVariables } from "../../utils/logger.js"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Authentication guard middleware.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pino from "pino"
|
|
2
|
-
import { env } from "
|
|
2
|
+
import { env } from "../config/env.js"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Global logger client.
|
|
@@ -32,7 +32,7 @@ export const logger = loggerInstance
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
import type { Logger } from "pino"
|
|
35
|
-
import type { AuthTokenPayload } from "
|
|
35
|
+
import type { AuthTokenPayload } from "../domains/auth/auth.types.js"
|
|
36
36
|
|
|
37
37
|
export type AppVariables = {
|
|
38
38
|
requestId: string
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Link from "next/link"
|
|
2
2
|
import { LogoutButton } from "@/domains/auth/components/logout-button"
|
|
3
3
|
import { Button } from "@/components/ui/button"
|
|
4
|
-
import { RequireAuth } from "@/
|
|
4
|
+
import { RequireAuth } from "@/components/require-auth"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Next.js Router Page: Dashboard
|
|
@@ -8,7 +8,7 @@ import { client, unwrap } from "../lib/api-client"
|
|
|
8
8
|
* Client-side auth gate for pages with no data fetch of their own to piggyback
|
|
9
9
|
* a redirect on (see use-profile.ts for pages that need both). Necessary
|
|
10
10
|
* because there is no server-side proxy.ts guard anymore — see the Next.js 16
|
|
11
|
-
* caveat in
|
|
11
|
+
* caveat in DEVELOPMENT.md for why.
|
|
12
12
|
*/
|
|
13
13
|
export function RequireAuth({ children }: { children: React.ReactNode }) {
|
|
14
14
|
const router = useRouter()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import { LoginSchema, type LoginInput } from "@restack/shared"
|
|
4
|
-
import { useAuthMutation } from "@/
|
|
4
|
+
import { useAuthMutation } from "@/hooks/use-auth-mutation"
|
|
5
5
|
import { authApi } from "../services/auth.api"
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import { RegisterSchema, type RegisterInput } from "@restack/shared"
|
|
4
|
-
import { useAuthMutation } from "@/
|
|
4
|
+
import { useAuthMutation } from "@/hooks/use-auth-mutation"
|
|
5
5
|
import { authApi } from "../services/auth.api"
|
|
6
6
|
|
|
7
7
|
/**
|
package/template/gitignore
CHANGED
package/template/CLAUDE.md
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides architecture, build, and styling guidance to Claude Code (claude.ai/code) and other AI assistants working in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Stack
|
|
6
|
-
- **Frontend**: Next.js 16 (App Router)
|
|
7
|
-
- **Backend**: Hono
|
|
8
|
-
- **ORM**: Drizzle ORM
|
|
9
|
-
- **Database**: PostgreSQL (Postgres-js driver)
|
|
10
|
-
- **Validation**: Zod (shared schemas)
|
|
11
|
-
- **Package Manager**: pnpm workspaces
|
|
12
|
-
|
|
13
|
-
## Monorepo Layout
|
|
14
|
-
- `frontend/` — Next.js 16 App Router
|
|
15
|
-
- `backend/` — Hono API
|
|
16
|
-
- `packages/shared/` — Shared Zod schemas (the single source of truth)
|
|
17
|
-
|
|
18
|
-
## Build and Dev Commands
|
|
19
|
-
All commands should be run from the repository root:
|
|
20
|
-
- `pnpm install` — Install all dependencies
|
|
21
|
-
- `pnpm --filter @restack/shared build` — Build shared Zod schemas (run first!)
|
|
22
|
-
- `pnpm --filter backend dev` — Start Hono dev server on port 3001
|
|
23
|
-
- `pnpm --filter frontend dev` — Start Next.js dev server on port 3000
|
|
24
|
-
- `pnpm --filter backend db:push` — Push Drizzle schema to PostgreSQL database
|
|
25
|
-
- `pnpm --filter backend db:studio` — Open Drizzle Studio database viewer
|
|
26
|
-
- `pnpm --filter backend test` — Run Vitest tests
|
|
27
|
-
|
|
28
|
-
## Architecture Rules: Semi-DDD (Feature-Driven)
|
|
29
|
-
Code is organized by business domain/feature, not by file type.
|
|
30
|
-
|
|
31
|
-
### Backend Layout (`backend/src/domains/[feature]/`)
|
|
32
|
-
Each domain has 4 primary files:
|
|
33
|
-
- `[feature].routes.ts` — HTTP endpoints & input validation (imports Zod schema from `@restack/shared`)
|
|
34
|
-
- `[feature].service.ts` — Pure business logic only (no direct DB access)
|
|
35
|
-
- `[feature].repo.ts` — Drizzle queries only (no business logic)
|
|
36
|
-
- `[feature].model.ts` — Drizzle table definitions
|
|
37
|
-
|
|
38
|
-
**Cross-Domain Dependency Rule**: The `auth` domain may import from `user` (e.g. `usersTable` from `user.model.ts`). The reverse (user importing from auth) is STRICTLY FORBIDDEN.
|
|
39
|
-
|
|
40
|
-
### Frontend Layout (`frontend/domains/[feature]/`)
|
|
41
|
-
- `components/` — UI components (no direct data fetching)
|
|
42
|
-
- `hooks/` — Reactive state & data fetching logic
|
|
43
|
-
- `services/` — Thin HTTP wrappers around `apiClient`
|
|
44
|
-
- `types.ts` — Local TS type declarations
|
|
45
|
-
- `frontend/app/` is strictly for layout, routing config, metadata, or entry gates. Do not implement custom JSX layouts, forms, state, or complex components here. Always delegate rendering to domain feature components.
|
|
46
|
-
|
|
47
|
-
## Critical Gotcha: Shared Package Build Requirement
|
|
48
|
-
`@restack/shared`'s `package.json` resolves to `dist/`, which is gitignored. When editing Zod schemas in `packages/shared/src/schemas/`, you MUST compile them by running:
|
|
49
|
-
`pnpm --filter @restack/shared build`
|
|
50
|
-
(or keep `pnpm --filter @restack/shared dev` watch mode running in a terminal) or the frontend and backend will fail to resolve the updated types or throw compilation errors.
|
|
51
|
-
|
|
52
|
-
## Auth & Cookie Strategy
|
|
53
|
-
- Short-lived JWT `access_token` (15m) and opaque `refresh_token` (30d) are both set as `httpOnly` cookies at `Path=/`.
|
|
54
|
-
- Access tokens are automatically refreshed by the client-side `apiClient` on a 401 response.
|
|
55
|
-
- Cookie configuration: `SameSite=None` in production (requires `Secure=true`), and `SameSite=Lax` in development (`Secure=false` since local dev runs on HTTP).
|
|
56
|
-
- There is no server-side auth gate (`middleware.ts`/`proxy.ts`) because cookies cannot be read server-side when frontend and backend deploy to unrelated domains (Topology B). Authenticated routes are protected via backend `requireAuth` middleware, and frontend pages are protected via `<RequireAuth>` or client-side checks in hooks.
|
|
57
|
-
|
|
58
|
-
## Structured & Correlation Logging
|
|
59
|
-
- Every incoming HTTP request is tagged with a unique `requestId` via Hono's `requestId` middleware.
|
|
60
|
-
- A request-scoped child logger (`logger.child({ requestId })`) is bound to Hono's context.
|
|
61
|
-
- In route handlers, always extract the request-specific child logger from Hono's context (`c.get("logger") || logger`) to log events. This ensures all logs generated during a request carry the correct `requestId` and `userId` context (which is automatically enriched by the `requireAuth` middleware).
|
|
62
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|