@shivasankaran18/stackd 1.8.0 → 2.0.1

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.
Files changed (73) hide show
  1. package/apps/cli/src/cli.ts +28 -2
  2. package/apps/cli/src/commands/create.ts +30 -0
  3. package/apps/cli/src/scripts/ui/shadcn.ts +4 -10
  4. package/apps/cli/src/scripts/ui/tailwind.ts +39 -0
  5. package/apps/web/app/scaffold/page.tsx +1 -1
  6. package/apps/web/package.json +1 -1
  7. package/apps/web/tsconfig.json +108 -20
  8. package/package.json +18 -20
  9. package/dist/apps/cli/src/cli.js +0 -217
  10. package/dist/apps/cli/src/commands/create.js +0 -148
  11. package/dist/apps/cli/src/scripts/Auth/jwt.js +0 -78
  12. package/dist/apps/cli/src/scripts/Auth/nextAuth.js +0 -131
  13. package/dist/apps/cli/src/scripts/Auth/passport.js +0 -218
  14. package/dist/apps/cli/src/scripts/backend/django.js +0 -20
  15. package/dist/apps/cli/src/scripts/backend/expressjs.js +0 -58
  16. package/dist/apps/cli/src/scripts/backend/expressts.js +0 -83
  17. package/dist/apps/cli/src/scripts/frontend/angularjs.js +0 -1
  18. package/dist/apps/cli/src/scripts/frontend/angularts.js +0 -22
  19. package/dist/apps/cli/src/scripts/frontend/nextjs.js +0 -62
  20. package/dist/apps/cli/src/scripts/frontend/reactjs.js +0 -31
  21. package/dist/apps/cli/src/scripts/frontend/reactts.js +0 -30
  22. package/dist/apps/cli/src/scripts/frontend/vuejs.js +0 -37
  23. package/dist/apps/cli/src/scripts/frontend/vuets.js +0 -43
  24. package/dist/apps/cli/src/scripts/orms/drizzleSetup.js +0 -85
  25. package/dist/apps/cli/src/scripts/orms/mongoSetup.js +0 -53
  26. package/dist/apps/cli/src/scripts/orms/prismaSetup.js +0 -12
  27. package/dist/apps/cli/src/scripts/ui/shadcn.js +0 -207
  28. package/dist/apps/cli/src/scripts/ui/tailwindcss.js +0 -102
  29. package/dist/apps/web/app/api/auth/[...nextauth]/route.js +0 -5
  30. package/dist/apps/web/app/api/scaffold/route.js +0 -251
  31. package/dist/apps/web/app/home/page.js +0 -19
  32. package/dist/apps/web/app/layout.js +0 -19
  33. package/dist/apps/web/app/page.js +0 -1
  34. package/dist/apps/web/app/providers.js +0 -7
  35. package/dist/apps/web/app/scaffold/page.js +0 -326
  36. package/dist/apps/web/components/Sidebar.js +0 -54
  37. package/dist/apps/web/components/theme-provider.js +0 -6
  38. package/dist/apps/web/components/ui/button.js +0 -32
  39. package/dist/apps/web/components/ui/card.js +0 -15
  40. package/dist/apps/web/components/ui/dropdown-menu.js +0 -54
  41. package/dist/apps/web/components/ui/input.js +0 -7
  42. package/dist/apps/web/components/ui/label.js +0 -9
  43. package/dist/apps/web/components/ui/scroll-area.js +0 -19
  44. package/dist/apps/web/components/ui/sonner.js +0 -15
  45. package/dist/apps/web/components/ui/steps.js +0 -14
  46. package/dist/apps/web/components/ui/switch.js +0 -9
  47. package/dist/apps/web/lib/auth.js +0 -32
  48. package/dist/apps/web/lib/redis.js +0 -9
  49. package/dist/apps/web/lib/utils.js +0 -5
  50. package/dist/packages/scripts/Auth/jwt.js +0 -78
  51. package/dist/packages/scripts/Auth/nextAuth.js +0 -131
  52. package/dist/packages/scripts/Auth/passport.js +0 -218
  53. package/dist/packages/scripts/backend/django.js +0 -20
  54. package/dist/packages/scripts/backend/expressjs.js +0 -58
  55. package/dist/packages/scripts/backend/expressts.js +0 -83
  56. package/dist/packages/scripts/frontend/angularjs.js +0 -1
  57. package/dist/packages/scripts/frontend/angularts.js +0 -22
  58. package/dist/packages/scripts/frontend/nextjs.js +0 -62
  59. package/dist/packages/scripts/frontend/reactjs.js +0 -31
  60. package/dist/packages/scripts/frontend/reactts.js +0 -30
  61. package/dist/packages/scripts/frontend/vuejs.js +0 -37
  62. package/dist/packages/scripts/frontend/vuets.js +0 -43
  63. package/dist/packages/scripts/orms/drizzleSetup.js +0 -85
  64. package/dist/packages/scripts/orms/mongoSetup.js +0 -53
  65. package/dist/packages/scripts/orms/prismaSetup.js +0 -12
  66. package/dist/packages/scripts/ui/shadcn.js +0 -207
  67. package/dist/packages/scripts/ui/tailwindcss.js +0 -102
  68. package/dist/stackd.js +0 -114
  69. package/dist/tsconfig.tsbuildinfo +0 -1
  70. package/packages/typescript-config/base.json +0 -19
  71. package/packages/typescript-config/nextjs.json +0 -12
  72. package/packages/typescript-config/package.json +0 -9
  73. package/packages/typescript-config/react-library.json +0 -7
