@kood/claude-code 0.3.7 → 0.3.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/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/.claude/agents/code-reviewer.md +124 -124
- package/templates/.claude/agents/dependency-manager.md +85 -85
- package/templates/.claude/agents/deployment-validator.md +56 -56
- package/templates/.claude/agents/git-operator.md +64 -64
- package/templates/.claude/agents/implementation-executor.md +95 -95
- package/templates/.claude/agents/ko-to-en-translator.md +74 -0
- package/templates/.claude/agents/lint-fixer.md +78 -78
- package/templates/.claude/agents/refactor-advisor.md +122 -122
- package/templates/.claude/commands/agent-creator.md +185 -185
- package/templates/.claude/commands/bug-fix.md +193 -193
- package/templates/.claude/commands/command-creator.md +54 -54
- package/templates/.claude/commands/docs-creator.md +57 -57
- package/templates/.claude/commands/docs-refactor.md +26 -26
- package/templates/.claude/commands/execute.md +12 -12
- package/templates/.claude/commands/git-all.md +32 -32
- package/templates/.claude/commands/git-session.md +42 -42
- package/templates/.claude/commands/git.md +34 -34
- package/templates/.claude/commands/lint-fix.md +138 -138
- package/templates/.claude/commands/lint-init.md +61 -61
- package/templates/.claude/commands/plan.md +260 -260
- package/templates/.claude/commands/prd.md +24 -24
- package/templates/.claude/commands/pre-deploy.md +109 -109
- package/templates/.claude/commands/refactor.md +147 -147
- package/templates/.claude/commands/version-update.md +17 -17
- package/templates/hono/CLAUDE.md +27 -27
- package/templates/hono/docs/architecture.md +24 -24
- package/templates/hono/docs/deployment/cloudflare.md +18 -18
- package/templates/hono/docs/deployment/docker.md +13 -13
- package/templates/hono/docs/deployment/index.md +19 -19
- package/templates/hono/docs/deployment/railway.md +32 -32
- package/templates/hono/docs/deployment/vercel.md +29 -29
- package/templates/hono/docs/guides/conventions.md +57 -57
- package/templates/hono/docs/guides/env-setup.md +47 -47
- package/templates/hono/docs/guides/getting-started.md +27 -27
- package/templates/hono/docs/library/hono/error-handling.md +11 -11
- package/templates/hono/docs/library/hono/index.md +4 -4
- package/templates/hono/docs/library/hono/middleware.md +18 -18
- package/templates/hono/docs/library/hono/rpc.md +7 -7
- package/templates/hono/docs/library/hono/validation.md +6 -6
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +29 -29
- package/templates/hono/docs/library/prisma/config.md +16 -16
- package/templates/hono/docs/library/prisma/index.md +32 -32
- package/templates/hono/docs/library/t3-env/index.md +22 -22
- package/templates/hono/docs/library/zod/index.md +31 -31
- package/templates/nextjs/CLAUDE.md +51 -51
- package/templates/nextjs/docs/design.md +183 -183
- package/templates/nextjs/docs/guides/conventions.md +86 -86
- package/templates/nextjs/docs/guides/getting-started.md +28 -28
- package/templates/nextjs/docs/guides/routes.md +32 -32
- package/templates/nextjs/docs/library/better-auth/index.md +70 -70
- package/templates/nextjs/docs/library/nextjs/app-router.md +43 -43
- package/templates/nextjs/docs/library/nextjs/caching.md +73 -73
- package/templates/nextjs/docs/library/nextjs/index.md +51 -51
- package/templates/nextjs/docs/library/nextjs/middleware.md +41 -41
- package/templates/nextjs/docs/library/nextjs/route-handlers.md +31 -31
- package/templates/nextjs/docs/library/nextjs/server-actions.md +34 -34
- package/templates/nextjs/docs/library/prisma/cloudflare-d1.md +20 -20
- package/templates/nextjs/docs/library/prisma/config.md +18 -18
- package/templates/nextjs/docs/library/prisma/crud.md +17 -17
- package/templates/nextjs/docs/library/prisma/index.md +18 -18
- package/templates/nextjs/docs/library/prisma/relations.md +16 -16
- package/templates/nextjs/docs/library/prisma/schema.md +23 -23
- package/templates/nextjs/docs/library/prisma/setup.md +6 -6
- package/templates/nextjs/docs/library/prisma/transactions.md +10 -10
- package/templates/nextjs/docs/library/tanstack-query/index.md +6 -6
- package/templates/nextjs/docs/library/tanstack-query/invalidation.md +20 -20
- package/templates/nextjs/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/nextjs/docs/library/tanstack-query/use-mutation.md +15 -15
- package/templates/nextjs/docs/library/tanstack-query/use-query.md +22 -22
- package/templates/nextjs/docs/library/zod/complex-types.md +11 -11
- package/templates/nextjs/docs/library/zod/index.md +8 -8
- package/templates/nextjs/docs/library/zod/transforms.md +11 -11
- package/templates/nextjs/docs/library/zod/validation.md +9 -9
- package/templates/npx/CLAUDE.md +37 -37
- package/templates/npx/docs/library/commander/index.md +12 -12
- package/templates/npx/docs/library/fs-extra/index.md +9 -9
- package/templates/npx/docs/library/prompts/index.md +3 -3
- package/templates/npx/docs/references/patterns.md +12 -12
- package/templates/tanstack-start/CLAUDE.md +53 -53
- package/templates/tanstack-start/docs/architecture.md +128 -128
- package/templates/tanstack-start/docs/design.md +169 -169
- package/templates/tanstack-start/docs/guides/conventions.md +43 -43
- package/templates/tanstack-start/docs/guides/env-setup.md +35 -35
- package/templates/tanstack-start/docs/guides/getting-started.md +19 -19
- package/templates/tanstack-start/docs/guides/hooks.md +45 -45
- package/templates/tanstack-start/docs/guides/routes.md +54 -54
- package/templates/tanstack-start/docs/guides/services.md +45 -45
- package/templates/tanstack-start/docs/library/better-auth/index.md +68 -68
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +19 -19
- package/templates/tanstack-start/docs/library/prisma/config.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/crud.md +17 -17
- package/templates/tanstack-start/docs/library/prisma/index.md +17 -17
- package/templates/tanstack-start/docs/library/prisma/relations.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/schema.md +23 -23
- package/templates/tanstack-start/docs/library/prisma/setup.md +6 -6
- package/templates/tanstack-start/docs/library/prisma/transactions.md +10 -10
- package/templates/tanstack-start/docs/library/t3-env/index.md +21 -160
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +6 -6
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +19 -19
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +14 -14
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +21 -21
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +11 -11
- package/templates/tanstack-start/docs/library/tanstack-router/index.md +18 -18
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +17 -17
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +5 -5
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +10 -10
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +8 -8
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +15 -15
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +6 -6
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +18 -18
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +4 -4
- package/templates/tanstack-start/docs/library/zod/complex-types.md +11 -11
- package/templates/tanstack-start/docs/library/zod/index.md +8 -8
- package/templates/tanstack-start/docs/library/zod/transforms.md +11 -11
- package/templates/tanstack-start/docs/library/zod/validation.md +9 -9
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<patterns>
|
|
4
4
|
|
|
5
5
|
```tsx
|
|
6
|
-
//
|
|
6
|
+
// Basic
|
|
7
7
|
export const Route = createFileRoute('/about')({ component: AboutPage })
|
|
8
8
|
|
|
9
9
|
// Loader
|
|
@@ -16,7 +16,7 @@ const Page = () => {
|
|
|
16
16
|
return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
//
|
|
19
|
+
// Dynamic routes
|
|
20
20
|
export const Route = createFileRoute('/users/$id')({
|
|
21
21
|
loader: async ({ params }) => ({ user: await getUserById(params.id) }),
|
|
22
22
|
component: () => {
|
|
@@ -25,10 +25,10 @@ export const Route = createFileRoute('/users/$id')({
|
|
|
25
25
|
},
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
// SSR
|
|
29
|
-
ssr: true //
|
|
30
|
-
ssr: false //
|
|
31
|
-
ssr: 'data-only' //
|
|
28
|
+
// SSR options
|
|
29
|
+
ssr: true // Full SSR (default)
|
|
30
|
+
ssr: false // Client-only
|
|
31
|
+
ssr: 'data-only' // Data only on server
|
|
32
32
|
|
|
33
33
|
// Server Routes (API)
|
|
34
34
|
export const Route = createFileRoute('/api/hello')({
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# TanStack Start - Server Functions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Type-safe functions that run only on the server.
|
|
4
4
|
|
|
5
|
-
## ⚠️
|
|
5
|
+
## ⚠️ Required: Use TanStack Query
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
-
|
|
7
|
+
Always use useQuery/useMutation when calling from client.
|
|
8
|
+
- Auto caching, deduplication, loading/error states, invalidateQueries sync
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Basic Patterns
|
|
11
11
|
|
|
12
12
|
```typescript
|
|
13
13
|
// GET
|
|
@@ -25,31 +25,31 @@ export const createUser = createServerFn({ method: 'POST' })
|
|
|
25
25
|
.handler(async ({ data }) => prisma.user.create({ data }))
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## Calling from Components
|
|
29
29
|
|
|
30
30
|
```tsx
|
|
31
|
-
// ✅ useQuery (
|
|
31
|
+
// ✅ useQuery (read)
|
|
32
32
|
const { data, isLoading } = useQuery({
|
|
33
33
|
queryKey: ['posts'],
|
|
34
34
|
queryFn: () => getServerPosts(),
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
// ✅ useMutation (
|
|
37
|
+
// ✅ useMutation (write)
|
|
38
38
|
const mutation = useMutation({
|
|
39
39
|
mutationFn: createPost,
|
|
40
40
|
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['posts'] }),
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
// ❌
|
|
43
|
+
// ❌ Direct calls forbidden (no caching, no sync)
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
##
|
|
46
|
+
## Function Separation Rules
|
|
47
47
|
|
|
48
48
|
```typescript
|
|
49
|
-
//
|
|
49
|
+
// Internal helper (don't export!)
|
|
50
50
|
const validateUserData = async (email: string) => { ... }
|
|
51
51
|
|
|
52
|
-
// Server Function (
|
|
52
|
+
// Server Function (exportable)
|
|
53
53
|
export const createUser = createServerFn({ method: 'POST' })
|
|
54
54
|
.inputValidator(createUserSchema)
|
|
55
55
|
.handler(async ({ data }) => {
|
|
@@ -57,19 +57,19 @@ export const createUser = createServerFn({ method: 'POST' })
|
|
|
57
57
|
return prisma.user.create({ data })
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
// index.ts: Server
|
|
60
|
+
// index.ts: Export only Server Functions
|
|
61
61
|
export { createUser } from './mutations'
|
|
62
|
-
// ❌ export { validateUserData }
|
|
62
|
+
// ❌ export { validateUserData } forbidden
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
##
|
|
65
|
+
## Security
|
|
66
66
|
|
|
67
67
|
```tsx
|
|
68
|
-
// ❌
|
|
68
|
+
// ❌ Environment variables in loader (exposed)
|
|
69
69
|
loader: () => { const secret = process.env.SECRET }
|
|
70
70
|
|
|
71
|
-
// ✅ Server
|
|
71
|
+
// ✅ Use Server Functions
|
|
72
72
|
const fn = createServerFn().handler(() => {
|
|
73
|
-
const secret = process.env.SECRET //
|
|
73
|
+
const secret = process.env.SECRET // server-only
|
|
74
74
|
})
|
|
75
75
|
```
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# TanStack Start -
|
|
1
|
+
# TanStack Start - Installation and Setup
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Installation
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
yarn add @tanstack/react-start @tanstack/react-router vinxi
|
|
7
7
|
yarn add -D vite @vitejs/plugin-react vite-tsconfig-paths
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Configuration
|
|
11
11
|
|
|
12
12
|
```typescript
|
|
13
13
|
// vite.config.ts
|
|
@@ -36,7 +36,7 @@ export default defineConfig({
|
|
|
36
36
|
}
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
##
|
|
39
|
+
## Environment Variable Validation
|
|
40
40
|
|
|
41
41
|
```typescript
|
|
42
42
|
// lib/env.ts
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# Zod -
|
|
1
|
+
# Zod - Complex Types
|
|
2
2
|
|
|
3
3
|
<patterns>
|
|
4
4
|
|
|
5
5
|
```typescript
|
|
6
|
-
//
|
|
6
|
+
// Object
|
|
7
7
|
const UserSchema = z.object({
|
|
8
8
|
name: z.string(),
|
|
9
9
|
email: z.email(),
|
|
10
10
|
age: z.number().optional(),
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
-
UserSchema.partial() //
|
|
14
|
-
UserSchema.required() //
|
|
15
|
-
UserSchema.pick({ name: true }) //
|
|
16
|
-
UserSchema.omit({ email: true }) //
|
|
13
|
+
UserSchema.partial() // All fields optional
|
|
14
|
+
UserSchema.required() // All fields required
|
|
15
|
+
UserSchema.pick({ name: true }) // Only specific fields
|
|
16
|
+
UserSchema.omit({ email: true }) // Exclude specific fields
|
|
17
17
|
UserSchema.extend({ role: z.enum(['admin', 'user']) })
|
|
18
18
|
UserSchema.merge(AnotherSchema)
|
|
19
19
|
|
|
20
|
-
z.strictObject({ name: z.string() }) // v4:
|
|
21
|
-
z.looseObject({ name: z.string() }) // v4:
|
|
20
|
+
z.strictObject({ name: z.string() }) // v4: error on extra keys
|
|
21
|
+
z.looseObject({ name: z.string() }) // v4: allow extra keys
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// Array/Tuple
|
|
24
24
|
z.array(z.string())
|
|
25
25
|
z.array(z.number()).min(1).max(10).length(5).nonempty()
|
|
26
26
|
z.tuple([z.string(), z.number()]) // [string, number]
|
|
27
27
|
|
|
28
|
-
//
|
|
28
|
+
// Union
|
|
29
29
|
z.union([z.string(), z.number()])
|
|
30
30
|
z.string().or(z.number())
|
|
31
31
|
|
|
@@ -46,7 +46,7 @@ z.record(z.string(), z.object({ name: z.string() })) // { [key: string]: { name
|
|
|
46
46
|
z.map(z.string(), z.number()) // Map<string, number>
|
|
47
47
|
z.set(z.number()) // Set<number>
|
|
48
48
|
|
|
49
|
-
//
|
|
49
|
+
// Recursive
|
|
50
50
|
type Json = string | number | boolean | null | { [key: string]: Json } | Json[]
|
|
51
51
|
|
|
52
52
|
const jsonSchema: z.ZodType<Json> = z.lazy(() =>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<quick_reference>
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
//
|
|
14
|
+
// Basic
|
|
15
15
|
const schema = z.object({
|
|
16
16
|
email: z.email(), // v4!
|
|
17
17
|
name: z.string().min(1).trim(),
|
|
@@ -20,7 +20,7 @@ const schema = z.object({
|
|
|
20
20
|
})
|
|
21
21
|
type Input = z.infer<typeof schema>
|
|
22
22
|
|
|
23
|
-
schema.parse(data) //
|
|
23
|
+
schema.parse(data) // Throw on failure
|
|
24
24
|
schema.safeParse(data) // { success, data/error }
|
|
25
25
|
|
|
26
26
|
// TanStack Start
|
|
@@ -34,7 +34,7 @@ export const createUser = createServerFn({ method: 'POST' })
|
|
|
34
34
|
<v4_changes>
|
|
35
35
|
|
|
36
36
|
```typescript
|
|
37
|
-
// ✅ v4
|
|
37
|
+
// ✅ v4 new API
|
|
38
38
|
z.email() z.url() z.uuid()
|
|
39
39
|
z.iso.date() z.iso.datetime() z.iso.duration()
|
|
40
40
|
z.stringbool() // "true"/"yes"/"1" → true
|
|
@@ -42,13 +42,13 @@ z.stringbool() // "true"/"yes"/"1" → true
|
|
|
42
42
|
// ❌ v3 deprecated
|
|
43
43
|
z.string().email() z.string().url()
|
|
44
44
|
|
|
45
|
-
//
|
|
45
|
+
// Changes
|
|
46
46
|
z.string().min(5, { error: "Too short." }) // message → error
|
|
47
|
-
z.strictObject({ name: z.string() }) //
|
|
48
|
-
z.looseObject({ name: z.string() }) //
|
|
49
|
-
z.string().refine(val => val.includes("@")).min(5) //
|
|
47
|
+
z.strictObject({ name: z.string() }) // Error on extra keys
|
|
48
|
+
z.looseObject({ name: z.string() }) // Allow extra keys
|
|
49
|
+
z.string().refine(val => val.includes("@")).min(5) // Refinement chaining
|
|
50
50
|
|
|
51
|
-
//
|
|
51
|
+
// Template literals
|
|
52
52
|
const css = z.templateLiteral([z.number(), z.enum(["px", "em", "rem"])])
|
|
53
53
|
// `${number}px` | `${number}em` | `${number}rem`
|
|
54
54
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Zod -
|
|
1
|
+
# Zod - Transforms
|
|
2
2
|
|
|
3
3
|
<patterns>
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ stringToLength.parse('hello') // => 5
|
|
|
10
10
|
type In = z.input<typeof stringToLength> // string
|
|
11
11
|
type Out = z.output<typeof stringToLength> // number
|
|
12
12
|
|
|
13
|
-
// Pipe (
|
|
13
|
+
// Pipe (validate then transform)
|
|
14
14
|
const stringToNumber = z.string()
|
|
15
15
|
.transform((val) => parseInt(val, 10))
|
|
16
16
|
.pipe(z.number().min(0).max(100))
|
|
@@ -18,20 +18,20 @@ const stringToNumber = z.string()
|
|
|
18
18
|
stringToNumber.parse('50') // => 50
|
|
19
19
|
stringToNumber.parse('150') // throws
|
|
20
20
|
|
|
21
|
-
// Coerce (
|
|
22
|
-
z.coerce.string() //
|
|
23
|
-
z.coerce.number() //
|
|
24
|
-
z.coerce.boolean() //
|
|
25
|
-
z.coerce.date() //
|
|
26
|
-
z.coerce.bigint() //
|
|
21
|
+
// Coerce (force conversion)
|
|
22
|
+
z.coerce.string() // any → string
|
|
23
|
+
z.coerce.number() // any → number
|
|
24
|
+
z.coerce.boolean() // any → boolean
|
|
25
|
+
z.coerce.date() // any → Date
|
|
26
|
+
z.coerce.bigint() // any → BigInt
|
|
27
27
|
|
|
28
28
|
z.coerce.number().parse("42") // => 42
|
|
29
29
|
z.coerce.date().parse("2021-01-01") // => Date
|
|
30
30
|
|
|
31
|
-
// v4:
|
|
31
|
+
// v4: input type changed to unknown
|
|
32
32
|
type In = z.input<typeof z.coerce.string()> // unknown
|
|
33
33
|
|
|
34
|
-
// v4
|
|
34
|
+
// v4 environment boolean
|
|
35
35
|
z.stringbool() // "true"/"yes"/"1" → true, "false"/"no"/"0" → false
|
|
36
36
|
|
|
37
37
|
// Preprocess
|
|
@@ -40,7 +40,7 @@ const trimmed = z.preprocess(
|
|
|
40
40
|
z.string()
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
-
//
|
|
43
|
+
// Separate input/output types
|
|
44
44
|
const Schema = z.object({
|
|
45
45
|
createdAt: z.string().transform((str) => new Date(str)),
|
|
46
46
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Zod -
|
|
1
|
+
# Zod - Validation
|
|
2
2
|
|
|
3
3
|
<patterns>
|
|
4
4
|
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
// Refinement (v4: message → error)
|
|
7
7
|
const PasswordSchema = z.string()
|
|
8
8
|
.min(8)
|
|
9
|
-
.refine((val) => /[A-Z]/.test(val), { error: '
|
|
10
|
-
.refine((val) => /[0-9]/.test(val), { error: '
|
|
9
|
+
.refine((val) => /[A-Z]/.test(val), { error: 'Uppercase required' })
|
|
10
|
+
.refine((val) => /[0-9]/.test(val), { error: 'Number required' })
|
|
11
11
|
|
|
12
|
-
z.string().refine(val => val.includes("@")).min(5) // v4:
|
|
12
|
+
z.string().refine(val => val.includes("@")).min(5) // v4: chaining after refinement
|
|
13
13
|
|
|
14
14
|
// Async
|
|
15
15
|
const schema = z.string().refine(async (val) => val.length <= 8)
|
|
@@ -23,20 +23,20 @@ z.object({
|
|
|
23
23
|
if (data.password !== data.confirmPassword) {
|
|
24
24
|
ctx.addIssue({
|
|
25
25
|
code: z.ZodIssueCode.custom,
|
|
26
|
-
message: '
|
|
26
|
+
message: 'Passwords do not match',
|
|
27
27
|
path: ['confirmPassword'],
|
|
28
28
|
})
|
|
29
29
|
}
|
|
30
|
-
}) // v4: ctx.path
|
|
30
|
+
}) // v4: ctx.path cannot be used
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// Custom
|
|
33
33
|
const px = z.custom<`${number}px`>((val) =>
|
|
34
34
|
typeof val === 'string' && /^\d+px$/.test(val)
|
|
35
35
|
)
|
|
36
36
|
px.parse('42px') // ✅
|
|
37
37
|
px.parse('42vw') // throws
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// Error handling
|
|
40
40
|
const result = schema.safeParse(data)
|
|
41
41
|
if (!result.success) {
|
|
42
42
|
result.error.errors.forEach((err) => {
|
|
@@ -50,7 +50,7 @@ export const createUser = createServerFn({ method: 'POST' })
|
|
|
50
50
|
.inputValidator(zodValidator(createUserSchema))
|
|
51
51
|
.handler(async ({ data }) => prisma.user.create({ data }))
|
|
52
52
|
|
|
53
|
-
//
|
|
53
|
+
// Environment variables
|
|
54
54
|
const env = z.object({
|
|
55
55
|
NODE_ENV: z.enum(['development', 'production', 'test']),
|
|
56
56
|
DATABASE_URL: z.string().url(),
|