@bonginkan/maria 4.2.20 → 4.2.22

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.
@@ -0,0 +1,348 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var express = require('express');
5
+ var cors = require('cors');
6
+ var helmet = require('helmet');
7
+ var compression = require('compression');
8
+ var auth = require('firebase-admin/auth');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ var express__default = /*#__PURE__*/_interopDefault(express);
13
+ var cors__default = /*#__PURE__*/_interopDefault(cors);
14
+ var helmet__default = /*#__PURE__*/_interopDefault(helmet);
15
+ var compression__default = /*#__PURE__*/_interopDefault(compression);
16
+
17
+ var rateLimitStore = /* @__PURE__ */ new Map();
18
+ var RATE_LIMITS = {
19
+ "/image:FREE": { windowMs: 3e3, requests: 1 },
20
+ // 1 req per 3s
21
+ "/video:FREE": { windowMs: 15e3, requests: 1 },
22
+ // 1 req per 15s
23
+ "/code:FREE": { windowMs: 1e3, requests: 1 },
24
+ // 1 req per 1s
25
+ "/chat:FREE": { windowMs: 500, requests: 1 },
26
+ // 2 req per sec
27
+ "/image:STARTER": { windowMs: 1e3, requests: 1 },
28
+ // 1 req per 1s
29
+ "/video:STARTER": { windowMs: 5e3, requests: 1 },
30
+ // 1 req per 5s
31
+ "/code:STARTER": { windowMs: 500, requests: 1 },
32
+ // 2 req per sec
33
+ "/image:PRO": { windowMs: 100, requests: 1 },
34
+ // 10 req per sec
35
+ "/video:PRO": { windowMs: 1e3, requests: 1 },
36
+ // 1 req per sec
37
+ "/code:PRO": { windowMs: 100, requests: 1 },
38
+ // 10 req per sec
39
+ "default": { windowMs: 1e3, requests: 1 }
40
+ // Fallback
41
+ };
42
+ function getRateLimitConfig(endpoint, plan) {
43
+ const key = `${endpoint}:${plan.toUpperCase()}`;
44
+ return RATE_LIMITS[key] || RATE_LIMITS.default;
45
+ }
46
+ function getEndpointCategory(path) {
47
+ if (path.includes("/image")) return "/image";
48
+ if (path.includes("/video")) return "/video";
49
+ if (path.includes("/code")) return "/code";
50
+ if (path.includes("/chat")) return "/chat";
51
+ return "default";
52
+ }
53
+ async function rateLimitMiddleware(req, res, next) {
54
+ try {
55
+ const authHeader = req.headers.authorization;
56
+ const bearer = authHeader?.split(" ")[1];
57
+ let userId = "anonymous";
58
+ let userPlan = "FREE";
59
+ if (bearer) {
60
+ try {
61
+ const decodedToken = await auth.getAuth().verifyIdToken(bearer);
62
+ userId = decodedToken.uid;
63
+ userPlan = req.user?.plan || "FREE";
64
+ } catch {
65
+ }
66
+ } else if (req.headers["x-api-key"]) {
67
+ userId = `apikey:${req.headers["x-api-key"]}`;
68
+ }
69
+ const endpoint = getEndpointCategory(req.path);
70
+ const config = getRateLimitConfig(endpoint, userPlan);
71
+ const rateLimitKey = `${userId}:${endpoint}`;
72
+ const now = Date.now();
73
+ const userRecord = rateLimitStore.get(rateLimitKey);
74
+ if (!userRecord || typeof userRecord.lastAt !== "number") {
75
+ rateLimitStore.set(rateLimitKey, { lastAt: now });
76
+ return next();
77
+ }
78
+ const elapsedMs = now - userRecord.lastAt;
79
+ const remainingMs = Math.max(0, config.windowMs - elapsedMs);
80
+ if (remainingMs > 0) {
81
+ const retryAfterSeconds = Math.max(1, Math.ceil(remainingMs / 1e3));
82
+ const resetAt = new Date(now + remainingMs);
83
+ return res.status(429).json({
84
+ error: "rate_limit_exceeded",
85
+ message: `Rate limit exceeded for ${endpoint} endpoint`,
86
+ details: {
87
+ endpoint,
88
+ plan: userPlan,
89
+ limit: `${config.requests} request per ${config.windowMs / 1e3} seconds`,
90
+ retryAfterSeconds,
91
+ resetAt: resetAt.toISOString()
92
+ },
93
+ hint: userPlan === "FREE" ? `Free plan limit: ${config.requests} request per ${config.windowMs / 1e3}s. Upgrade at https://maria.ai/upgrade` : `Please wait ${retryAfterSeconds} seconds before retrying.`
94
+ });
95
+ }
96
+ rateLimitStore.set(rateLimitKey, { lastAt: now });
97
+ return next();
98
+ } catch (error) {
99
+ console.error("[RateLimit] Error in middleware:", error);
100
+ return next();
101
+ }
102
+ }
103
+ function startRateLimitCleanup() {
104
+ setInterval(() => {
105
+ const now = Date.now();
106
+ const maxAge = 60 * 60 * 1e3;
107
+ rateLimitStore.forEach((value, key) => {
108
+ if (now - value.lastAt > maxAge) {
109
+ rateLimitStore.delete(key);
110
+ }
111
+ });
112
+ }, 10 * 60 * 1e3);
113
+ }
114
+
115
+ // src/server/express-server.ts
116
+ var app = express__default.default();
117
+ var port = process.env.PORT || 8080;
118
+ app.use(helmet__default.default());
119
+ app.use(cors__default.default());
120
+ app.use(compression__default.default());
121
+ app.use(express__default.default.json({ limit: "10mb" }));
122
+ app.use(express__default.default.urlencoded({ extended: true }));
123
+ app.use((req, res, next) => {
124
+ console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] ${req.method} ${req.path}`);
125
+ next();
126
+ });
127
+ app.get("/health", (req, res) => {
128
+ res.status(200).send("OK");
129
+ });
130
+ app.get("/api/status", (req, res) => {
131
+ res.json({
132
+ status: "healthy",
133
+ version: "4.2.22",
134
+ uptime: process.uptime(),
135
+ memory: process.memoryUsage(),
136
+ platform: process.platform,
137
+ node: process.version,
138
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
139
+ });
140
+ });
141
+ app.get("/", (req, res) => {
142
+ res.json({
143
+ name: "MARIA CODE API",
144
+ version: "4.2.22",
145
+ status: "running",
146
+ environment: process.env.NODE_ENV || "development",
147
+ endpoints: {
148
+ health: "/health",
149
+ status: "/api/status",
150
+ image: "/api/v1/image",
151
+ video: "/api/v1/video",
152
+ code: "/api/v1/code",
153
+ chat: "/api/v1/chat"
154
+ },
155
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
156
+ });
157
+ });
158
+ app.get("/api/user/profile", async (req, res) => {
159
+ try {
160
+ const authHeader = req.headers.authorization || "";
161
+ if (!authHeader.startsWith("Bearer ")) {
162
+ return res.status(401).json({ error: "unauthorized" });
163
+ }
164
+ const userAgent = req.headers["user-agent"] || "";
165
+ const plan = "FREE";
166
+ const response = {
167
+ id: "server-user-" + Date.now(),
168
+ email: "user@api.maria-code.ai",
169
+ name: "API User",
170
+ plan,
171
+ usage: {
172
+ requests: 0,
173
+ requestLimit: 1e3,
174
+ tokens: 0,
175
+ tokenLimit: 5e5,
176
+ resetDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3).toISOString()
177
+ },
178
+ models: ["gpt-5", "gemini-2.5-pro"]
179
+ };
180
+ return res.status(200).json(response);
181
+ } catch (error) {
182
+ console.error("[User Profile] Error:", error);
183
+ return res.status(500).json({ error: "PROFILE_FETCH_FAILED" });
184
+ }
185
+ });
186
+ app.post("/api/auth/revoke", async (req, res) => {
187
+ try {
188
+ const authHeader = req.headers.authorization || "";
189
+ if (!authHeader.startsWith("Bearer ")) {
190
+ return res.status(401).json({ error: "unauthorized" });
191
+ }
192
+ const { refresh_token, all_devices } = req.body || {};
193
+ return res.status(200).json({ success: true, allDevices: Boolean(all_devices) });
194
+ } catch (error) {
195
+ console.error("[Auth Revoke] Error:", error);
196
+ return res.status(500).json({ error: "REVOCATION_FAILED" });
197
+ }
198
+ });
199
+ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
200
+ try {
201
+ const { prompt, model = "dall-e-3", size = "1024x1024" } = req.body;
202
+ if (!prompt) {
203
+ return res.status(400).json({
204
+ error: "bad_request",
205
+ message: "Prompt is required"
206
+ });
207
+ }
208
+ return res.json({
209
+ success: true,
210
+ data: {
211
+ url: `https://placeholder.com/generated-image-${Date.now()}.png`,
212
+ prompt,
213
+ model,
214
+ size,
215
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
216
+ }
217
+ });
218
+ } catch (error) {
219
+ console.error("[Image API] Error:", error);
220
+ return res.status(500).json({
221
+ error: "internal_error",
222
+ message: "Failed to generate image"
223
+ });
224
+ }
225
+ });
226
+ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
227
+ try {
228
+ const { prompt, duration = 5, model = "runway-gen2" } = req.body;
229
+ if (!prompt) {
230
+ return res.status(400).json({
231
+ error: "bad_request",
232
+ message: "Prompt is required"
233
+ });
234
+ }
235
+ return res.json({
236
+ success: true,
237
+ data: {
238
+ url: `https://placeholder.com/generated-video-${Date.now()}.mp4`,
239
+ prompt,
240
+ duration,
241
+ model,
242
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
243
+ }
244
+ });
245
+ } catch (error) {
246
+ console.error("[Video API] Error:", error);
247
+ return res.status(500).json({
248
+ error: "internal_error",
249
+ message: "Failed to generate video"
250
+ });
251
+ }
252
+ });
253
+ app.post("/api/v1/code", rateLimitMiddleware, async (req, res) => {
254
+ try {
255
+ const { prompt, language = "typescript", model = "gpt-4" } = req.body;
256
+ if (!prompt) {
257
+ return res.status(400).json({
258
+ error: "bad_request",
259
+ message: "Prompt is required"
260
+ });
261
+ }
262
+ return res.json({
263
+ success: true,
264
+ data: {
265
+ code: `// Generated code for: ${prompt}
266
+ function example() {
267
+ return "Generated by MARIA CODE";
268
+ }`,
269
+ language,
270
+ model,
271
+ prompt,
272
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
273
+ }
274
+ });
275
+ } catch (error) {
276
+ console.error("[Code API] Error:", error);
277
+ return res.status(500).json({
278
+ error: "internal_error",
279
+ message: "Failed to generate code"
280
+ });
281
+ }
282
+ });
283
+ app.post("/api/v1/chat", rateLimitMiddleware, async (req, res) => {
284
+ try {
285
+ const { message, model = "gpt-4" } = req.body;
286
+ if (!message) {
287
+ return res.status(400).json({
288
+ error: "bad_request",
289
+ message: "Message is required"
290
+ });
291
+ }
292
+ return res.json({
293
+ success: true,
294
+ data: {
295
+ response: `Echo: ${message}`,
296
+ model,
297
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
298
+ }
299
+ });
300
+ } catch (error) {
301
+ console.error("[Chat API] Error:", error);
302
+ return res.status(500).json({
303
+ error: "internal_error",
304
+ message: "Failed to process chat"
305
+ });
306
+ }
307
+ });
308
+ app.use((req, res) => {
309
+ res.status(404).json({
310
+ error: "not_found",
311
+ message: "The requested endpoint does not exist",
312
+ path: req.path
313
+ });
314
+ });
315
+ app.use((err, req, res, next) => {
316
+ console.error("[Server Error]:", err);
317
+ res.status(500).json({
318
+ error: "internal_server_error",
319
+ message: "An unexpected error occurred"
320
+ });
321
+ });
322
+ var server = app.listen(port, () => {
323
+ console.log(`\u{1F680} MARIA CODE Express Server running on port ${port}`);
324
+ console.log(`\u{1F4CD} Health check: http://localhost:${port}/health`);
325
+ console.log(`\u{1F4CD} API Status: http://localhost:${port}/api/status`);
326
+ console.log(`\u{1F4CD} API Endpoints: http://localhost:${port}/`);
327
+ startRateLimitCleanup();
328
+ console.log("\u{1F527} Rate limit cleanup job started");
329
+ });
330
+ process.on("SIGTERM", () => {
331
+ console.log("SIGTERM signal received: closing HTTP server");
332
+ server.close(() => {
333
+ console.log("HTTP server closed");
334
+ process.exit(0);
335
+ });
336
+ });
337
+ process.on("SIGINT", () => {
338
+ console.log("SIGINT signal received: closing HTTP server");
339
+ server.close(() => {
340
+ console.log("HTTP server closed");
341
+ process.exit(0);
342
+ });
343
+ });
344
+
345
+ exports.app = app;
346
+ exports.server = server;
347
+ //# sourceMappingURL=express-server.cjs.map
348
+ //# sourceMappingURL=express-server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/middleware/rate-limit.ts","../../src/server/express-server.ts"],"names":["getAuth","express","helmet","cors","compression"],"mappings":"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","file":"express-server.cjs","sourcesContent":["/**\n * Production-ready Rate Limit Middleware\n * Fixes: First-call false positive, Infinity/Invalid Date errors\n */\n\nimport type { Request, Response, NextFunction } from 'express';\nimport { getAuth } from 'firebase-admin/auth';\n\n// In-memory store (TODO: Replace with Redis for multi-instance)\nconst rateLimitStore = new Map<string, { lastAt: number }>();\n\n// Rate limit configurations per endpoint and plan\ninterface RateLimitConfig {\n windowMs: number;\n requests: number;\n}\n\nconst RATE_LIMITS: Record<string, RateLimitConfig> = {\n '/image:FREE': { windowMs: 3000, requests: 1 }, // 1 req per 3s\n '/video:FREE': { windowMs: 15000, requests: 1 }, // 1 req per 15s\n '/code:FREE': { windowMs: 1000, requests: 1 }, // 1 req per 1s\n '/chat:FREE': { windowMs: 500, requests: 1 }, // 2 req per sec\n \n '/image:STARTER': { windowMs: 1000, requests: 1 }, // 1 req per 1s\n '/video:STARTER': { windowMs: 5000, requests: 1 }, // 1 req per 5s\n '/code:STARTER': { windowMs: 500, requests: 1 }, // 2 req per sec\n \n '/image:PRO': { windowMs: 100, requests: 1 }, // 10 req per sec\n '/video:PRO': { windowMs: 1000, requests: 1 }, // 1 req per sec\n '/code:PRO': { windowMs: 100, requests: 1 }, // 10 req per sec\n \n 'default': { windowMs: 1000, requests: 1 } // Fallback\n};\n\n/**\n * Get rate limit config for specific endpoint and plan\n */\nfunction getRateLimitConfig(endpoint: string, plan: string): RateLimitConfig {\n const key = `${endpoint}:${plan.toUpperCase()}`;\n return RATE_LIMITS[key] || RATE_LIMITS.default;\n}\n\n/**\n * Extract endpoint category from request path\n */\nfunction getEndpointCategory(path: string): string {\n if (path.includes('/image')) return '/image';\n if (path.includes('/video')) return '/video';\n if (path.includes('/code')) return '/code';\n if (path.includes('/chat')) return '/chat';\n return 'default';\n}\n\n/**\n * Main rate limit middleware\n */\nexport async function rateLimitMiddleware(\n req: Request,\n res: Response,\n next: NextFunction\n): Promise<void> {\n try {\n // 1. Identify user (from JWT or API key)\n const authHeader = req.headers.authorization;\n const bearer = authHeader?.split(' ')[1];\n \n let userId = 'anonymous';\n let userPlan = 'FREE';\n \n if (bearer) {\n try {\n const decodedToken = await getAuth().verifyIdToken(bearer);\n userId = decodedToken.uid;\n // TODO: Fetch actual plan from Firestore\n userPlan = (req as any).user?.plan || 'FREE';\n } catch {\n // Invalid token, treat as anonymous\n }\n } else if (req.headers['x-api-key']) {\n userId = `apikey:${req.headers['x-api-key']}`;\n // TODO: Resolve plan from API key\n }\n \n // 2. Determine endpoint category\n const endpoint = getEndpointCategory(req.path);\n \n // 3. Get rate limit config\n const config = getRateLimitConfig(endpoint, userPlan);\n \n // 4. Build unique key for this user-endpoint combination\n const rateLimitKey = `${userId}:${endpoint}`;\n \n // 5. Check rate limit\n const now = Date.now();\n const userRecord = rateLimitStore.get(rateLimitKey);\n \n // First request - always allow\n if (!userRecord || typeof userRecord.lastAt !== 'number') {\n rateLimitStore.set(rateLimitKey, { lastAt: now });\n return next();\n }\n \n // Calculate time elapsed since last request\n const elapsedMs = now - userRecord.lastAt;\n const remainingMs = Math.max(0, config.windowMs - elapsedMs);\n \n // If window hasn't passed, reject\n if (remainingMs > 0) {\n // Ensure clean, bounded values for response\n const retryAfterSeconds = Math.max(1, Math.ceil(remainingMs / 1000));\n const resetAt = new Date(now + remainingMs);\n \n return res.status(429).json({\n error: 'rate_limit_exceeded',\n message: `Rate limit exceeded for ${endpoint} endpoint`,\n details: {\n endpoint,\n plan: userPlan,\n limit: `${config.requests} request per ${config.windowMs / 1000} seconds`,\n retryAfterSeconds,\n resetAt: resetAt.toISOString()\n },\n hint: userPlan === 'FREE' \n ? `Free plan limit: ${config.requests} request per ${config.windowMs / 1000}s. Upgrade at https://maria.ai/upgrade`\n : `Please wait ${retryAfterSeconds} seconds before retrying.`\n });\n }\n \n // Window has passed - allow and update timestamp\n rateLimitStore.set(rateLimitKey, { lastAt: now });\n return next();\n \n } catch (error) {\n // Fail open - don't block users on rate limiter errors\n console.error('[RateLimit] Error in middleware:', error);\n return next();\n }\n}\n\n/**\n * Clear rate limit for specific user (e.g., after upgrade)\n */\nexport function clearUserRateLimit(userId: string): void {\n const keysToDelete: string[] = [];\n \n rateLimitStore.forEach((_, key) => {\n if (key.startsWith(`${userId}:`)) {\n keysToDelete.push(key);\n }\n });\n \n keysToDelete.forEach(key => rateLimitStore.delete(key));\n}\n\n/**\n * Periodic cleanup of old entries (prevent memory leak)\n */\nexport function startRateLimitCleanup(): void {\n setInterval(() => {\n const now = Date.now();\n const maxAge = 60 * 60 * 1000; // 1 hour\n \n rateLimitStore.forEach((value, key) => {\n if (now - value.lastAt > maxAge) {\n rateLimitStore.delete(key);\n }\n });\n }, 10 * 60 * 1000); // Run every 10 minutes\n}","/**\n * Express Server for MARIA CODE API\n * With Rate Limiting and API Endpoints\n */\n\nimport express, { Request, Response, NextFunction } from 'express';\nimport cors from 'cors';\nimport helmet from 'helmet';\nimport compression from 'compression';\nimport { rateLimitMiddleware, startRateLimitCleanup } from '../middleware/rate-limit';\n\nconst app = express();\nconst port = process.env.PORT || 8080;\n\n// Security middleware\napp.use(helmet());\napp.use(cors());\napp.use(compression());\napp.use(express.json({ limit: '10mb' }));\napp.use(express.urlencoded({ extended: true }));\n\n// Request logging\napp.use((req: Request, res: Response, next: NextFunction) => {\n console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);\n next();\n});\n\n// Health check (no rate limit)\napp.get('/health', (req: Request, res: Response) => {\n res.status(200).send('OK');\n});\n\napp.get('/api/status', (req: Request, res: Response) => {\n res.json({\n status: 'healthy',\n version: '4.2.22',\n uptime: process.uptime(),\n memory: process.memoryUsage(),\n platform: process.platform,\n node: process.version,\n timestamp: new Date().toISOString()\n });\n});\n\n// Root endpoint\napp.get('/', (req: Request, res: Response) => {\n res.json({\n name: 'MARIA CODE API',\n version: '4.2.22',\n status: 'running',\n environment: process.env.NODE_ENV || 'development',\n endpoints: {\n health: '/health',\n status: '/api/status',\n image: '/api/v1/image',\n video: '/api/v1/video',\n code: '/api/v1/code',\n chat: '/api/v1/chat'\n },\n timestamp: new Date().toISOString()\n });\n});\n\n/**\n * Auth: Get current user profile\n * Mirrors expected CLI contract at GET /api/user/profile\n */\napp.get('/api/user/profile', async (req: Request, res: Response) => {\n try {\n const authHeader = req.headers.authorization || '';\n if (!authHeader.startsWith('Bearer ')) {\n return res.status(401).json({ error: 'unauthorized' });\n }\n\n // NOTE: For now, return a minimal compatible shape for CLI\n const userAgent = req.headers['user-agent'] || '';\n const plan: 'FREE' | 'STARTER' | 'PRO' | 'ULTRA' | 'ENTERPRISE' = 'FREE';\n const response = {\n id: 'server-user-' + Date.now(),\n email: 'user@api.maria-code.ai',\n name: 'API User',\n plan,\n usage: {\n requests: 0,\n requestLimit: 1000,\n tokens: 0,\n tokenLimit: 500000,\n resetDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString()\n },\n models: ['gpt-5', 'gemini-2.5-pro']\n };\n\n // Optional: include UA echo to help diagnostics\n return res.status(200).json(response);\n } catch (error) {\n console.error('[User Profile] Error:', error);\n return res.status(500).json({ error: 'PROFILE_FETCH_FAILED' });\n }\n});\n\n/**\n * Auth: Revoke tokens\n * Expected by CLI at POST /api/auth/revoke\n */\napp.post('/api/auth/revoke', async (req: Request, res: Response) => {\n try {\n const authHeader = req.headers.authorization || '';\n if (!authHeader.startsWith('Bearer ')) {\n return res.status(401).json({ error: 'unauthorized' });\n }\n\n // Accept both fields used by CLI\n const { refresh_token, all_devices } = req.body || {};\n // TODO: Integrate with real session store/token revocation\n return res.status(200).json({ success: true, allDevices: Boolean(all_devices) });\n } catch (error) {\n console.error('[Auth Revoke] Error:', error);\n return res.status(500).json({ error: 'REVOCATION_FAILED' });\n }\n});\n\n// ===========================================\n// API ENDPOINTS WITH RATE LIMITING\n// ===========================================\n\n/**\n * Image Generation Endpoint\n */\napp.post('/api/v1/image', rateLimitMiddleware, async (req: Request, res: Response) => {\n try {\n const { prompt, model = 'dall-e-3', size = '1024x1024' } = req.body;\n \n if (!prompt) {\n return res.status(400).json({\n error: 'bad_request',\n message: 'Prompt is required'\n });\n }\n \n // TODO: Implement actual image generation logic\n // For now, return mock response\n return res.json({\n success: true,\n data: {\n url: `https://placeholder.com/generated-image-${Date.now()}.png`,\n prompt,\n model,\n size,\n createdAt: new Date().toISOString()\n }\n });\n } catch (error) {\n console.error('[Image API] Error:', error);\n return res.status(500).json({\n error: 'internal_error',\n message: 'Failed to generate image'\n });\n }\n});\n\n/**\n * Video Generation Endpoint\n */\napp.post('/api/v1/video', rateLimitMiddleware, async (req: Request, res: Response) => {\n try {\n const { prompt, duration = 5, model = 'runway-gen2' } = req.body;\n \n if (!prompt) {\n return res.status(400).json({\n error: 'bad_request',\n message: 'Prompt is required'\n });\n }\n \n // TODO: Implement actual video generation logic\n return res.json({\n success: true,\n data: {\n url: `https://placeholder.com/generated-video-${Date.now()}.mp4`,\n prompt,\n duration,\n model,\n createdAt: new Date().toISOString()\n }\n });\n } catch (error) {\n console.error('[Video API] Error:', error);\n return res.status(500).json({\n error: 'internal_error',\n message: 'Failed to generate video'\n });\n }\n});\n\n/**\n * Code Generation Endpoint\n */\napp.post('/api/v1/code', rateLimitMiddleware, async (req: Request, res: Response) => {\n try {\n const { prompt, language = 'typescript', model = 'gpt-4' } = req.body;\n \n if (!prompt) {\n return res.status(400).json({\n error: 'bad_request',\n message: 'Prompt is required'\n });\n }\n \n // TODO: Implement actual code generation logic\n return res.json({\n success: true,\n data: {\n code: `// Generated code for: ${prompt}\\nfunction example() {\\n return \"Generated by MARIA CODE\";\\n}`,\n language,\n model,\n prompt,\n createdAt: new Date().toISOString()\n }\n });\n } catch (error) {\n console.error('[Code API] Error:', error);\n return res.status(500).json({\n error: 'internal_error',\n message: 'Failed to generate code'\n });\n }\n});\n\n/**\n * Chat Endpoint\n */\napp.post('/api/v1/chat', rateLimitMiddleware, async (req: Request, res: Response) => {\n try {\n const { message, model = 'gpt-4' } = req.body;\n \n if (!message) {\n return res.status(400).json({\n error: 'bad_request',\n message: 'Message is required'\n });\n }\n \n // TODO: Implement actual chat logic\n return res.json({\n success: true,\n data: {\n response: `Echo: ${message}`,\n model,\n createdAt: new Date().toISOString()\n }\n });\n } catch (error) {\n console.error('[Chat API] Error:', error);\n return res.status(500).json({\n error: 'internal_error',\n message: 'Failed to process chat'\n });\n }\n});\n\n// 404 handler\napp.use((req: Request, res: Response) => {\n res.status(404).json({\n error: 'not_found',\n message: 'The requested endpoint does not exist',\n path: req.path\n });\n});\n\n// Error handler\napp.use((err: Error, req: Request, res: Response, next: NextFunction) => {\n console.error('[Server Error]:', err);\n res.status(500).json({\n error: 'internal_server_error',\n message: 'An unexpected error occurred'\n });\n});\n\n// Start server\nconst server = app.listen(port, () => {\n console.log(`🚀 MARIA CODE Express Server running on port ${port}`);\n console.log(`📍 Health check: http://localhost:${port}/health`);\n console.log(`📍 API Status: http://localhost:${port}/api/status`);\n console.log(`📍 API Endpoints: http://localhost:${port}/`);\n \n // Start rate limit cleanup job\n startRateLimitCleanup();\n console.log('🔧 Rate limit cleanup job started');\n});\n\n// Graceful shutdown\nprocess.on('SIGTERM', () => {\n console.log('SIGTERM signal received: closing HTTP server');\n server.close(() => {\n console.log('HTTP server closed');\n process.exit(0);\n });\n});\n\nprocess.on('SIGINT', () => {\n console.log('SIGINT signal received: closing HTTP server');\n server.close(() => {\n console.log('HTTP server closed');\n process.exit(0);\n });\n});\n\nexport { app, server };"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bonginkan/maria",
3
- "version": "4.2.20",
4
- "description": "🚀 MARIA v4.2.20 - Enterprise AI Development Platform with 100% Command Availability. Features 74 production-ready commands with comprehensive fallback implementation, local LLM support, and zero external dependencies. Includes natural language coding, AI safety evaluation, intelligent evolution system, episodic memory with PII masking, and real-time monitoring dashboard. Built with TypeScript AST-powered code generation, OAuth2.0 + PKCE authentication, quantum-resistant cryptography, and enterprise-grade performance.",
3
+ "version": "4.2.22",
4
+ "description": "🚀 MARIA v4.2.22 - Enterprise AI Development Platform with 100% Command Availability. Features 74 production-ready commands with comprehensive fallback implementation, local LLM support, and zero external dependencies. Includes natural language coding, AI safety evaluation, intelligent evolution system, episodic memory with PII masking, and real-time monitoring dashboard. Built with TypeScript AST-powered code generation, OAuth2.0 + PKCE authentication, quantum-resistant cryptography, and enterprise-grade performance.",
5
5
  "keywords": [
6
6
  "ai",
7
7
  "cli",
@@ -416,7 +416,11 @@
416
416
  "uuid": "^9.0.1",
417
417
  "winston": "^3.11.0",
418
418
  "ws": "^8.16.0",
419
- "zod": "^3.22.4"
419
+ "zod": "^3.22.4",
420
+ "compression": "^1.8.1",
421
+ "cors": "^2.8.5",
422
+ "express": "^5.1.0",
423
+ "helmet": "^8.1.0"
420
424
  },