@@ -1,326 +0,0 @@
1
- 'use client';
2
- import React, { useState, useEffect } from 'react';
3
- import { Button } from '@/components/ui/button';
4
- import { Input } from '@/components/ui/input';
5
- import { Card } from '@/components/ui/card';
6
- import { Layout, Server, Database, FolderOpen } from 'lucide-react';
7
- import { Steps } from '@/components/ui/steps';
8
- import { toast } from 'sonner';
9
- import { Label } from '@/components/ui/label';
10
- import { motion } from 'framer-motion';
11
- const SkipButton = ({ onSkip }) => (<Button variant="outline" onClick={onSkip} className="text-orange-500 hover:text-orange-600 hover:bg-orange-50 dark:hover:bg-orange-950/10 border-orange-200 hover:border-orange-300 dark:border-orange-800">
12
- Skip
13
- </Button>);
14
- const Navbar = () => (<nav className="navbar backdrop-blur-sm">
15
- <div className="max-w-6xl mx-auto px-8 py-3 flex justify-center">
16
- <div className="flex flex-col items-center">
17
- <pre className="text-cyan-500 text-xs leading-none font-bold">
18
- {` ██████╗████████╗ █████╗ ██████╗██╗ ██╗'██████╗
19
- ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝██╔══██╗
20
- ╚█████╗ ██║ ███████║██║ █████═╝ ██║ ██║
21
- ╚═══██╗ ██║ ██╔══██║██║ ██╔═██╗ ██║ ██║
22
- ██████╔╝ ██║ ██║ ██║╚██████╗██║ ██╗██████╔╝
23
- ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═════╝`}
24
- </pre>
25
- <p className="text-sm text-cyan-500/80 mt-2">Full Stack Project Generator</p>
26
- </div>
27
-
28
- <a href="https://github.com/ShyamSunder06/STACKD" target="_blank" rel="noopener noreferrer" className="absolute right-8 text-muted-foreground hover:text-foreground">
29
- <svg viewBox="0 0 24 24" className="h-6 w-6" fill="currentColor">
30
- <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
31
- </svg>
32
- </a>
33
- </div>
34
- </nav>);
35
- const TerminalLogs = ({ logs }) => (<div className="bg-black rounded-lg p-4 font-mono text-sm text-green-400 max-h-96 overflow-auto">
36
- {logs.map((log, i) => (<div key={i} className="whitespace-pre-wrap">
37
- <span className="text-blue-400">$</span> {log}
38
- </div>))}
39
- </div>);
40
- const SuccessAnimation = ({ projectPath }) => (<motion.div initial={{ opacity: 0, scale: 0.5 }} animate={{ opacity: 1, scale: 1 }} className="text-center p-8">
41
- <motion.div animate={{ rotate: 360 }} transition={{ duration: 0.5 }} className="text-6xl mb-4">
42
- 🎉
43
- </motion.div>
44
- <h2 className="text-2xl font-bold mb-4">Congratulations!</h2>
45
- <p className="text-muted-foreground mb-6">
46
- Your project is ready. Happy coding!
47
- </p>
48
- <div className="bg-secondary p-4 rounded-lg mb-6">
49
- <p className="font-medium mb-2">Project Location:</p>
50
- <code className="text-sm">{projectPath}</code>
51
- </div>
52
- <Button onClick={() => window.open(`file://${projectPath}`, '_blank')} className="gap-2">
53
- <FolderOpen className="h-4 w-4"/>
54
- Open Project Folder
55
- </Button>
56
- </motion.div>);
57
- const ScaffoldPage = () => {
58
- const [step, setStep] = useState(0);
59
- const [config, setConfig] = useState({
60
- projectName: '',
61
- projectPath: process.cwd(),
62
- frontendPort: 3000,
63
- backendPort: 3001,
64
- frontend: null,
65
- backend: null,
66
- database: null,
67
- orm: null,
68
- auth: null,
69
- dbUrl: '',
70
- giturl: null,
71
- ui: null,
72
- });
73
- const [isGenerating, setIsGenerating] = useState(false);
74
- const [logs, setLogs] = useState([]);
75
- const [isSuccess, setIsSuccess] = useState(false);
76
- const [generatedPath, setGeneratedPath] = useState('');
77
- useEffect(() => {
78
- if (isGenerating) {
79
- const eventSource = new EventSource('/api/scaffold/logs');
80
- eventSource.onmessage = (event) => {
81
- setLogs(prev => [...prev, event.data]);
82
- };
83
- eventSource.onerror = () => {
84
- eventSource.close();
85
- };
86
- return () => eventSource.close();
87
- }
88
- }, [isGenerating]);
89
- const steps = [
90
- {
91
- title: "Project Settings",
92
- description: "Basic configuration",
93
- icon: <FolderOpen className="w-5 h-5"/>,
94
- component: (<div className="space-y-4 w-full max-w-md">
95
- <div>
96
- <Label htmlFor="projectName">Project Name</Label>
97
- <Input id="projectName" placeholder="my-fullstack-app" value={config.projectName} onChange={(e) => setConfig(prev => ({ ...prev, projectName: e.target.value }))}/>
98
- </div>
99
- <div>
100
- <Label htmlFor="projectPath">Project Location</Label>
101
- <Input id="projectPath" placeholder="/path/to/your/project" value={config.projectPath} onChange={(e) => setConfig(prev => ({ ...prev, projectPath: e.target.value }))}/>
102
- </div>
103
- <div className="grid grid-cols-2 gap-4">
104
- <div>
105
- <Label htmlFor="frontendPort">Frontend Port</Label>
106
- <Input id="frontendPort" type="number" value={config.frontendPort} onChange={(e) => setConfig(prev => ({ ...prev, frontendPort: parseInt(e.target.value) }))}/>
107
- </div>
108
- <div>
109
- <Label htmlFor="backendPort">Backend Port</Label>
110
- <Input id="backendPort" type="number" value={config.backendPort} onChange={(e) => setConfig(prev => ({ ...prev, backendPort: parseInt(e.target.value) }))}/>
111
- </div>
112
- </div>
113
- </div>)
114
- },
115
- {
116
- title: "Frontend",
117
- description: "Choose your frontend",
118
- icon: <Layout className="w-5 h-5"/>,
119
- options: [
120
- { id: 'react-ts', name: 'React + TypeScript', description: 'React with TypeScript template', features: ['Vite', 'TypeScript', 'React Router', 'TailwindCSS'] },
121
- { id: 'react', name: 'React (JavaScript)', description: 'React with JavaScript template', features: ['Vite', 'JavaScript', 'React Router', 'TailwindCSS'] },
122
- { id: 'django', name: 'Django Templates', description: 'Django framework', features: ['Full-stack', 'Django ORM', 'Django Admin'] },
123
- { id: 'vue-ts', name: 'Vue + TypeScript', description: 'Vue 3 with TypeScript template', features: ['Vite', 'TypeScript', 'Vue Router', 'Pinia', 'TailwindCSS'] },
124
- { id: 'vue', name: 'Vue (JavaScript)', description: 'Vue 3 with JavaScript template', features: ['Vite', 'JavaScript', 'Vue Router', 'Pinia', 'TailwindCSS'] },
125
- { id: 'angularts', name: 'Angular (Typescript)', description: 'Angular 16 with Typescript template', features: ['Angular CLI', 'Typescript', 'Angular Router', 'Angular Material', 'TailwindCSS'] },
126
- { id: 'nextjs', name: 'Next.js', description: 'Next.js with TypeScript template', features: ['Next.js', 'TypeScript', 'TailwindCSS'] },
127
- { id: 'Skip', name: 'Skip', description: 'Skip frontend configuration', features: ['Skip this step'] },
128
- ]
129
- },
130
- {
131
- title: "UI",
132
- description: "Choose your UI",
133
- icon: <Layout className="w-5 h-5"/>,
134
- options: [
135
- { id: 'shadcn', name: 'Shadcn', description: 'Shadcn UI', features: ['Shadcn UI', 'TailwindCSS'] },
136
- { id: 'tailwind', name: 'TailwindCSS', description: 'TailwindCSS', features: ['TailwindCSS', 'React'] },
137
- { id: 'Skip', name: 'Skip', description: 'Skip UI configuration', features: ['Skip this step'] },
138
- ]
139
- },
140
- {
141
- title: "Backend",
142
- description: "Select your backend",
143
- icon: <Server className="w-5 h-5"/>,
144
- options: [
145
- { id: 'express-ts', name: 'Express + TypeScript', description: 'Express with TypeScript setup', features: ['TypeScript', 'API Routes', 'Middleware', 'CORS'] },
146
- { id: 'express', name: 'Express (JavaScript)', description: 'Express with JavaScript setup', features: ['JavaScript', 'API Routes', 'Middleware', 'CORS'] },
147
- { id: 'django', name: 'Django', description: 'Django framework', features: ['Full-stack', 'Django ORM', 'Django Admin'] },
148
- { id: 'Skip', name: 'Skip', description: 'Skip backend configuration', features: ['Skip this step'] }
149
- ]
150
- },
151
- {
152
- title: "Database",
153
- description: "Pick your database",
154
- icon: <Database className="w-5 h-5"/>,
155
- options: [
156
- { id: 'postgresql', name: 'PostgreSQL', description: 'Powerful, open source database', features: ['Prisma ORM', 'Migrations', 'TypeScript'] },
157
- { id: 'mongodb', name: 'MongoDB', description: 'NoSQL document database', features: ['Mongoose', 'Schemas', 'TypeScript'] },
158
- { id: 'Skip', name: 'Skip', description: 'Skip database configuration', features: ['Skip this step'] }
159
- ]
160
- },
161
- {
162
- title: "ORM",
163
- description: "Select your ORM",
164
- icon: <Database className="w-5 h-5"/>,
165
- options: config.database === 'postgresql' ? [
166
- { id: 'prisma', name: 'Prisma', description: 'Prisma ORM', features: ['Type-safe', 'Migrations'] },
167
- { id: 'drizzle', name: 'Drizzle', description: 'Drizzle ORM', features: ['Lightweight', 'Flexible'] },
168
- { id: 'Skip', name: 'Skip', description: 'Skip ORM configuration', features: ['Skip this step'] }
169
- ] : config.database === 'mongodb' ? [
170
- { id: 'mongoose', name: 'Mongoose', description: 'Mongoose ORM', features: ['Schemas', 'Validation'] },
171
- { id: 'Skip', name: 'Skip', description: 'Skip ORM configuration', features: ['Skip this step'] }
172
- ] : [
173
- { id: 'Skip', name: 'Skip', description: 'Skip ORM configuration', features: ['Skip this step'] }
174
- ]
175
- },
176
- {
177
- title: "auth",
178
- description: "Choose your authentication method",
179
- icon: <Server className="w-5 h-5"/>,
180
- options: [
181
- { id: 'jwt', name: 'JWT', description: 'JSON Web Tokens', features: ['Stateless', 'Secure'] },
182
- { id: 'nextauth', name: 'NextAuth', description: 'NextAuth.js', features: ['Strategies', 'Middleware'] },
183
- { id: 'passport', name: 'Passport', description: 'Passport.js', features: ['Strategies', 'Middleware'] },
184
- { id: 'Skip', name: 'Skip', description: 'Skip authentication configuration', features: ['Skip this step'] }
185
- ]
186
- },
187
- {
188
- title: "Database URL",
189
- description: "Enter your database URL",
190
- icon: <Database className="w-5 h-5"/>,
191
- component: config.database !== 'Skip' ? (<div className="space-y-4 w-full max-w-md">
192
- <div>
193
- <Label htmlFor="dbUrl">Database URL</Label>
194
- <Input id="dbUrl" placeholder="Enter your database URL" value={config.dbUrl} onChange={(e) => setConfig(prev => ({ ...prev, dbUrl: e.target.value }))}/>
195
- </div>
196
- </div>) : null
197
- }, {
198
- title: "Git URL",
199
- description: "Enter your git URL",
200
- icon: <Database className="w-5 h-5"/>,
201
- component: config.giturl !== 'Skip' ? (<div className="space-y-4 w-full max-w-md">
202
- <div>
203
- <Label htmlFor="giturl">Git URL</Label>
204
- <Input id="giturl" placeholder="Enter your git URL" value={config.giturl || ''} onChange={(e) => setConfig(prev => ({ ...prev, giturl: e.target.value }))}/>
205
- </div>
206
- </div>) : null
207
- }
208
- ];
209
- const handleSelect = (key, value) => {
210
- setConfig(prev => ({ ...prev, [key]: value }));
211
- if (step < steps.length - 1) {
212
- setStep(step + 1);
213
- }
214
- };
215
- const validateConfig = () => {
216
- if (!config.projectName.trim()) {
217
- toast.error('Please enter a project name');
218
- return false;
219
- }
220
- if (!config.projectPath.trim()) {
221
- toast.error('Please enter a project location');
222
- return false;
223
- }
224
- if (config.frontendPort === config.backendPort) {
225
- toast.error('Frontend and backend ports must be different');
226
- return false;
227
- }
228
- return true;
229
- };
230
- const handleGenerate = async () => {
231
- if (!validateConfig())
232
- return;
233
- try {
234
- setIsGenerating(true);
235
- setLogs([]);
236
- const response = await fetch('/api/scaffold', {
237
- method: 'POST',
238
- headers: { 'Content-Type': 'application/json' },
239
- body: JSON.stringify(config)
240
- });
241
- if (!response.ok)
242
- throw new Error('Failed to generate project');
243
- const result = await response.json();
244
- if (result.success) {
245
- setGeneratedPath(result.projectPath);
246
- setIsSuccess(true);
247
- }
248
- }
249
- catch (error) {
250
- toast.error('Failed to generate project');
251
- }
252
- finally {
253
- setIsGenerating(false);
254
- }
255
- };
256
- return (<div className="min-h-screen bg-background">
257
- <Navbar />
258
- <div className="p-8">
259
- <div className="max-w-6xl mx-auto">
260
- <div className="mb-8">
261
- <h1 className="text-4xl font-bold mb-2">Create Your Project</h1>
262
- <p className="text-muted-foreground">
263
- Configure your full-stack application
264
- </p>
265
- </div>
266
-
267
- <Steps steps={steps.map(s => ({
268
- title: s.title,
269
- description: s.description,
270
- icon: s.icon
271
- }))} currentStep={step} onStepClick={setStep}/>
272
-
273
- <div className="mt-8">
274
- {steps[step]?.component ? (<div className="flex justify-center">
275
- {steps[step].component}
276
- </div>) : (<div className="relative">
277
- <div className="grid md:grid-cols-3 gap-4 card-grid">
278
- {steps[step]?.options?.filter(option => option.id !== 'Skip').map((option) => (<Card key={option.id} className={`card p-4 cursor-pointer interactive-element ${config[steps[step]?.title.toLowerCase()] === option.id
279
- ? 'border-primary/50 bg-primary/5 card-selected'
280
- : ''}`} onClick={() => handleSelect(steps[step]?.title.toLowerCase(), option.id)}>
281
- <div className="relative z-10">
282
- <h3 className="font-medium mb-2 text-lg">{option.name}</h3>
283
- <p className="text-sm text-muted-foreground mb-4">
284
- {option.description}
285
- </p>
286
- <div className="space-y-1">
287
- {option.features.map((feature, index) => (<div key={index} className="text-xs text-muted-foreground flex items-center gap-1">
288
- <span className="text-primary">•</span> {feature}
289
- </div>))}
290
- </div>
291
- </div>
292
- </Card>))}
293
- </div>
294
- </div>)}
295
-
296
- <div className="mt-8 flex justify-between">
297
- <Button variant="outline" onClick={() => setStep(Math.max(0, step - 1))} disabled={step === 0} className="px-6">
298
- Previous
299
- </Button>
300
-
301
- {step === steps.length - 1 ? (<Button onClick={handleGenerate} className="px-6">
302
- Generate Project
303
- </Button>) : (<div className="flex gap-2">
304
- {step > 0 && !steps[step].component && (<SkipButton onSkip={() => handleSelect(steps[step]?.title.toLowerCase(), 'Skip')}/>)}
305
- <Button onClick={() => setStep(Math.min(steps.length - 1, step + 1))} disabled={step === 0
306
- ? !config.projectName || !config.projectPath
307
- : step === steps.length - 2 && config.database !== 'Skip' // Database URL step
308
- ? !config.dbUrl
309
- : step === steps.length - 1 && config.giturl !== 'Skip' // Git URL step
310
- ? !config.giturl
311
- : !config[steps[step]?.title.toLowerCase()]} className="px-6">
312
- Next
313
- </Button>
314
- </div>)}
315
- </div>
316
- </div>
317
-
318
- {isSuccess ? (<SuccessAnimation projectPath={generatedPath}/>) : isGenerating ? (<div className="space-y-4">
319
- <h2 className="text-xl font-semibold">Generating Your Project...</h2>
320
- <TerminalLogs logs={logs}/>
321
- </div>) : null}
322
- </div>
323
- </div>
324
- </div>);
325
- };
326
- export default ScaffoldPage;
@@ -1,54 +0,0 @@
1
- 'use client';
2
- import React, { useState } from 'react';
3
- import { motion } from 'framer-motion';
4
- import { Home, GitFork, Github, ChevronFirst, ChevronLast, FolderGit2, Menu } from 'lucide-react';
5
- import { useRouter } from 'next/navigation';
6
- export const Sidebar = () => {
7
- const [isOpen, setIsOpen] = useState(true);
8
- const router = useRouter();
9
- const toggleSidebar = () => {
10
- setIsOpen(!isOpen);
11
- };
12
- const menuItems = [
13
- { icon: Home, label: "Home", href: "/home" },
14
- { icon: FolderGit2, label: "Local Repositories", href: "/local-repos" },
15
- { icon: GitFork, label: "Remote Repositories", href: "/commit" },
16
- { icon: Github, label: "GitHub Summary", href: "/user" },
17
- ];
18
- return (<motion.div animate={{ width: isOpen ? 280 : 72 }} transition={{ duration: 0.3 }} className="relative text-neutral-400 h-screen bg-[#1e1e1e] border-r-4 border-cyan-800">
19
- <div className="flex items-center justify-between p-4 border-b border-neutral-800">
20
- {isOpen && (<motion.span initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.1 }} className="text-lg font-semibold text-neutral-200">
21
- Dashboard
22
- </motion.span>)}
23
- <button onClick={toggleSidebar} className="absolute right-2 p-2 hover:bg-cyan-800 rounded-lg transition-colors">
24
- {isOpen ? (<ChevronFirst className="h-5 w-5"/>) : (<ChevronLast className="h-5 w-5"/>)}
25
- </button>
26
- </div>
27
-
28
- <div className="space-y-1 py-4">
29
- {menuItems.map((item, index) => (<motion.div key={index} whileHover={{ x: 4 }} className={`flex items-center cursor-pointer
30
- ${isOpen ? 'px-4' : 'justify-center px-2'}
31
- py-3 mx-2 rounded-lg hover:bg-neutral-800 hover:text-cyan-500
32
- transition-colors group relative`} onClick={() => router.push(item.href)}>
33
- <item.icon className="h-5 w-5 min-w-[20px]"/>
34
- {isOpen && (<motion.span initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.1 }} className="ml-4 text-sm">
35
- {item.label}
36
- </motion.span>)}
37
- {!isOpen && (<div className="absolute left-full rounded-md px-2 py-1 ml-6 bg-neutral-900 text-neutral-200 text-sm
38
- invisible opacity-0 -translate-x-3 transition-all group-hover:visible group-hover:opacity-100 group-hover:translate-x-0">
39
- {item.label}
40
- </div>)}
41
- </motion.div>))}
42
- </div>
43
-
44
-
45
- <div className="absolute bottom-0 w-full border-t border-neutral-800 p-4">
46
- <div className={`flex items-center ${isOpen ? '' : 'justify-center'}`}>
47
- <Menu className="h-5 w-5 min-w-[20px]"/>
48
- {isOpen && (<motion.span initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.1 }} className="ml-4 text-sm">
49
- Toggle Menu
50
- </motion.span>)}
51
- </div>
52
- </div>
53
- </motion.div>);
54
- };
@@ -1,6 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import { ThemeProvider as NextThemesProvider } from "next-themes";
4
- export function ThemeProvider({ children, ...props }) {
5
- return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
6
- }
@@ -1,32 +0,0 @@
1
- import * as React from "react";
2
- import { Slot } from "@radix-ui/react-slot";
3
- import { cva } from "class-variance-authority";
4
- import { cn } from "@/lib/utils";
5
- const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", {
6
- variants: {
7
- variant: {
8
- default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
9
- destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
10
- outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
11
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
12
- ghost: "hover:bg-accent hover:text-accent-foreground",
13
- link: "text-primary underline-offset-4 hover:underline",
14
- },
15
- size: {
16
- default: "h-9 px-4 py-2",
17
- sm: "h-8 rounded-md px-3 text-xs",
18
- lg: "h-10 rounded-md px-8",
19
- icon: "h-9 w-9",
20
- },
21
- },
22
- defaultVariants: {
23
- variant: "default",
24
- size: "default",
25
- },
26
- });
27
- const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
28
- const Comp = asChild ? Slot : "button";
29
- return (<Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props}/>);
30
- });
31
- Button.displayName = "Button";
32
- export { Button, buttonVariants };
@@ -1,15 +0,0 @@
1
- import * as React from "react";
2
- import { cn } from "@/lib/utils";
3
- const Card = React.forwardRef(({ className, ...props }, ref) => (<div ref={ref} className={cn("rounded-xl border bg-card text-card-foreground shadow", className)} {...props}/>));
4
- Card.displayName = "Card";
5
- const CardHeader = React.forwardRef(({ className, ...props }, ref) => (<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props}/>));
6
- CardHeader.displayName = "CardHeader";
7
- const CardTitle = React.forwardRef(({ className, ...props }, ref) => (<div ref={ref} className={cn("font-semibold leading-none tracking-tight", className)} {...props}/>));
8
- CardTitle.displayName = "CardTitle";
9
- const CardDescription = React.forwardRef(({ className, ...props }, ref) => (<div ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props}/>));
10
- CardDescription.displayName = "CardDescription";
11
- const CardContent = React.forwardRef(({ className, ...props }, ref) => (<div ref={ref} className={cn("p-6 pt-0", className)} {...props}/>));
12
- CardContent.displayName = "CardContent";
13
- const CardFooter = React.forwardRef(({ className, ...props }, ref) => (<div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props}/>));
14
- CardFooter.displayName = "CardFooter";
15
- export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
@@ -1,54 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
4
- import { Check, ChevronRight, Circle } from "lucide-react";
5
- import { cn } from "@/lib/utils";
6
- const DropdownMenu = DropdownMenuPrimitive.Root;
7
- const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
8
- const DropdownMenuGroup = DropdownMenuPrimitive.Group;
9
- const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
10
- const DropdownMenuSub = DropdownMenuPrimitive.Sub;
11
- const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
12
- const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }, ref) => (<DropdownMenuPrimitive.SubTrigger ref={ref} className={cn("flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", className)} {...props}>
13
- {children}
14
- <ChevronRight className="ml-auto"/>
15
- </DropdownMenuPrimitive.SubTrigger>));
16
- DropdownMenuSubTrigger.displayName =
17
- DropdownMenuPrimitive.SubTrigger.displayName;
18
- const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) => (<DropdownMenuPrimitive.SubContent ref={ref} className={cn("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className)} {...props}/>));
19
- DropdownMenuSubContent.displayName =
20
- DropdownMenuPrimitive.SubContent.displayName;
21
- const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => (<DropdownMenuPrimitive.Portal>
22
- <DropdownMenuPrimitive.Content ref={ref} sideOffset={sideOffset} className={cn("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className)} {...props}/>
23
- </DropdownMenuPrimitive.Portal>));
24
- DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
25
- const DropdownMenuItem = React.forwardRef(({ className, inset, ...props }, ref) => (<DropdownMenuPrimitive.Item ref={ref} className={cn("relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", className)} {...props}/>));
26
- DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
27
- const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, ...props }, ref) => (<DropdownMenuPrimitive.CheckboxItem ref={ref} className={cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className)} checked={checked} {...props}>
28
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
29
- <DropdownMenuPrimitive.ItemIndicator>
30
- <Check className="h-4 w-4"/>
31
- </DropdownMenuPrimitive.ItemIndicator>
32
- </span>
33
- {children}
34
- </DropdownMenuPrimitive.CheckboxItem>));
35
- DropdownMenuCheckboxItem.displayName =
36
- DropdownMenuPrimitive.CheckboxItem.displayName;
37
- const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props }, ref) => (<DropdownMenuPrimitive.RadioItem ref={ref} className={cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className)} {...props}>
38
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
39
- <DropdownMenuPrimitive.ItemIndicator>
40
- <Circle className="h-2 w-2 fill-current"/>
41
- </DropdownMenuPrimitive.ItemIndicator>
42
- </span>
43
- {children}
44
- </DropdownMenuPrimitive.RadioItem>));
45
- DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
46
- const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, ref) => (<DropdownMenuPrimitive.Label ref={ref} className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} {...props}/>));
47
- DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
48
- const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => (<DropdownMenuPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props}/>));
49
- DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
50
- const DropdownMenuShortcut = ({ className, ...props }) => {
51
- return (<span className={cn("ml-auto text-xs tracking-widest opacity-60", className)} {...props}/>);
52
- };
53
- DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
54
- export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuGroup, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuRadioGroup, };
@@ -1,7 +0,0 @@
1
- import * as React from "react";
2
- import { cn } from "@/lib/utils";
3
- const Input = React.forwardRef(({ className, type, ...props }, ref) => {
4
- return (<input type={type} className={cn("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className)} ref={ref} {...props}/>);
5
- });
6
- Input.displayName = "Input";
7
- export { Input };
@@ -1,9 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import * as LabelPrimitive from "@radix-ui/react-label";
4
- import { cva } from "class-variance-authority";
5
- import { cn } from "@/lib/utils";
6
- const labelVariants = cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
7
- const Label = React.forwardRef(({ className, ...props }, ref) => (<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props}/>));
8
- Label.displayName = LabelPrimitive.Root.displayName;
9
- export { Label };
@@ -1,19 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
4
- import { cn } from "@/lib/utils";
5
- const ScrollArea = React.forwardRef(({ className, children, ...props }, ref) => (<ScrollAreaPrimitive.Root ref={ref} className={cn("relative overflow-hidden", className)} {...props}>
6
- <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
7
- {children}
8
- </ScrollAreaPrimitive.Viewport>
9
- <ScrollBar />
10
- <ScrollAreaPrimitive.Corner />
11
- </ScrollAreaPrimitive.Root>));
12
- ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
13
- const ScrollBar = React.forwardRef(({ className, orientation = "vertical", ...props }, ref) => (<ScrollAreaPrimitive.ScrollAreaScrollbar ref={ref} orientation={orientation} className={cn("flex touch-none select-none transition-colors", orientation === "vertical" &&
14
- "h-full w-2.5 border-l border-l-transparent p-[1px]", orientation === "horizontal" &&
15
- "h-2.5 flex-col border-t border-t-transparent p-[1px]", className)} {...props}>
16
- <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border"/>
17
- </ScrollAreaPrimitive.ScrollAreaScrollbar>));
18
- ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
19
- export { ScrollArea, ScrollBar };
@@ -1,15 +0,0 @@
1
- "use client";
2
- import { useTheme } from "next-themes";
3
- import { Toaster as Sonner } from "sonner";
4
- const Toaster = ({ ...props }) => {
5
- const { theme = "system" } = useTheme();
6
- return (<Sonner theme={theme} className="toaster group" toastOptions={{
7
- classNames: {
8
- toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
9
- description: "group-[.toast]:text-muted-foreground",
10
- actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
11
- cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
12
- },
13
- }} {...props}/>);
14
- };
15
- export { Toaster };
@@ -1,14 +0,0 @@
1
- export function Steps({ steps, currentStep, onStepClick }) {
2
- return (<div className="flex justify-between">
3
- {steps.map((step, index) => (<div key={step.title} className={`flex flex-col items-center cursor-pointer ${index <= currentStep ? 'text-primary' : 'text-muted-foreground'}`} onClick={() => onStepClick(index)}>
4
- <div className={`
5
- w-10 h-10 rounded-full border-2 flex items-center justify-center mb-2
6
- ${index <= currentStep ? 'border-primary' : 'border-muted'}
7
- `}>
8
- {step.icon}
9
- </div>
10
- <div className="text-sm font-medium">{step.title}</div>
11
- <div className="text-xs text-muted-foreground">{step.description}</div>
12
- </div>))}
13
- </div>);
14
- }
@@ -1,9 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import * as SwitchPrimitives from "@radix-ui/react-switch";
4
- import { cn } from "@/lib/utils";
5
- const Switch = React.forwardRef(({ className, ...props }, ref) => (<SwitchPrimitives.Root className={cn("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", className)} {...props} ref={ref}>
6
- <SwitchPrimitives.Thumb className={cn("pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0")}/>
7
- </SwitchPrimitives.Root>));
8
- Switch.displayName = SwitchPrimitives.Root.displayName;
9
- export { Switch };
@@ -1,32 +0,0 @@
1
- import GitHubProvider from "next-auth/providers/github";
2
- export const authOptions = {
3
- providers: [
4
- GitHubProvider({
5
- clientId: process.env.GITHUB_ID || " ",
6
- clientSecret: process.env.GITHUB_SECRET || " ",
7
- authorization: {
8
- params: {
9
- scope: "repo read:user read:org workflow",
10
- },
11
- },
12
- }),
13
- ],
14
- callbacks: {
15
- async jwt({ token, account }) {
16
- console.log(account);
17
- if (account) {
18
- token.accessToken = account.access_token;
19
- }
20
- return token;
21
- },
22
- async session({ session, token }) {
23
- // console.log(token)
24
- session.accessToken = token.accessToken;
25
- return session;
26
- },
27
- async redirect({ baseUrl }) {
28
- return `${baseUrl}/home`;
29
- },
30
- },
31
- secret: process.env.NEXTAUTH_SECRET || " ",
32
- };
@@ -1,9 +0,0 @@
1
- import { createClient } from 'redis';
2
- const redis = createClient({
3
- url: process.env.REDIS_URL || 'redis://localhost:6379'
4
- });
5
- redis.on('error', (err) => console.error('Redis Client Error', err));
6
- if (!redis.isOpen) {
7
- redis.connect();
8
- }
9
- export default redis;
@@ -1,5 +0,0 @@
1
- import { clsx } from "clsx";
2
- import { twMerge } from "tailwind-merge";
3
- export function cn(...inputs) {
4
- return twMerge(clsx(inputs));
5
- }