helix-lang 11.0.0

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 (193) hide show
  1. package/README.md +168 -0
  2. package/dist/architect.d.ts +14 -0
  3. package/dist/architect.d.ts.map +1 -0
  4. package/dist/architect.js +127 -0
  5. package/dist/architect.js.map +1 -0
  6. package/dist/bin/helix.d.ts +20 -0
  7. package/dist/bin/helix.d.ts.map +1 -0
  8. package/dist/bin/helix.js +921 -0
  9. package/dist/bin/helix.js.map +1 -0
  10. package/dist/commands/collaborate/index.d.ts +2 -0
  11. package/dist/commands/collaborate/index.d.ts.map +1 -0
  12. package/dist/commands/collaborate/index.js +129 -0
  13. package/dist/commands/collaborate/index.js.map +1 -0
  14. package/dist/commands/collaborate/server.d.ts +31 -0
  15. package/dist/commands/collaborate/server.d.ts.map +1 -0
  16. package/dist/commands/collaborate/server.js +159 -0
  17. package/dist/commands/collaborate/server.js.map +1 -0
  18. package/dist/commands/deploy/index.d.ts +25 -0
  19. package/dist/commands/deploy/index.d.ts.map +1 -0
  20. package/dist/commands/deploy/index.js +130 -0
  21. package/dist/commands/deploy/index.js.map +1 -0
  22. package/dist/commands/deploy/platforms/fly.d.ts +9 -0
  23. package/dist/commands/deploy/platforms/fly.d.ts.map +1 -0
  24. package/dist/commands/deploy/platforms/fly.js +68 -0
  25. package/dist/commands/deploy/platforms/fly.js.map +1 -0
  26. package/dist/commands/deploy/platforms/railway.d.ts +9 -0
  27. package/dist/commands/deploy/platforms/railway.d.ts.map +1 -0
  28. package/dist/commands/deploy/platforms/railway.js +115 -0
  29. package/dist/commands/deploy/platforms/railway.js.map +1 -0
  30. package/dist/commands/deploy/platforms/vercel.d.ts +10 -0
  31. package/dist/commands/deploy/platforms/vercel.d.ts.map +1 -0
  32. package/dist/commands/deploy/platforms/vercel.js +126 -0
  33. package/dist/commands/deploy/platforms/vercel.js.map +1 -0
  34. package/dist/commands/deploy.d.ts +6 -0
  35. package/dist/commands/deploy.d.ts.map +1 -0
  36. package/dist/commands/deploy.js +56 -0
  37. package/dist/commands/deploy.js.map +1 -0
  38. package/dist/commands/evolve/analyzers/performance.d.ts +13 -0
  39. package/dist/commands/evolve/analyzers/performance.d.ts.map +1 -0
  40. package/dist/commands/evolve/analyzers/performance.js +591 -0
  41. package/dist/commands/evolve/analyzers/performance.js.map +1 -0
  42. package/dist/commands/evolve/analyzers/security.d.ts +21 -0
  43. package/dist/commands/evolve/analyzers/security.d.ts.map +1 -0
  44. package/dist/commands/evolve/analyzers/security.js +280 -0
  45. package/dist/commands/evolve/analyzers/security.js.map +1 -0
  46. package/dist/commands/evolve/index.d.ts +2 -0
  47. package/dist/commands/evolve/index.d.ts.map +1 -0
  48. package/dist/commands/evolve/index.js +122 -0
  49. package/dist/commands/evolve/index.js.map +1 -0
  50. package/dist/commands/generate.d.ts +6 -0
  51. package/dist/commands/generate.d.ts.map +1 -0
  52. package/dist/commands/generate.js +277 -0
  53. package/dist/commands/generate.js.map +1 -0
  54. package/dist/commands/install.d.ts +2 -0
  55. package/dist/commands/install.d.ts.map +1 -0
  56. package/dist/commands/install.js +176 -0
  57. package/dist/commands/install.js.map +1 -0
  58. package/dist/commands/library/index.d.ts +27 -0
  59. package/dist/commands/library/index.d.ts.map +1 -0
  60. package/dist/commands/library/index.js +126 -0
  61. package/dist/commands/library/index.js.map +1 -0
  62. package/dist/commands/migrate.d.ts +5 -0
  63. package/dist/commands/migrate.d.ts.map +1 -0
  64. package/dist/commands/migrate.js +258 -0
  65. package/dist/commands/migrate.js.map +1 -0
  66. package/dist/commands/new.d.ts +6 -0
  67. package/dist/commands/new.d.ts.map +1 -0
  68. package/dist/commands/new.js +195 -0
  69. package/dist/commands/new.js.map +1 -0
  70. package/dist/commands/preflight.d.ts +20 -0
  71. package/dist/commands/preflight.d.ts.map +1 -0
  72. package/dist/commands/preflight.js +182 -0
  73. package/dist/commands/preflight.js.map +1 -0
  74. package/dist/commands/preview.d.ts +13 -0
  75. package/dist/commands/preview.d.ts.map +1 -0
  76. package/dist/commands/preview.js +260 -0
  77. package/dist/commands/preview.js.map +1 -0
  78. package/dist/commands/run.d.ts +6 -0
  79. package/dist/commands/run.d.ts.map +1 -0
  80. package/dist/commands/run.js +96 -0
  81. package/dist/commands/run.js.map +1 -0
  82. package/dist/commands/spawn.d.ts +11 -0
  83. package/dist/commands/spawn.d.ts.map +1 -0
  84. package/dist/commands/spawn.js +916 -0
  85. package/dist/commands/spawn.js.map +1 -0
  86. package/dist/compiler.d.ts +12 -0
  87. package/dist/compiler.d.ts.map +1 -0
  88. package/dist/compiler.js +92 -0
  89. package/dist/compiler.js.map +1 -0
  90. package/dist/core/file-writer.d.ts +36 -0
  91. package/dist/core/file-writer.d.ts.map +1 -0
  92. package/dist/core/file-writer.js +268 -0
  93. package/dist/core/file-writer.js.map +1 -0
  94. package/dist/core/registry.d.ts +57 -0
  95. package/dist/core/registry.d.ts.map +1 -0
  96. package/dist/core/registry.js +222 -0
  97. package/dist/core/registry.js.map +1 -0
  98. package/dist/core/self-healing.d.ts +47 -0
  99. package/dist/core/self-healing.d.ts.map +1 -0
  100. package/dist/core/self-healing.js +250 -0
  101. package/dist/core/self-healing.js.map +1 -0
  102. package/dist/core/types.d.ts +126 -0
  103. package/dist/core/types.d.ts.map +1 -0
  104. package/dist/core/types.js +7 -0
  105. package/dist/core/types.js.map +1 -0
  106. package/dist/generators/databases/mongodb.d.ts +10 -0
  107. package/dist/generators/databases/mongodb.d.ts.map +1 -0
  108. package/dist/generators/databases/mongodb.js +83 -0
  109. package/dist/generators/databases/mongodb.js.map +1 -0
  110. package/dist/generators/databases/redis.d.ts +2 -0
  111. package/dist/generators/databases/redis.d.ts.map +1 -0
  112. package/dist/generators/databases/redis.js +140 -0
  113. package/dist/generators/databases/redis.js.map +1 -0
  114. package/dist/generators/flutter.d.ts +32 -0
  115. package/dist/generators/flutter.d.ts.map +1 -0
  116. package/dist/generators/flutter.js +628 -0
  117. package/dist/generators/flutter.js.map +1 -0
  118. package/dist/openrouter.d.ts +68 -0
  119. package/dist/openrouter.d.ts.map +1 -0
  120. package/dist/openrouter.js +241 -0
  121. package/dist/openrouter.js.map +1 -0
  122. package/dist/page-generator.d.ts +22 -0
  123. package/dist/page-generator.d.ts.map +1 -0
  124. package/dist/page-generator.js +192 -0
  125. package/dist/page-generator.js.map +1 -0
  126. package/dist/parser.d.ts +76 -0
  127. package/dist/parser.d.ts.map +1 -0
  128. package/dist/parser.js +691 -0
  129. package/dist/parser.js.map +1 -0
  130. package/dist/prompts/master-architect.d.ts +9 -0
  131. package/dist/prompts/master-architect.d.ts.map +1 -0
  132. package/dist/prompts/master-architect.js +150 -0
  133. package/dist/prompts/master-architect.js.map +1 -0
  134. package/dist/researcher.d.ts +12 -0
  135. package/dist/researcher.d.ts.map +1 -0
  136. package/dist/researcher.js +85 -0
  137. package/dist/researcher.js.map +1 -0
  138. package/dist/self-heal.d.ts +29 -0
  139. package/dist/self-heal.d.ts.map +1 -0
  140. package/dist/self-heal.js +260 -0
  141. package/dist/self-heal.js.map +1 -0
  142. package/dist/services/SupabaseDeployer.d.ts +9 -0
  143. package/dist/services/SupabaseDeployer.d.ts.map +1 -0
  144. package/dist/services/SupabaseDeployer.js +50 -0
  145. package/dist/services/SupabaseDeployer.js.map +1 -0
  146. package/dist/test-generator.d.ts +18 -0
  147. package/dist/test-generator.d.ts.map +1 -0
  148. package/dist/test-generator.js +180 -0
  149. package/dist/test-generator.js.map +1 -0
  150. package/dist/themes/index.d.ts +52 -0
  151. package/dist/themes/index.d.ts.map +1 -0
  152. package/dist/themes/index.js +273 -0
  153. package/dist/themes/index.js.map +1 -0
  154. package/dist/types.d.ts +9 -0
  155. package/dist/types.d.ts.map +1 -0
  156. package/dist/types.js +81 -0
  157. package/dist/types.js.map +1 -0
  158. package/dist/utils/constitutional-validator.d.ts +73 -0
  159. package/dist/utils/constitutional-validator.d.ts.map +1 -0
  160. package/dist/utils/constitutional-validator.js +249 -0
  161. package/dist/utils/constitutional-validator.js.map +1 -0
  162. package/library/auth-flow/app/api/auth/[...nextauth]/route.ts +31 -0
  163. package/library/auth-flow/app/api/auth/login/route.ts +90 -0
  164. package/library/auth-flow/app/api/auth/register/route.ts +91 -0
  165. package/library/auth-flow/components/auth/AuthMiddleware.tsx +139 -0
  166. package/library/auth-flow/components/auth/LoginForm.tsx +125 -0
  167. package/library/auth-flow/components/auth/RegisterForm.tsx +168 -0
  168. package/library/auth-flow/components/auth/nextauth-config.ts +99 -0
  169. package/library/auth-flow/manifest.json +29 -0
  170. package/library/auth-flow/schema.prisma +45 -0
  171. package/library/dashboard-analytics/components/dashboard/ActivityFeed.tsx +109 -0
  172. package/library/dashboard-analytics/components/dashboard/LineChart.tsx +180 -0
  173. package/library/dashboard-analytics/components/dashboard/StatsCard.tsx +47 -0
  174. package/library/dashboard-analytics/components/dashboard/SummaryGrid.tsx +39 -0
  175. package/library/dashboard-analytics/manifest.json +19 -0
  176. package/library/data-table/components/table/BulkActions.tsx +59 -0
  177. package/library/data-table/components/table/ColumnToggle.tsx +65 -0
  178. package/library/data-table/components/table/DataTable.tsx +318 -0
  179. package/library/data-table/components/table/ExportCSV.tsx +52 -0
  180. package/library/data-table/components/table/SearchFilter.tsx +48 -0
  181. package/library/data-table/manifest.json +20 -0
  182. package/library/file-upload/app/api/upload/route.ts +107 -0
  183. package/library/file-upload/components/upload/DropZone.tsx +268 -0
  184. package/library/file-upload/components/upload/FilePreview.tsx +82 -0
  185. package/library/file-upload/components/upload/UploadProgress.tsx +92 -0
  186. package/library/file-upload/components/upload/fileStorage.ts +142 -0
  187. package/library/file-upload/manifest.json +21 -0
  188. package/library/notification-system/app/api/notifications/route.ts +121 -0
  189. package/library/notification-system/components/notifications/NotificationBell.tsx +154 -0
  190. package/library/notification-system/components/notifications/NotificationProvider.tsx +161 -0
  191. package/library/notification-system/components/notifications/Toast.tsx +112 -0
  192. package/library/notification-system/manifest.json +20 -0
  193. package/package.json +66 -0