421
425
  "devDependencies": {
422
426
  "@babel/parser": "^7.28.3",
@@ -443,8 +447,7 @@
443
447
  "@vitest/coverage-v8": "^1.2.0",
444
448
  "better-sqlite3": "^12.2.0",
445
449
  "cli-highlight": "^2.1.11",
446
- "compression": "^1.8.1",
447
- "cors": "^2.8.5",
450
+
448
451
  "cross-env": "^10.0.0",
449
452
  "dependency-cruiser": "^16.10.4",
450
453
  "eslint": "^8.56.0",
@@ -453,11 +456,11 @@
453
456
  "eslint-plugin-node": "^11.1.0",
454
457
  "eslint-plugin-prettier": "^5.1.3",
455
458
  "execa": "^9.6.0",
456
- "express": "^5.1.0",
459
+
457
460
  "fast-glob": "^3.3.3",
458
461
  "figures": "^6.1.0",
459
462
  "glob": "^10.3.10",
460
- "helmet": "^8.1.0",
463
+
461
464
  "jscodeshift": "^17.3.0",
462
465
  "lint-staged": "^16.1.5",
463
466
  "node-fetch": "^3.3.2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "lite-1.0.0",
3
- "generatedAt": "2025-09-10T01:47:15.949Z",
3
+ "generatedAt": "2025-09-10T04:26:34.930Z",
4
4
  "totalCommands": 11,
5
5
  "readyCount": 11,
6
6
  "partialCount": 0,