blacksmith-cli 0.1.4 → 0.1.6
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 +276 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/backend/utils/__init__.py.hbs +0 -0
- package/src/templates/backend/utils/models.py.hbs +11 -0
- package/src/templates/frontend/package.json.hbs +9 -1
- package/src/templates/frontend/src/__tests__/setup.ts.hbs +21 -0
- package/src/templates/frontend/src/__tests__/test-utils.tsx.hbs +80 -0
- package/src/templates/frontend/src/pages/home/home.tsx.hbs +93 -11
- package/src/templates/frontend/tsconfig.app.json.hbs +1 -0
- package/src/templates/frontend/vite.config.ts.hbs +8 -0
- package/src/templates/resource/api-hooks/index.ts.hbs +2 -0
- package/src/templates/resource/{frontend/hooks → api-hooks}/use-{{kebabs}}-query.ts.hbs +10 -2
- package/src/templates/resource/{frontend/hooks → api-hooks}/use-{{kebab}}-mutations.ts.hbs +1 -1
- package/src/templates/resource/backend/models.py.hbs +2 -3
- package/src/templates/resource/frontend/components/{{kebab}}-card.tsx.hbs +1 -1
- package/src/templates/resource/frontend/components/{{kebab}}-list.tsx.hbs +1 -1
- package/src/templates/resource/frontend/index.ts.hbs +1 -2
- package/src/templates/resource/frontend/pages/{{kebabs}}-page.tsx.hbs +1 -1
- package/src/templates/resource/frontend/pages/{{kebab}}-detail-page.tsx.hbs +3 -11
- package/src/templates/resource/pages/components/{{kebab}}-card.tsx.hbs +1 -1
- package/src/templates/resource/pages/components/{{kebab}}-list.tsx.hbs +1 -1
- package/src/templates/resource/pages/hooks/index.ts.hbs +9 -0
- package/src/templates/resource/pages/index.ts.hbs +1 -2
- package/src/templates/resource/pages/{{kebabs}}-page.tsx.hbs +1 -1
- package/src/templates/resource/pages/{{kebab}}-detail-page.tsx.hbs +3 -11
- package/src/templates/frontend/src/pages/home/components/features-grid.tsx.hbs +0 -88
- package/src/templates/frontend/src/pages/home/components/getting-started.tsx.hbs +0 -88
- package/src/templates/frontend/src/pages/home/components/hero-section.tsx.hbs +0 -47
- package/src/templates/frontend/src/pages/home/components/resources-section.tsx.hbs +0 -34
- package/src/templates/resource/pages/hooks/use-{{kebabs}}-query.ts.hbs +0 -35
- package/src/templates/resource/pages/hooks/use-{{kebab}}-mutations.ts.hbs +0 -39
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Card,
|
|
3
|
-
CardHeader,
|
|
4
|
-
CardTitle,
|
|
5
|
-
CardDescription,
|
|
6
|
-
CardContent,
|
|
7
|
-
Button,
|
|
8
|
-
Tooltip,
|
|
9
|
-
Stack,
|
|
10
|
-
Flex,
|
|
11
|
-
Grid,
|
|
12
|
-
Typography,
|
|
13
|
-
Text,
|
|
14
|
-
} from '@blacksmith-ui/react'
|
|
15
|
-
import { Terminal, Copy, Check } from 'lucide-react'
|
|
16
|
-
import { useCopyToClipboard } from '@blacksmith-ui/hooks'
|
|
17
|
-
|
|
18
|
-
const steps = [
|
|
19
|
-
{
|
|
20
|
-
command: 'blacksmith dev',
|
|
21
|
-
title: 'Start the dev server',
|
|
22
|
-
description: 'Runs Django, Vite, and OpenAPI watcher concurrently.',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
command: 'blacksmith make:resource Post',
|
|
26
|
-
title: 'Scaffold a resource',
|
|
27
|
-
description: 'Generates model, serializer, viewset, hooks, and pages.',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
command: 'blacksmith sync',
|
|
31
|
-
title: 'Sync API types',
|
|
32
|
-
description: 'Regenerates the TypeScript client from your Django schema.',
|
|
33
|
-
},
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
function CommandBlock({ command }: { command: string }) {
|
|
37
|
-
const { status, copy } = useCopyToClipboard(2000)
|
|
38
|
-
const copied = status === 'copied'
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<Flex align="center" gap={2} className="rounded-lg bg-muted px-3 py-2">
|
|
42
|
-
<Terminal className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
|
|
43
|
-
<Text as="code" size="sm" className="flex-1 font-mono">{command}</Text>
|
|
44
|
-
<Tooltip content={copied ? 'Copied!' : 'Copy command'}>
|
|
45
|
-
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={() => copy(command)}>
|
|
46
|
-
{copied ? (
|
|
47
|
-
<Check className="h-3.5 w-3.5 text-green-500" />
|
|
48
|
-
) : (
|
|
49
|
-
<Copy className="h-3.5 w-3.5" />
|
|
50
|
-
)}
|
|
51
|
-
</Button>
|
|
52
|
-
</Tooltip>
|
|
53
|
-
</Flex>
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function GettingStarted() {
|
|
58
|
-
return (
|
|
59
|
-
<Stack as="section" gap={6}>
|
|
60
|
-
<Stack gap={2} align="center">
|
|
61
|
-
<Typography variant="h2">Get Started in 3 Steps</Typography>
|
|
62
|
-
<Text color="muted">
|
|
63
|
-
Everything you need to go from scaffold to production.
|
|
64
|
-
</Text>
|
|
65
|
-
</Stack>
|
|
66
|
-
<Grid columns=\{{ base: 1, md: 3 }} gap={4}>
|
|
67
|
-
{steps.map((step, index) => (
|
|
68
|
-
<Card key={step.command}>
|
|
69
|
-
<CardHeader className="pb-3">
|
|
70
|
-
<Flex align="center" gap={3}>
|
|
71
|
-
<Flex align="center" justify="center" className="h-8 w-8 shrink-0 rounded-full bg-primary text-primary-foreground">
|
|
72
|
-
<Text size="sm" weight="semibold">{index + 1}</Text>
|
|
73
|
-
</Flex>
|
|
74
|
-
<CardTitle className="text-base">{step.title}</CardTitle>
|
|
75
|
-
</Flex>
|
|
76
|
-
</CardHeader>
|
|
77
|
-
<CardContent>
|
|
78
|
-
<Stack gap={3}>
|
|
79
|
-
<CardDescription>{step.description}</CardDescription>
|
|
80
|
-
<CommandBlock command={step.command} />
|
|
81
|
-
</Stack>
|
|
82
|
-
</CardContent>
|
|
83
|
-
</Card>
|
|
84
|
-
))}
|
|
85
|
-
</Grid>
|
|
86
|
-
</Stack>
|
|
87
|
-
)
|
|
88
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { Stack, Flex, Typography, Text, Button } from '@blacksmith-ui/react'
|
|
2
|
-
import { Rocket, BookOpen } from 'lucide-react'
|
|
3
|
-
import { Link } from 'react-router-dom'
|
|
4
|
-
import { Path } from '@/router/paths'
|
|
5
|
-
|
|
6
|
-
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
|
|
7
|
-
|
|
8
|
-
interface HeroSectionProps {
|
|
9
|
-
isAuthenticated: boolean
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function HeroSection({ isAuthenticated }: HeroSectionProps) {
|
|
13
|
-
return (
|
|
14
|
-
<Stack as="section" gap={6} align="center" className="pt-10 pb-2">
|
|
15
|
-
<Typography variant="h1" className="sm:text-5xl">
|
|
16
|
-
Welcome to{' '}
|
|
17
|
-
<Text as="span" color="primary">{{projectName}}</Text>
|
|
18
|
-
</Typography>
|
|
19
|
-
<Text size="lg" color="muted" align="center" className="max-w-2xl">
|
|
20
|
-
Your fullstack Django + React application is ready to go.
|
|
21
|
-
</Text>
|
|
22
|
-
<Flex justify="center" gap={3} className="pt-2">
|
|
23
|
-
{isAuthenticated ? (
|
|
24
|
-
<Button size="lg" asChild>
|
|
25
|
-
<Link to={Path.Dashboard}>
|
|
26
|
-
<Rocket className="mr-2 h-4 w-4" />
|
|
27
|
-
Dashboard
|
|
28
|
-
</Link>
|
|
29
|
-
</Button>
|
|
30
|
-
) : (
|
|
31
|
-
<Button size="lg" asChild>
|
|
32
|
-
<Link to={Path.Login}>
|
|
33
|
-
<Rocket className="mr-2 h-4 w-4" />
|
|
34
|
-
Sign In
|
|
35
|
-
</Link>
|
|
36
|
-
</Button>
|
|
37
|
-
)}
|
|
38
|
-
<Button variant="outline" size="lg" asChild>
|
|
39
|
-
<a href={`${API_URL}/api/docs/`} target="_blank" rel="noopener noreferrer">
|
|
40
|
-
<BookOpen className="mr-2 h-4 w-4" />
|
|
41
|
-
API Docs
|
|
42
|
-
</a>
|
|
43
|
-
</Button>
|
|
44
|
-
</Flex>
|
|
45
|
-
</Stack>
|
|
46
|
-
)
|
|
47
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Stack, Flex, Typography, Text, Button } from '@blacksmith-ui/react'
|
|
2
|
-
import { ExternalLink } from 'lucide-react'
|
|
3
|
-
|
|
4
|
-
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
|
|
5
|
-
|
|
6
|
-
const links = [
|
|
7
|
-
{ label: 'Swagger UI', href: `${API_URL}/api/docs/` },
|
|
8
|
-
{ label: 'ReDoc', href: `${API_URL}/api/redoc/` },
|
|
9
|
-
{ label: 'OpenAPI Schema', href: `${API_URL}/api/schema/` },
|
|
10
|
-
{ label: 'Django Admin', href: `${API_URL}/admin/` },
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
export function ResourcesSection() {
|
|
14
|
-
return (
|
|
15
|
-
<Stack as="section" gap={4}>
|
|
16
|
-
<Stack gap={2} align="center">
|
|
17
|
-
<Typography variant="h2">Resources</Typography>
|
|
18
|
-
<Text color="muted">
|
|
19
|
-
Documentation and tools to help you build.
|
|
20
|
-
</Text>
|
|
21
|
-
</Stack>
|
|
22
|
-
<Flex justify="center" wrap="wrap" gap={3}>
|
|
23
|
-
{links.map((link) => (
|
|
24
|
-
<Button key={link.label} variant="outline" size="sm" asChild>
|
|
25
|
-
<a href={link.href} target="_blank" rel="noopener noreferrer">
|
|
26
|
-
<ExternalLink className="mr-2 h-3.5 w-3.5" />
|
|
27
|
-
{link.label}
|
|
28
|
-
</a>
|
|
29
|
-
</Button>
|
|
30
|
-
))}
|
|
31
|
-
</Flex>
|
|
32
|
-
</Stack>
|
|
33
|
-
)
|
|
34
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* use{{Names}} Hook
|
|
3
|
-
*
|
|
4
|
-
* Wraps the generated list query with smart retry and error parsing.
|
|
5
|
-
* Generated by Blacksmith. You own this file — customize as needed.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useApiQuery } from '@/shared/hooks/use-api-query'
|
|
9
|
-
import {
|
|
10
|
-
{{snakes}}ListOptions,
|
|
11
|
-
} from '@/api/generated/@tanstack/react-query.gen'
|
|
12
|
-
|
|
13
|
-
interface Use{{Names}}Params {
|
|
14
|
-
page?: number
|
|
15
|
-
search?: string
|
|
16
|
-
ordering?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function use{{Names}}(params: Use{{Names}}Params = {}) {
|
|
20
|
-
return useApiQuery({
|
|
21
|
-
...{{snakes}}ListOptions({
|
|
22
|
-
query: {
|
|
23
|
-
page: params.page ?? 1,
|
|
24
|
-
search: params.search,
|
|
25
|
-
ordering: params.ordering ?? '-created_at',
|
|
26
|
-
},
|
|
27
|
-
}),
|
|
28
|
-
select: (data: any) => ({
|
|
29
|
-
{{names}}: data.results ?? [],
|
|
30
|
-
total: data.count ?? 0,
|
|
31
|
-
hasNext: !!data.next,
|
|
32
|
-
hasPrev: !!data.previous,
|
|
33
|
-
}),
|
|
34
|
-
})
|
|
35
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* {{Name}} Mutation Hooks
|
|
3
|
-
*
|
|
4
|
-
* Create, update, and delete with cache invalidation and error parsing.
|
|
5
|
-
* Generated by Blacksmith. You own this file — customize as needed.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useApiMutation } from '@/shared/hooks/use-api-mutation'
|
|
9
|
-
import {
|
|
10
|
-
{{snakes}}CreateMutation,
|
|
11
|
-
{{snakes}}UpdateMutation,
|
|
12
|
-
{{snakes}}DestroyMutation,
|
|
13
|
-
{{snakes}}ListQueryKey,
|
|
14
|
-
{{snakes}}RetrieveQueryKey,
|
|
15
|
-
} from '@/api/generated/@tanstack/react-query.gen'
|
|
16
|
-
|
|
17
|
-
export function useCreate{{Name}}() {
|
|
18
|
-
return useApiMutation({
|
|
19
|
-
...{{snakes}}CreateMutation(),
|
|
20
|
-
invalidateKeys: [{{snakes}}ListQueryKey()],
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function useUpdate{{Name}}(id: number) {
|
|
25
|
-
return useApiMutation({
|
|
26
|
-
...{{snakes}}UpdateMutation(),
|
|
27
|
-
invalidateKeys: [
|
|
28
|
-
{{snakes}}ListQueryKey(),
|
|
29
|
-
{{snakes}}RetrieveQueryKey({ path: { id } }),
|
|
30
|
-
],
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function useDelete{{Name}}() {
|
|
35
|
-
return useApiMutation({
|
|
36
|
-
...{{snakes}}DestroyMutation(),
|
|
37
|
-
invalidateKeys: [{{snakes}}ListQueryKey()],
|
|
38
|
-
})
|
|
39
|
-
}
|