@@ -0,0 +1,139 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ export interface AuthenticatedUser {
4
+ id: string;
5
+ email: string;
6
+ name: string | null;
7
+ }
8
+
9
+ interface SessionRecord {
10
+ id: string;
11
+ userId: string;
12
+ token: string;
13
+ expiresAt: string;
14
+ user: AuthenticatedUser;
15
+ }
16
+
17
+ /**
18
+ * Extracts the bearer token from an Authorization header.
19
+ */
20
+ function extractToken(request: NextRequest): string | null {
21
+ const authHeader = request.headers.get('authorization');
22
+ if (!authHeader) return null;
23
+
24
+ const [scheme, token] = authHeader.split(' ');
25
+ if (scheme?.toLowerCase() !== 'bearer' || !token) return null;
26
+
27
+ return token;
28
+ }
29
+
30
+ /**
31
+ * Middleware that validates a session token against the database.
32
+ * Wrap your API route handler with this to protect it.
33
+ *
34
+ * Usage:
35
+ * import { withAuth } from '@/components/auth/AuthMiddleware';
36
+ *
37
+ * export const GET = withAuth(async (request, user) => {
38
+ * return NextResponse.json({ message: `Hello ${user.email}` });
39
+ * });
40
+ */
41
+ export function withAuth(
42
+ handler: (request: NextRequest, user: AuthenticatedUser) => Promise<NextResponse>,
43
+ options: { sessionLookup?: (token: string) => Promise<SessionRecord | null> } = {}
44
+ ) {
45
+ return async (request: NextRequest): Promise<NextResponse> => {
46
+ const token = extractToken(request);
47
+
48
+ if (!token) {
49
+ return NextResponse.json(
50
+ { error: 'Authentication required' },
51
+ { status: 401 }
52
+ );
53
+ }
54
+
55
+ try {
56
+ let session: SessionRecord | null = null;
57
+
58
+ if (options.sessionLookup) {
59
+ session = await options.sessionLookup(token);
60
+ } else {
61
+ // Default: call internal session validation endpoint
62
+ const validateRes = await fetch(
63
+ new URL('/api/auth/validate', request.url).toString(),
64
+ {
65
+ method: 'POST',
66
+ headers: { 'Content-Type': 'application/json' },
67
+ body: JSON.stringify({ token }),
68
+ }
69
+ );
70
+
71
+ if (validateRes.ok) {
72
+ const data = await validateRes.json();
73
+ session = data.session;
74
+ }
75
+ }
76
+
77
+ if (!session) {
78
+ return NextResponse.json(
79
+ { error: 'Invalid or expired session' },
80
+ { status: 401 }
81
+ );
82
+ }
83
+
84
+ // Check expiry
85
+ if (new Date(session.expiresAt) < new Date()) {
86
+ return NextResponse.json(
87
+ { error: 'Session expired' },
88
+ { status: 401 }
89
+ );
90
+ }
91
+
92
+ return handler(request, session.user);
93
+ } catch {
94
+ return NextResponse.json(
95
+ { error: 'Authentication failed' },
96
+ { status: 500 }
97
+ );
98
+ }
99
+ };
100
+ }
101
+
102
+ /**
103
+ * Next.js middleware config helper for protecting routes at the edge.
104
+ * Add to middleware.ts:
105
+ *
106
+ * import { authMiddlewareConfig } from '@/components/auth/AuthMiddleware';
107
+ * export const config = authMiddlewareConfig(['/dashboard', '/settings']);
108
+ */
109
+ export function authMiddlewareConfig(protectedPaths: string[]) {
110
+ return {
111
+ matcher: protectedPaths.map((p) => `${p}/:path*`),
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Edge middleware handler for Next.js middleware.ts
117
+ */
118
+ export function createAuthMiddleware(protectedPaths: string[]) {
119
+ return async function middleware(request: NextRequest) {
120
+ const { pathname } = request.nextUrl;
121
+ const isProtected = protectedPaths.some((p) => pathname.startsWith(p));
122
+
123
+ if (!isProtected) {
124
+ return NextResponse.next();
125
+ }
126
+
127
+ const token =
128
+ request.cookies.get('authToken')?.value ||
129
+ extractToken(request);
130
+
131
+ if (!token) {
132
+ const loginUrl = new URL('/login', request.url);
133
+ loginUrl.searchParams.set('callbackUrl', pathname);
134
+ return NextResponse.redirect(loginUrl);
135
+ }
136
+
137
+ return NextResponse.next();
138
+ };
139
+ }
@@ -0,0 +1,125 @@
1
+ 'use client';
2
+
3
+ import { useState, type FormEvent } from 'react';
4
+
5
+ interface LoginFormProps {
6
+ onSuccess?: (user: { id: string; email: string; name: string | null }) => void;
7
+ onRegisterClick?: () => void;
8
+ redirectTo?: string;
9
+ }
10
+
11
+ export default function LoginForm({ onSuccess, onRegisterClick, redirectTo = '/dashboard' }: LoginFormProps) {
12
+ const [email, setEmail] = useState('');
13
+ const [password, setPassword] = useState('');
14
+ const [error, setError] = useState('');
15
+ const [loading, setLoading] = useState(false);
16
+
17
+ const handleSubmit = async (e: FormEvent) => {
18
+ e.preventDefault();
19
+ setError('');
20
+ setLoading(true);
21
+
22
+ try {
23
+ const response = await fetch('/api/auth/login', {
24
+ method: 'POST',
25
+ headers: { 'Content-Type': 'application/json' },
26
+ body: JSON.stringify({ email, password }),
27
+ });
28
+
29
+ const data = await response.json();
30
+
31
+ if (!response.ok) {
32
+ setError(data.error || 'Login failed');
33
+ return;
34
+ }
35
+
36
+ localStorage.setItem('authToken', data.token);
37
+
38
+ if (onSuccess) {
39
+ onSuccess(data.user);
40
+ } else {
41
+ window.location.href = redirectTo;
42
+ }
43
+ } catch (err: unknown) {
44
+ const message = err instanceof Error ? err.message : 'An unexpected error occurred';
45
+ setError(message);
46
+ } finally {
47
+ setLoading(false);
48
+ }
49
+ };
50
+
51
+ return (
52
+ <div className="w-full max-w-md mx-auto">
53
+ <div className="backdrop-blur-xl bg-white/5 border border-white/10 rounded-2xl p-8 shadow-2xl">
54
+ <h2 className="text-2xl font-bold text-white mb-2">Welcome back</h2>
55
+ <p className="text-white/50 mb-6">Sign in to your account</p>
56
+
57
+ {error && (
58
+ <div className="mb-4 p-3 bg-red-500/10 border border-red-500/20 text-red-400 rounded-lg text-sm">
59
+ {error}
60
+ </div>
61
+ )}
62
+
63
+ <form onSubmit={handleSubmit} className="space-y-5">
64
+ <div>
65
+ <label className="block text-sm font-medium text-white/70 mb-1.5">
66
+ Email
67
+ </label>
68
+ <input
69
+ type="email"
70
+ value={email}
71
+ onChange={(e) => setEmail(e.target.value)}
72
+ className="w-full px-4 py-2.5 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
73
+ placeholder="you@example.com"
74
+ required
75
+ />
76
+ </div>
77
+
78
+ <div>
79
+ <label className="block text-sm font-medium text-white/70 mb-1.5">
80
+ Password
81
+ </label>
82
+ <input
83
+ type="password"
84
+ value={password}
85
+ onChange={(e) => setPassword(e.target.value)}
86
+ className="w-full px-4 py-2.5 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
87
+ placeholder="Enter your password"
88
+ required
89
+ />
90
+ </div>
91
+
92
+ <button
93
+ type="submit"
94
+ disabled={loading}
95
+ className="w-full py-2.5 px-4 bg-cyan-500 text-white font-medium rounded-lg hover:bg-cyan-400 disabled:opacity-50 disabled:cursor-not-allowed transition-colors shadow-lg shadow-cyan-500/25"
96
+ >
97
+ {loading ? (
98
+ <span className="flex items-center justify-center gap-2">
99
+ <svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
100
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
101
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
102
+ </svg>
103
+ Signing in...
104
+ </span>
105
+ ) : (
106
+ 'Sign in'
107
+ )}
108
+ </button>
109
+ </form>
110
+
111
+ {onRegisterClick && (
112
+ <p className="mt-6 text-center text-sm text-white/50">
113
+ Don&apos;t have an account?{' '}
114
+ <button
115
+ onClick={onRegisterClick}
116
+ className="text-cyan-400 hover:text-cyan-300 font-medium transition-colors"
117
+ >
118
+ Create one
119
+ </button>
120
+ </p>
121
+ )}
122
+ </div>
123
+ </div>
124
+ );
125
+ }
@@ -0,0 +1,168 @@
1
+ 'use client';
2
+
3
+ import { useState, type FormEvent } from 'react';
4
+
5
+ interface RegisterFormProps {
6
+ onSuccess?: (user: { id: string; email: string; name: string }) => void;
7
+ onLoginClick?: () => void;
8
+ redirectTo?: string;
9
+ }
10
+
11
+ export default function RegisterForm({ onSuccess, onLoginClick, redirectTo = '/dashboard' }: RegisterFormProps) {
12
+ const [name, setName] = useState('');
13
+ const [email, setEmail] = useState('');
14
+ const [password, setPassword] = useState('');
15
+ const [confirmPassword, setConfirmPassword] = useState('');
16
+ const [error, setError] = useState('');
17
+ const [loading, setLoading] = useState(false);
18
+
19
+ const handleSubmit = async (e: FormEvent) => {
20
+ e.preventDefault();
21
+ setError('');
22
+
23
+ if (password !== confirmPassword) {
24
+ setError('Passwords do not match');
25
+ return;
26
+ }
27
+
28
+ if (password.length < 8) {
29
+ setError('Password must be at least 8 characters');
30
+ return;
31
+ }
32
+
33
+ setLoading(true);
34
+
35
+ try {
36
+ const response = await fetch('/api/auth/register', {
37
+ method: 'POST',
38
+ headers: { 'Content-Type': 'application/json' },
39
+ body: JSON.stringify({ name, email, password }),
40
+ });
41
+
42
+ const data = await response.json();
43
+
44
+ if (!response.ok) {
45
+ setError(data.error || 'Registration failed');
46
+ return;
47
+ }
48
+
49
+ localStorage.setItem('authToken', data.token);
50
+
51
+ if (onSuccess) {
52
+ onSuccess(data.user);
53
+ } else {
54
+ window.location.href = redirectTo;
55
+ }
56
+ } catch (err: unknown) {
57
+ const message = err instanceof Error ? err.message : 'An unexpected error occurred';
58
+ setError(message);
59
+ } finally {
60
+ setLoading(false);
61
+ }
62
+ };
63
+
64
+ return (
65
+ <div className="w-full max-w-md mx-auto">
66
+ <div className="backdrop-blur-xl bg-white/5 border border-white/10 rounded-2xl p-8 shadow-2xl">
67
+ <h2 className="text-2xl font-bold text-white mb-2">Create account</h2>
68
+ <p className="text-white/50 mb-6">Get started with your new account</p>
69
+
70
+ {error && (
71
+ <div className="mb-4 p-3 bg-red-500/10 border border-red-500/20 text-red-400 rounded-lg text-sm">
72
+ {error}
73
+ </div>
74
+ )}
75
+
76
+ <form onSubmit={handleSubmit} className="space-y-5">
77
+ <div>
78
+ <label className="block text-sm font-medium text-white/70 mb-1.5">
79
+ Full name
80
+ </label>
81
+ <input
82
+ type="text"
83
+ value={name}
84
+ onChange={(e) => setName(e.target.value)}
85
+ className="w-full px-4 py-2.5 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
86
+ placeholder="John Doe"
87
+ required
88
+ />
89
+ </div>
90
+
91
+ <div>
92
+ <label className="block text-sm font-medium text-white/70 mb-1.5">
93
+ Email
94
+ </label>
95
+ <input
96
+ type="email"
97
+ value={email}
98
+ onChange={(e) => setEmail(e.target.value)}
99
+ className="w-full px-4 py-2.5 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
100
+ placeholder="you@example.com"
101
+ required
102
+ />
103
+ </div>
104
+
105
+ <div>
106
+ <label className="block text-sm font-medium text-white/70 mb-1.5">
107
+ Password
108
+ </label>
109
+ <input
110
+ type="password"
111
+ value={password}
112
+ onChange={(e) => setPassword(e.target.value)}
113
+ className="w-full px-4 py-2.5 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
114
+ placeholder="Min. 8 characters"
115
+ minLength={8}
116
+ required
117
+ />
118
+ </div>
119
+
120
+ <div>
121
+ <label className="block text-sm font-medium text-white/70 mb-1.5">
122
+ Confirm password
123
+ </label>
124
+ <input
125
+ type="password"
126
+ value={confirmPassword}
127
+ onChange={(e) => setConfirmPassword(e.target.value)}
128
+ className="w-full px-4 py-2.5 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-cyan-500/50 focus:border-cyan-500/50 transition-all"
129
+ placeholder="Re-enter your password"
130
+ minLength={8}
131
+ required
132
+ />
133
+ </div>
134
+
135
+ <button
136
+ type="submit"
137
+ disabled={loading}
138
+ className="w-full py-2.5 px-4 bg-cyan-500 text-white font-medium rounded-lg hover:bg-cyan-400 disabled:opacity-50 disabled:cursor-not-allowed transition-colors shadow-lg shadow-cyan-500/25"
139
+ >
140
+ {loading ? (
141
+ <span className="flex items-center justify-center gap-2">
142
+ <svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
143
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
144
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
145
+ </svg>
146
+ Creating account...
147
+ </span>
148
+ ) : (
149
+ 'Create account'
150
+ )}
151
+ </button>
152
+ </form>
153
+
154
+ {onLoginClick && (
155
+ <p className="mt-6 text-center text-sm text-white/50">
156
+ Already have an account?{' '}
157
+ <button
158
+ onClick={onLoginClick}
159
+ className="text-cyan-400 hover:text-cyan-300 font-medium transition-colors"
160
+ >
161
+ Sign in
162
+ </button>
163
+ </p>
164
+ )}
165
+ </div>
166
+ </div>
167
+ );
168
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * NextAuth.js configuration boilerplate for Helix projects.
3
+ *
4
+ * Usage:
5
+ * 1. Copy this file to src/lib/auth.ts
6
+ * 2. Create app/api/auth/[...nextauth]/route.ts with:
7
+ * import NextAuth from 'next-auth';
8
+ * import { authOptions } from '@/lib/auth';
9
+ * const handler = NextAuth(authOptions);
10
+ * export { handler as GET, handler as POST };
11
+ * 3. Set NEXTAUTH_SECRET and NEXTAUTH_URL in .env
12
+ */
13
+
14
+ import type { NextAuthOptions, Session, User } from 'next-auth';
15
+ import type { JWT } from 'next-auth/jwt';
16
+ import CredentialsProvider from 'next-auth/providers/credentials';
17
+
18
+ /**
19
+ * Stub for password verification -- replace with your actual bcrypt compare.
20
+ */
21
+ async function verifyPassword(_plain: string, _hash: string): Promise<boolean> {
22
+ // Replace with: return bcrypt.compare(plain, hash);
23
+ return false;
24
+ }
25
+
26
+ /**
27
+ * Stub for user lookup -- replace with your Prisma/DB query.
28
+ */
29
+ async function findUserByEmail(_email: string): Promise<{
30
+ id: string;
31
+ email: string;
32
+ name: string | null;
33
+ passwordHash: string;
34
+ } | null> {
35
+ // Replace with: return prisma.user.findUnique({ where: { email } });
36
+ return null;
37
+ }
38
+
39
+ export const authOptions: NextAuthOptions = {
40
+ providers: [
41
+ CredentialsProvider({
42
+ name: 'Credentials',
43
+ credentials: {
44
+ email: { label: 'Email', type: 'email', placeholder: 'you@example.com' },
45
+ password: { label: 'Password', type: 'password' },
46
+ },
47
+ async authorize(credentials) {
48
+ if (!credentials?.email || !credentials?.password) {
49
+ throw new Error('Email and password are required');
50
+ }
51
+
52
+ const user = await findUserByEmail(credentials.email);
53
+
54
+ if (!user) {
55
+ throw new Error('Invalid credentials');
56
+ }
57
+
58
+ const isValid = await verifyPassword(credentials.password, user.passwordHash);
59
+
60
+ if (!isValid) {
61
+ throw new Error('Invalid credentials');
62
+ }
63
+
64
+ return {
65
+ id: user.id,
66
+ email: user.email,
67
+ name: user.name,
68
+ };
69
+ },
70
+ }),
71
+ ],
72
+
73
+ session: {
74
+ strategy: 'jwt',
75
+ maxAge: 7 * 24 * 60 * 60, // 7 days
76
+ },
77
+
78
+ pages: {
79
+ signIn: '/login',
80
+ error: '/login',
81
+ },
82
+
83
+ callbacks: {
84
+ async jwt({ token, user }: { token: JWT; user?: User }) {
85
+ if (user) {
86
+ token.id = user.id;
87
+ }
88
+ return token;
89
+ },
90
+ async session({ session, token }: { session: Session; token: JWT }) {
91
+ if (session.user && token.id) {
92
+ (session.user as Record<string, unknown>).id = token.id;
93
+ }
94
+ return session;
95
+ },
96
+ },
97
+
98
+ secret: process.env.NEXTAUTH_SECRET,
99
+ };
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "auth-flow",
3
+ "version": "1.0.0",
4
+ "description": "Complete authentication flow with login, registration, session middleware, and NextAuth configuration",
5
+ "author": "AD AI Engine",
6
+ "category": "auth",
7
+ "dependencies": [
8
+ "next-auth",
9
+ "@prisma/client",
10
+ "bcrypt",
11
+ "zod"
12
+ ],
13
+ "files": {
14
+ "schema": "schema.prisma",
15
+ "api": [
16
+ "app/api/auth/login/route.ts",
17
+ "app/api/auth/register/route.ts",
18
+ "app/api/auth/[...nextauth]/route.ts"
19
+ ],
20
+ "components": [
21
+ "components/auth/LoginForm.tsx",
22
+ "components/auth/RegisterForm.tsx",
23
+ "components/auth/AuthMiddleware.tsx",
24
+ "components/auth/nextauth-config.ts"
25
+ ]
26
+ },
27
+ "schema": "schema.prisma",
28
+ "instructions": "1. Install dependencies: npm install next-auth @prisma/client bcrypt zod\n2. Add NEXTAUTH_SECRET and NEXTAUTH_URL to .env\n3. Run npx prisma db push to create User/Session tables\n4. Wrap your app with SessionProvider from next-auth/react\n5. Use AuthMiddleware in API routes to protect endpoints"
29
+ }
@@ -0,0 +1,45 @@
1
+ // Prisma Schema additions for auth-flow component
2
+ // Merge into your existing schema.prisma
3
+
4
+ model User {
5
+ id String @id @default(uuid())
6
+ email String @unique
7
+ passwordHash String
8
+ name String?
9
+ image String?
10
+ emailVerified DateTime?
11
+ createdAt DateTime @default(now())
12
+ updatedAt DateTime @updatedAt
13
+ sessions Session[]
14
+ accounts Account[]
15
+ }
16
+
17
+ model Session {
18
+ id String @id @default(uuid())
19
+ userId String
20
+ token String @unique
21
+ expiresAt DateTime
22
+ createdAt DateTime @default(now())
23
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
24
+
25
+ @@index([token])
26
+ @@index([userId])
27
+ }
28
+
29
+ model Account {
30
+ id String @id @default(uuid())
31
+ userId String
32
+ type String
33
+ provider String
34
+ providerAccountId String
35
+ refresh_token String?
36
+ access_token String?
37
+ expires_at Int?
38
+ token_type String?
39
+ scope String?
40
+ id_token String?
41
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
42
+
43
+ @@unique([provider, providerAccountId])
44
+ @@index([userId])
45
+ }