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,121 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Server-Sent Events endpoint for real-time notifications.
5
+ *
6
+ * GET /api/notifications - Opens an SSE stream for the authenticated user.
7
+ * POST /api/notifications - Sends a notification (triggers SSE to all connected clients).
8
+ *
9
+ * Integration:
10
+ * const eventSource = new EventSource('/api/notifications');
11
+ * eventSource.onmessage = (event) => {
12
+ * const notification = JSON.parse(event.data);
13
+ * // Handle notification
14
+ * };
15
+ */
16
+
17
+ interface SSEClient {
18
+ id: string;
19
+ controller: ReadableStreamDefaultController;
20
+ }
21
+
22
+ // In-memory client registry (replace with Redis pub/sub for multi-instance)
23
+ const clients = new Map<string, SSEClient>();
24
+
25
+ function broadcastNotification(data: Record<string, unknown>) {
26
+ const message = `data: ${JSON.stringify(data)}\n\n`;
27
+ const encoder = new TextEncoder();
28
+ const encoded = encoder.encode(message);
29
+
30
+ for (const [id, client] of clients.entries()) {
31
+ try {
32
+ client.controller.enqueue(encoded);
33
+ } catch {
34
+ clients.delete(id);
35
+ }
36
+ }
37
+ }
38
+
39
+ export async function GET(request: NextRequest) {
40
+ const clientId = request.headers.get('x-client-id') || crypto.randomUUID();
41
+
42
+ const stream = new ReadableStream({
43
+ start(controller) {
44
+ clients.set(clientId, { id: clientId, controller });
45
+
46
+ // Send initial connection message
47
+ const encoder = new TextEncoder();
48
+ controller.enqueue(
49
+ encoder.encode(`data: ${JSON.stringify({ type: 'connected', clientId })}\n\n`)
50
+ );
51
+
52
+ // Heartbeat every 30s to keep connection alive
53
+ const heartbeat = setInterval(() => {
54
+ try {
55
+ controller.enqueue(encoder.encode(': heartbeat\n\n'));
56
+ } catch {
57
+ clearInterval(heartbeat);
58
+ clients.delete(clientId);
59
+ }
60
+ }, 30000);
61
+
62
+ // Cleanup on close
63
+ request.signal.addEventListener('abort', () => {
64
+ clearInterval(heartbeat);
65
+ clients.delete(clientId);
66
+ try {
67
+ controller.close();
68
+ } catch {
69
+ // Already closed
70
+ }
71
+ });
72
+ },
73
+ cancel() {
74
+ clients.delete(clientId);
75
+ },
76
+ });
77
+
78
+ return new NextResponse(stream, {
79
+ headers: {
80
+ 'Content-Type': 'text/event-stream',
81
+ 'Cache-Control': 'no-cache',
82
+ 'Connection': 'keep-alive',
83
+ },
84
+ });
85
+ }
86
+
87
+ export async function POST(request: NextRequest) {
88
+ try {
89
+ const body = await request.json();
90
+
91
+ const { type = 'info', title, message, targetUserId } = body;
92
+
93
+ if (!title) {
94
+ return NextResponse.json(
95
+ { error: 'Title is required' },
96
+ { status: 400 }
97
+ );
98
+ }
99
+
100
+ const notification = {
101
+ id: crypto.randomUUID(),
102
+ type,
103
+ title,
104
+ message: message || null,
105
+ targetUserId: targetUserId || null,
106
+ createdAt: new Date().toISOString(),
107
+ };
108
+
109
+ // Broadcast to connected clients
110
+ broadcastNotification(notification);
111
+
112
+ return NextResponse.json({
113
+ message: 'Notification sent',
114
+ notification,
115
+ connectedClients: clients.size,
116
+ });
117
+ } catch (error: unknown) {
118
+ const msg = error instanceof Error ? error.message : 'Failed to send notification';
119
+ return NextResponse.json({ error: msg }, { status: 500 });
120
+ }
121
+ }
@@ -0,0 +1,154 @@
1
+ 'use client';
2
+
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { useNotifications } from './NotificationProvider';
5
+
6
+ interface NotificationBellProps {
7
+ maxVisible?: number;
8
+ }
9
+
10
+ function formatRelativeTime(date: Date): string {
11
+ const now = Date.now();
12
+ const diffMs = now - date.getTime();
13
+ const diffSec = Math.floor(diffMs / 1000);
14
+ const diffMin = Math.floor(diffSec / 60);
15
+ const diffHour = Math.floor(diffMin / 60);
16
+ const diffDay = Math.floor(diffHour / 24);
17
+
18
+ if (diffSec < 60) return 'just now';
19
+ if (diffMin < 60) return `${diffMin}m ago`;
20
+ if (diffHour < 24) return `${diffHour}h ago`;
21
+ if (diffDay < 7) return `${diffDay}d ago`;
22
+ return date.toLocaleDateString();
23
+ }
24
+
25
+ const typeColors: Record<string, string> = {
26
+ success: 'bg-emerald-400',
27
+ error: 'bg-red-400',
28
+ warning: 'bg-amber-400',
29
+ info: 'bg-cyan-400',
30
+ };
31
+
32
+ export default function NotificationBell({ maxVisible = 10 }: NotificationBellProps) {
33
+ const { notifications, unreadCount, markAsRead, markAllAsRead, removeNotification } =
34
+ useNotifications();
35
+ const [open, setOpen] = useState(false);
36
+ const ref = useRef<HTMLDivElement>(null);
37
+
38
+ useEffect(() => {
39
+ function handleClickOutside(e: MouseEvent) {
40
+ if (ref.current && !ref.current.contains(e.target as Node)) {
41
+ setOpen(false);
42
+ }
43
+ }
44
+ document.addEventListener('mousedown', handleClickOutside);
45
+ return () => document.removeEventListener('mousedown', handleClickOutside);
46
+ }, []);
47
+
48
+ const visibleNotifications = notifications.slice(0, maxVisible);
49
+
50
+ return (
51
+ <div className="relative" ref={ref}>
52
+ {/* Bell button */}
53
+ <button
54
+ onClick={() => setOpen(!open)}
55
+ className="relative p-2 text-white/60 hover:text-white transition-colors rounded-lg hover:bg-white/5"
56
+ >
57
+ <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
58
+ <path
59
+ strokeLinecap="round"
60
+ strokeLinejoin="round"
61
+ d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
62
+ />
63
+ </svg>
64
+
65
+ {/* Badge */}
66
+ {unreadCount > 0 && (
67
+ <span className="absolute -top-0.5 -right-0.5 flex items-center justify-center min-w-[18px] h-[18px] px-1 bg-cyan-500 text-white text-[10px] font-bold rounded-full shadow-lg shadow-cyan-500/30">
68
+ {unreadCount > 99 ? '99+' : unreadCount}
69
+ </span>
70
+ )}
71
+ </button>
72
+
73
+ {/* Dropdown */}
74
+ {open && (
75
+ <div className="absolute right-0 top-full mt-2 w-80 backdrop-blur-xl bg-gray-900/95 border border-white/10 rounded-xl shadow-2xl z-50 overflow-hidden">
76
+ {/* Header */}
77
+ <div className="flex items-center justify-between px-4 py-3 border-b border-white/5">
78
+ <h3 className="text-sm font-semibold text-white">Notifications</h3>
79
+ {unreadCount > 0 && (
80
+ <button
81
+ onClick={markAllAsRead}
82
+ className="text-xs text-cyan-400 hover:text-cyan-300 transition-colors"
83
+ >
84
+ Mark all read
85
+ </button>
86
+ )}
87
+ </div>
88
+
89
+ {/* List */}
90
+ <div className="max-h-96 overflow-y-auto">
91
+ {visibleNotifications.length === 0 ? (
92
+ <div className="px-4 py-8 text-center">
93
+ <svg className="w-8 h-8 mx-auto text-white/20 mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
94
+ <path strokeLinecap="round" strokeLinejoin="round" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
95
+ </svg>
96
+ <p className="text-sm text-white/30">No notifications</p>
97
+ </div>
98
+ ) : (
99
+ visibleNotifications.map((notification) => (
100
+ <div
101
+ key={notification.id}
102
+ onClick={() => markAsRead(notification.id)}
103
+ className={`flex items-start gap-3 px-4 py-3 hover:bg-white/5 cursor-pointer transition-colors border-b border-white/5 last:border-0 ${
104
+ !notification.read ? 'bg-white/[0.02]' : ''
105
+ }`}
106
+ >
107
+ {/* Type indicator */}
108
+ <div className={`w-2 h-2 rounded-full mt-1.5 flex-shrink-0 ${typeColors[notification.type] || 'bg-white/30'}`} />
109
+
110
+ {/* Content */}
111
+ <div className="flex-1 min-w-0">
112
+ <p className={`text-sm ${!notification.read ? 'text-white font-medium' : 'text-white/70'}`}>
113
+ {notification.title}
114
+ </p>
115
+ {notification.message && (
116
+ <p className="text-xs text-white/40 mt-0.5 truncate">
117
+ {notification.message}
118
+ </p>
119
+ )}
120
+ <p className="text-[11px] text-white/20 mt-1">
121
+ {formatRelativeTime(notification.createdAt)}
122
+ </p>
123
+ </div>
124
+
125
+ {/* Remove */}
126
+ <button
127
+ onClick={(e) => {
128
+ e.stopPropagation();
129
+ removeNotification(notification.id);
130
+ }}
131
+ className="flex-shrink-0 p-0.5 text-white/20 hover:text-white/50 opacity-0 group-hover:opacity-100 transition-all"
132
+ >
133
+ <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
134
+ <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
135
+ </svg>
136
+ </button>
137
+ </div>
138
+ ))
139
+ )}
140
+ </div>
141
+
142
+ {/* Footer */}
143
+ {notifications.length > maxVisible && (
144
+ <div className="px-4 py-2 border-t border-white/5 text-center">
145
+ <span className="text-xs text-white/30">
146
+ +{notifications.length - maxVisible} more notifications
147
+ </span>
148
+ </div>
149
+ )}
150
+ </div>
151
+ )}
152
+ </div>
153
+ );
154
+ }
@@ -0,0 +1,161 @@
1
+ 'use client';
2
+
3
+ import {
4
+ createContext,
5
+ useContext,
6
+ useState,
7
+ useCallback,
8
+ type ReactNode,
9
+ } from 'react';
10
+ import Toast, { type ToastData, type ToastType } from './Toast';
11
+
12
+ export interface Notification {
13
+ id: string;
14
+ type: ToastType;
15
+ title: string;
16
+ message?: string;
17
+ read: boolean;
18
+ createdAt: Date;
19
+ }
20
+
21
+ interface NotificationContextValue {
22
+ /** Persistent notifications (for bell icon / notification panel) */
23
+ notifications: Notification[];
24
+ unreadCount: number;
25
+ addNotification: (notification: Omit<Notification, 'id' | 'read' | 'createdAt'>) => void;
26
+ markAsRead: (id: string) => void;
27
+ markAllAsRead: () => void;
28
+ removeNotification: (id: string) => void;
29
+ clearAll: () => void;
30
+
31
+ /** Toast helpers */
32
+ toast: {
33
+ success: (title: string, message?: string) => void;
34
+ error: (title: string, message?: string) => void;
35
+ warning: (title: string, message?: string) => void;
36
+ info: (title: string, message?: string) => void;
37
+ custom: (data: Omit<ToastData, 'id'>) => void;
38
+ };
39
+ }
40
+
41
+ const NotificationContext = createContext<NotificationContextValue | null>(null);
42
+
43
+ export function useNotifications(): NotificationContextValue {
44
+ const ctx = useContext(NotificationContext);
45
+ if (!ctx) {
46
+ throw new Error('useNotifications must be used within a NotificationProvider');
47
+ }
48
+ return ctx;
49
+ }
50
+
51
+ interface NotificationProviderProps {
52
+ children: ReactNode;
53
+ maxToasts?: number;
54
+ position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
55
+ }
56
+
57
+ export default function NotificationProvider({
58
+ children,
59
+ maxToasts = 5,
60
+ position = 'top-right',
61
+ }: NotificationProviderProps) {
62
+ const [notifications, setNotifications] = useState<Notification[]>([]);
63
+ const [toasts, setToasts] = useState<ToastData[]>([]);
64
+
65
+ // --- Notifications ---
66
+
67
+ const addNotification = useCallback(
68
+ (data: Omit<Notification, 'id' | 'read' | 'createdAt'>) => {
69
+ const notification: Notification = {
70
+ ...data,
71
+ id: crypto.randomUUID(),
72
+ read: false,
73
+ createdAt: new Date(),
74
+ };
75
+ setNotifications((prev) => [notification, ...prev]);
76
+ },
77
+ []
78
+ );
79
+
80
+ const markAsRead = useCallback((id: string) => {
81
+ setNotifications((prev) =>
82
+ prev.map((n) => (n.id === id ? { ...n, read: true } : n))
83
+ );
84
+ }, []);
85
+
86
+ const markAllAsRead = useCallback(() => {
87
+ setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
88
+ }, []);
89
+
90
+ const removeNotification = useCallback((id: string) => {
91
+ setNotifications((prev) => prev.filter((n) => n.id !== id));
92
+ }, []);
93
+
94
+ const clearAll = useCallback(() => {
95
+ setNotifications([]);
96
+ }, []);
97
+
98
+ // --- Toasts ---
99
+
100
+ const showToast = useCallback(
101
+ (data: Omit<ToastData, 'id'>) => {
102
+ const id = crypto.randomUUID();
103
+ setToasts((prev) => {
104
+ const next = [...prev, { ...data, id }];
105
+ return next.slice(-maxToasts);
106
+ });
107
+ },
108
+ [maxToasts]
109
+ );
110
+
111
+ const dismissToast = useCallback((id: string) => {
112
+ setToasts((prev) => prev.filter((t) => t.id !== id));
113
+ }, []);
114
+
115
+ const toast = {
116
+ success: (title: string, message?: string) =>
117
+ showToast({ type: 'success', title, message }),
118
+ error: (title: string, message?: string) =>
119
+ showToast({ type: 'error', title, message }),
120
+ warning: (title: string, message?: string) =>
121
+ showToast({ type: 'warning', title, message }),
122
+ info: (title: string, message?: string) =>
123
+ showToast({ type: 'info', title, message }),
124
+ custom: (data: Omit<ToastData, 'id'>) => showToast(data),
125
+ };
126
+
127
+ const unreadCount = notifications.filter((n) => !n.read).length;
128
+
129
+ const positionClasses: Record<string, string> = {
130
+ 'top-right': 'top-4 right-4',
131
+ 'top-left': 'top-4 left-4',
132
+ 'bottom-right': 'bottom-4 right-4',
133
+ 'bottom-left': 'bottom-4 left-4',
134
+ };
135
+
136
+ return (
137
+ <NotificationContext.Provider
138
+ value={{
139
+ notifications,
140
+ unreadCount,
141
+ addNotification,
142
+ markAsRead,
143
+ markAllAsRead,
144
+ removeNotification,
145
+ clearAll,
146
+ toast,
147
+ }}
148
+ >
149
+ {children}
150
+
151
+ {/* Toast container */}
152
+ <div className={`fixed ${positionClasses[position]} z-50 flex flex-col gap-2 pointer-events-none`}>
153
+ {toasts.map((t) => (
154
+ <div key={t.id} className="pointer-events-auto">
155
+ <Toast toast={t} onDismiss={dismissToast} />
156
+ </div>
157
+ ))}
158
+ </div>
159
+ </NotificationContext.Provider>
160
+ );
161
+ }
@@ -0,0 +1,112 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+
5
+ export type ToastType = 'success' | 'error' | 'info' | 'warning';
6
+
7
+ export interface ToastData {
8
+ id: string;
9
+ type: ToastType;
10
+ title: string;
11
+ message?: string;
12
+ duration?: number;
13
+ }
14
+
15
+ interface ToastProps {
16
+ toast: ToastData;
17
+ onDismiss: (id: string) => void;
18
+ }
19
+
20
+ const typeStyles: Record<ToastType, { bg: string; border: string; icon: string; iconColor: string }> = {
21
+ success: {
22
+ bg: 'bg-emerald-500/10',
23
+ border: 'border-emerald-500/20',
24
+ icon: 'M5 13l4 4L19 7',
25
+ iconColor: 'text-emerald-400',
26
+ },
27
+ error: {
28
+ bg: 'bg-red-500/10',
29
+ border: 'border-red-500/20',
30
+ icon: 'M6 18L18 6M6 6l12 12',
31
+ iconColor: 'text-red-400',
32
+ },
33
+ warning: {
34
+ bg: 'bg-amber-500/10',
35
+ border: 'border-amber-500/20',
36
+ icon: 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.34 16.5c-.77.833.192 2.5 1.732 2.5z',
37
+ iconColor: 'text-amber-400',
38
+ },
39
+ info: {
40
+ bg: 'bg-cyan-500/10',
41
+ border: 'border-cyan-500/20',
42
+ icon: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z',
43
+ iconColor: 'text-cyan-400',
44
+ },
45
+ };
46
+
47
+ export default function Toast({ toast, onDismiss }: ToastProps) {
48
+ const [isVisible, setIsVisible] = useState(false);
49
+ const [isLeaving, setIsLeaving] = useState(false);
50
+ const style = typeStyles[toast.type];
51
+ const duration = toast.duration ?? 5000;
52
+
53
+ useEffect(() => {
54
+ // Enter animation
55
+ const showTimer = setTimeout(() => setIsVisible(true), 10);
56
+
57
+ // Auto-dismiss
58
+ let dismissTimer: ReturnType<typeof setTimeout> | undefined;
59
+ if (duration > 0) {
60
+ dismissTimer = setTimeout(() => {
61
+ handleDismiss();
62
+ }, duration);
63
+ }
64
+
65
+ return () => {
66
+ clearTimeout(showTimer);
67
+ if (dismissTimer) clearTimeout(dismissTimer);
68
+ };
69
+ }, [duration]);
70
+
71
+ const handleDismiss = () => {
72
+ setIsLeaving(true);
73
+ setTimeout(() => onDismiss(toast.id), 300);
74
+ };
75
+
76
+ return (
77
+ <div
78
+ className={`
79
+ max-w-sm w-full backdrop-blur-xl ${style.bg} border ${style.border} rounded-xl p-4 shadow-2xl
80
+ transform transition-all duration-300 ease-out
81
+ ${isVisible && !isLeaving ? 'translate-x-0 opacity-100' : 'translate-x-full opacity-0'}
82
+ `}
83
+ >
84
+ <div className="flex items-start gap-3">
85
+ {/* Icon */}
86
+ <div className="flex-shrink-0 mt-0.5">
87
+ <svg className={`w-5 h-5 ${style.iconColor}`} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
88
+ <path strokeLinecap="round" strokeLinejoin="round" d={style.icon} />
89
+ </svg>
90
+ </div>
91
+
92
+ {/* Content */}
93
+ <div className="flex-1 min-w-0">
94
+ <p className="text-sm font-medium text-white">{toast.title}</p>
95
+ {toast.message && (
96
+ <p className="text-xs text-white/50 mt-0.5">{toast.message}</p>
97
+ )}
98
+ </div>
99
+
100
+ {/* Close */}
101
+ <button
102
+ onClick={handleDismiss}
103
+ className="flex-shrink-0 p-0.5 text-white/30 hover:text-white/60 transition-colors"
104
+ >
105
+ <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
106
+ <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
107
+ </svg>
108
+ </button>
109
+ </div>
110
+ </div>
111
+ );
112
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "notification-system",
3
+ "version": "1.0.0",
4
+ "description": "Complete notification system with toast messages, React context provider, SSE API route, and bell icon badge",
5
+ "author": "AD AI Engine",
6
+ "category": "notifications",
7
+ "dependencies": [],
8
+ "files": {
9
+ "components": [
10
+ "components/notifications/Toast.tsx",
11
+ "components/notifications/NotificationProvider.tsx",
12
+ "components/notifications/NotificationBell.tsx"
13
+ ],
14
+ "api": [
15
+ "app/api/notifications/route.ts"
16
+ ]
17
+ },
18
+ "schema": null,
19
+ "instructions": "1. Wrap your app with NotificationProvider\n2. Use the useNotifications() hook to show toasts: toast.success('Done!')\n3. Place NotificationBell in your header for the bell icon with badge count\n4. The SSE API route streams real-time notifications to connected clients\n5. Call addNotification() from the provider to push persistent notifications"
20
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "helix-lang",
3
+ "version": "11.0.0",
4
+ "description": "Helix - AI-Native Development Platform with Full-Stack Generation, Preview & Deploy",
5
+ "main": "dist/index.js",
6
+ "files": [
7
+ "dist/",
8
+ "library/",
9
+ "package.json",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "bin": {
14
+ "helix": "./dist/bin/helix.js"
15
+ },
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "start": "node dist/bin/helix.js",
19
+ "dev": "npx ts-node src/bin/helix.ts",
20
+ "helix": "npx ts-node src/bin/helix.ts",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "helix",
25
+ "ai",
26
+ "code-generation",
27
+ "cli",
28
+ "react",
29
+ "nextjs",
30
+ "flutter",
31
+ "prisma",
32
+ "full-stack",
33
+ "deploy",
34
+ "preview"
35
+ ],
36
+ "author": "Ayman Dwidar <ayman.dwidar@gmail.com>",
37
+ "license": "MIT",
38
+ "homepage": "https://github.com/aymandwidar/helix",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/aymandwidar/helix.git"
42
+ },
43
+ "engines": {
44
+ "node": ">=18"
45
+ },
46
+ "dependencies": {
47
+ "@anthropic-ai/sdk": "^0.39.0",
48
+ "@types/pg": "^8.16.0",
49
+ "chalk": "^4.1.2",
50
+ "commander": "^12.1.0",
51
+ "dotenv": "^16.4.7",
52
+ "execa": "^5.1.1",
53
+ "fs-extra": "^11.2.0",
54
+ "glob": "^13.0.0",
55
+ "ora": "^5.4.1",
56
+ "pg": "^8.17.2",
57
+ "ws": "^8.19.0"
58
+ },
59
+ "devDependencies": {
60
+ "@types/fs-extra": "^11.0.4",
61
+ "@types/node": "^22.10.7",
62
+ "@types/ws": "^8.18.1",
63
+ "ts-node": "^10.9.2",
64
+ "typescript": "^5.7.3"
65
+ }
66
+ }