docit-ai 1.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 (81) hide show
  1. package/.env.example +1 -0
  2. package/INSTRUCTIONS.MD +70 -0
  3. package/dist/ai/engine.d.ts +24 -0
  4. package/dist/ai/engine.d.ts.map +1 -0
  5. package/dist/ai/engine.js +69 -0
  6. package/dist/ai/engine.js.map +1 -0
  7. package/dist/ai/prompts.d.ts +11 -0
  8. package/dist/ai/prompts.d.ts.map +1 -0
  9. package/dist/ai/prompts.js +116 -0
  10. package/dist/ai/prompts.js.map +1 -0
  11. package/dist/cli/index.d.ts +3 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +384 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/formatter/index.d.ts +13 -0
  16. package/dist/formatter/index.d.ts.map +1 -0
  17. package/dist/formatter/index.js +76 -0
  18. package/dist/formatter/index.js.map +1 -0
  19. package/dist/index.d.ts +7 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +9 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/parser/extractor.d.ts +23 -0
  24. package/dist/parser/extractor.d.ts.map +1 -0
  25. package/dist/parser/extractor.js +148 -0
  26. package/dist/parser/extractor.js.map +1 -0
  27. package/dist/scanner/index.d.ts +11 -0
  28. package/dist/scanner/index.d.ts.map +1 -0
  29. package/dist/scanner/index.js +30 -0
  30. package/dist/scanner/index.js.map +1 -0
  31. package/package.json +31 -0
  32. package/server/.env.example +22 -0
  33. package/server/package-lock.json +4426 -0
  34. package/server/package.json +31 -0
  35. package/server/src/config/database.d.ts +18 -0
  36. package/server/src/config/database.d.ts.map +1 -0
  37. package/server/src/config/database.js +8 -0
  38. package/server/src/config/database.js.map +1 -0
  39. package/server/src/config/database.ts +31 -0
  40. package/server/src/index.d.ts +2 -0
  41. package/server/src/index.d.ts.map +1 -0
  42. package/server/src/index.js +33 -0
  43. package/server/src/index.js.map +1 -0
  44. package/server/src/index.ts +55 -0
  45. package/server/src/middleware/auth.d.ts +12 -0
  46. package/server/src/middleware/auth.d.ts.map +1 -0
  47. package/server/src/middleware/auth.js +35 -0
  48. package/server/src/middleware/auth.js.map +1 -0
  49. package/server/src/middleware/auth.ts +56 -0
  50. package/server/src/routes/auth.d.ts +3 -0
  51. package/server/src/routes/auth.d.ts.map +1 -0
  52. package/server/src/routes/auth.js +145 -0
  53. package/server/src/routes/auth.js.map +1 -0
  54. package/server/src/routes/auth.ts +185 -0
  55. package/server/src/routes/dashboard.ts +243 -0
  56. package/server/src/routes/generate.d.ts +3 -0
  57. package/server/src/routes/generate.d.ts.map +1 -0
  58. package/server/src/routes/generate.js +55 -0
  59. package/server/src/routes/generate.js.map +1 -0
  60. package/server/src/routes/generate.ts +75 -0
  61. package/server/src/routes/payment.ts +192 -0
  62. package/server/src/services/ai.d.ts +10 -0
  63. package/server/src/services/ai.d.ts.map +1 -0
  64. package/server/src/services/ai.js +75 -0
  65. package/server/src/services/ai.js.map +1 -0
  66. package/server/src/services/ai.ts +99 -0
  67. package/server/src/services/payment.ts +141 -0
  68. package/server/src/types/flutterwave.d.ts +60 -0
  69. package/server/supabase_payments.sql +35 -0
  70. package/server/supabase_schema.sql +90 -0
  71. package/server/tsconfig.json +17 -0
  72. package/server/vercel.json +15 -0
  73. package/server/verify_dashboard.ts +126 -0
  74. package/src/ai/engine.ts +103 -0
  75. package/src/ai/prompts.ts +123 -0
  76. package/src/cli/index.ts +552 -0
  77. package/src/formatter/index.ts +110 -0
  78. package/src/index.ts +11 -0
  79. package/src/parser/extractor.ts +211 -0
  80. package/src/scanner/index.ts +49 -0
  81. package/tsconfig.json +43 -0
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "docit-server",
3
+ "version": "1.0.0",
4
+ "description": "Docit Backend API Server",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "dev": "tsx watch src/index.ts"
11
+ },
12
+ "dependencies": {
13
+ "@google/genai": "^1.38.0",
14
+ "@supabase/supabase-js": "^2.49.1",
15
+ "bcrypt": "^6.0.0",
16
+ "cors": "^2.8.5",
17
+ "dotenv": "^17.2.3",
18
+ "express": "^5.0.1",
19
+ "flutterwave-node-v3": "^1.3.0",
20
+ "jsonwebtoken": "^9.0.2"
21
+ },
22
+ "devDependencies": {
23
+ "@types/bcrypt": "^5.0.2",
24
+ "@types/cors": "^2.8.17",
25
+ "@types/express": "^5.0.1",
26
+ "@types/jsonwebtoken": "^9.0.9",
27
+ "@types/node": "^22.0.0",
28
+ "tsx": "^4.19.0",
29
+ "typescript": "^5.9.3"
30
+ }
31
+ }
@@ -0,0 +1,18 @@
1
+ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<any, "public", "public", any, any>;
2
+ export interface User {
3
+ id: string;
4
+ email: string;
5
+ password_hash: string;
6
+ credits: number;
7
+ created_at: string;
8
+ updated_at: string;
9
+ }
10
+ export interface CreditTransaction {
11
+ id: string;
12
+ user_id: string;
13
+ amount: number;
14
+ type: "purchase" | "usage" | "refund" | "bonus";
15
+ description: string;
16
+ created_at: string;
17
+ }
18
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["database.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,QAAQ,mFAAyC,CAAC;AAG/D,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,8 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+ const supabaseUrl = process.env.SUPABASE_URL ?? "";
3
+ const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY ?? "";
4
+ if (!supabaseUrl || !supabaseKey) {
5
+ throw new Error("Missing Supabase environment variables");
6
+ }
7
+ export const supabase = createClient(supabaseUrl, supabaseKey);
8
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;AACnD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC;AAEhE,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+
3
+ const supabaseUrl = process.env.SUPABASE_URL ?? "";
4
+ const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY ?? "";
5
+
6
+ if (!supabaseUrl || !supabaseKey) {
7
+ throw new Error("Missing Supabase environment variables");
8
+ }
9
+
10
+ export const supabase = createClient(supabaseUrl, supabaseKey);
11
+
12
+ // Database types
13
+ export interface User {
14
+ id: string;
15
+ email: string;
16
+ password_hash: string;
17
+ name?: string;
18
+ country?: string;
19
+ credits: number;
20
+ created_at: string;
21
+ updated_at: string;
22
+ }
23
+
24
+ export interface CreditTransaction {
25
+ id: string;
26
+ user_id: string;
27
+ amount: number;
28
+ type: "purchase" | "usage" | "refund" | "bonus";
29
+ description: string;
30
+ created_at: string;
31
+ }
@@ -0,0 +1,2 @@
1
+ import "dotenv/config";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC"}
@@ -0,0 +1,33 @@
1
+ import "dotenv/config";
2
+ import express from "express";
3
+ import cors from "cors";
4
+ import authRoutes from "./routes/auth.js";
5
+ import generateRoutes from "./routes/generate.js";
6
+ const app = express();
7
+ const PORT = process.env.PORT ?? 3001;
8
+ // Middleware
9
+ app.use(cors());
10
+ app.use(express.json({ limit: "10mb" }));
11
+ // Health check
12
+ app.get("/health", (_req, res) => {
13
+ res.json({ status: "ok", timestamp: new Date().toISOString() });
14
+ });
15
+ // Routes
16
+ app.use("/api/auth", authRoutes);
17
+ app.use("/api/generate", generateRoutes);
18
+ // Error handler
19
+ app.use((err, _req, res, _next) => {
20
+ console.error("Unhandled error:", err);
21
+ res.status(500).json({ error: "Internal server error" });
22
+ });
23
+ // Start server
24
+ app.listen(PORT, () => {
25
+ console.log(`🚀 Docit API server running on http://localhost:${PORT}`);
26
+ console.log(`📚 Endpoints:`);
27
+ console.log(` POST /api/auth/register - Create account`);
28
+ console.log(` POST /api/auth/login - Login`);
29
+ console.log(` GET /api/auth/me - Get current user`);
30
+ console.log(` GET /api/auth/credits - Get credit balance`);
31
+ console.log(` POST /api/generate - Generate documentation`);
32
+ });
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAElD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAEtC,aAAa;AACb,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AAChB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAEzC,eAAe;AACf,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC;AAEH,SAAS;AACT,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AACjC,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;AAEzC,gBAAgB;AAChB,GAAG,CAAC,GAAG,CACL,CACE,GAAU,EACV,IAAqB,EACrB,GAAqB,EACrB,KAA2B,EAC3B,EAAE;IACF,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACvC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;AAC3D,CAAC,CACF,CAAC;AAEF,eAAe;AACf,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,mDAAmD,IAAI,EAAE,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,55 @@
1
+ import "dotenv/config";
2
+ import express from "express";
3
+ import cors from "cors";
4
+ import authRoutes from "./routes/auth.js";
5
+ import generateRoutes from "./routes/generate.js";
6
+ import paymentRoutes from "./routes/payment.js";
7
+ import dashboardRoutes from "./routes/dashboard.js";
8
+
9
+ const app = express();
10
+ const PORT = process.env.PORT ?? 3001;
11
+
12
+ // Middleware
13
+ app.use(cors());
14
+ app.use(express.json({ limit: "10mb" }));
15
+
16
+ // Health check
17
+ app.get("/health", (_req, res) => {
18
+ res.json({ status: "ok", timestamp: new Date().toISOString() });
19
+ });
20
+
21
+ // Routes
22
+ app.use("/api/auth", authRoutes);
23
+ app.use("/api/generate", generateRoutes);
24
+ app.use("/api/payment", paymentRoutes);
25
+ app.use("/api/dashboard", dashboardRoutes);
26
+
27
+ // Error handler
28
+ app.use(
29
+ (
30
+ err: Error,
31
+ _req: express.Request,
32
+ res: express.Response,
33
+ _next: express.NextFunction,
34
+ ) => {
35
+ console.error("Unhandled error:", err);
36
+ res.status(500).json({ error: "Internal server error" });
37
+ },
38
+ );
39
+
40
+ // Start server
41
+ if (process.env.VERCEL !== "1") {
42
+ app.listen(PORT, () => {
43
+ console.log(`🚀 Docit API server running on http://localhost:${PORT}`);
44
+ console.log(`📚 Endpoints:`);
45
+ console.log(` POST /api/auth/register - Create account`);
46
+ console.log(` POST /api/auth/login - Login`);
47
+ console.log(` GET /api/auth/me - Get current user`);
48
+ console.log(` POST /api/generate - Generate documentation`);
49
+ console.log(` GET /api/payment/plans - Get subscription plans`);
50
+ console.log(` POST /api/payment/initiate - Start payment`);
51
+ console.log(` GET /api/dashboard/* - Dashboard stats & data`);
52
+ });
53
+ }
54
+
55
+ export default app;
@@ -0,0 +1,12 @@
1
+ import type { Request, Response, NextFunction } from "express";
2
+ import { type User } from "../config/database.js";
3
+ export interface AuthRequest extends Request {
4
+ user?: User;
5
+ userId?: string;
6
+ }
7
+ export interface JWTPayload {
8
+ userId: string;
9
+ email: string;
10
+ }
11
+ export declare function authMiddleware(req: AuthRequest, res: Response, next: NextFunction): Promise<void>;
12
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,EAAY,KAAK,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC1C,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAqCf"}
@@ -0,0 +1,35 @@
1
+ import jwt from "jsonwebtoken";
2
+ import { supabase } from "../config/database.js";
3
+ export async function authMiddleware(req, res, next) {
4
+ const authHeader = req.headers.authorization;
5
+ if (!authHeader?.startsWith("Bearer ")) {
6
+ res.status(401).json({ error: "Missing or invalid authorization header" });
7
+ return;
8
+ }
9
+ const token = authHeader.slice(7);
10
+ try {
11
+ const jwtSecret = process.env.JWT_SECRET;
12
+ if (!jwtSecret) {
13
+ res.status(500).json({ error: "Server configuration error" });
14
+ return;
15
+ }
16
+ const decoded = jwt.verify(token, jwtSecret);
17
+ // Fetch user from database
18
+ const { data: user, error } = await supabase
19
+ .from("users")
20
+ .select("*")
21
+ .eq("id", decoded.userId)
22
+ .single();
23
+ if (error || !user) {
24
+ res.status(401).json({ error: "User not found" });
25
+ return;
26
+ }
27
+ req.user = user;
28
+ req.userId = decoded.userId;
29
+ next();
30
+ }
31
+ catch {
32
+ res.status(401).json({ error: "Invalid or expired token" });
33
+ }
34
+ }
35
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["auth.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAa,MAAM,uBAAuB,CAAC;AAY5D,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAgB,EAChB,GAAa,EACb,IAAkB;IAElB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IAE7C,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC,CAAC;QAC3E,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAElC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACzC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC,CAAC;YAC9D,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAe,CAAC;QAE3D,2BAA2B;QAC3B,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ;aACzC,IAAI,CAAC,OAAO,CAAC;aACb,MAAM,CAAC,GAAG,CAAC;aACX,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC;aACxB,MAAM,EAAE,CAAC;QAEZ,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QAED,GAAG,CAAC,IAAI,GAAG,IAAY,CAAC;QACxB,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC5B,IAAI,EAAE,CAAC;IACT,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { Request, Response, NextFunction } from "express";
2
+ import jwt from "jsonwebtoken";
3
+ import { supabase, type User } from "../config/database.js";
4
+
5
+ export interface AuthRequest extends Request {
6
+ user?: User;
7
+ userId?: string;
8
+ }
9
+
10
+ export interface JWTPayload {
11
+ userId: string;
12
+ email: string;
13
+ }
14
+
15
+ export async function authMiddleware(
16
+ req: AuthRequest,
17
+ res: Response,
18
+ next: NextFunction,
19
+ ): Promise<void> {
20
+ const authHeader = req.headers.authorization;
21
+
22
+ if (!authHeader?.startsWith("Bearer ")) {
23
+ res.status(401).json({ error: "Missing or invalid authorization header" });
24
+ return;
25
+ }
26
+
27
+ const token = authHeader.slice(7);
28
+
29
+ try {
30
+ const jwtSecret = process.env.JWT_SECRET;
31
+ if (!jwtSecret) {
32
+ res.status(500).json({ error: "Server configuration error" });
33
+ return;
34
+ }
35
+
36
+ const decoded = jwt.verify(token, jwtSecret) as JWTPayload;
37
+
38
+ // Fetch user from database
39
+ const { data: user, error } = await supabase
40
+ .from("users")
41
+ .select("*")
42
+ .eq("id", decoded.userId)
43
+ .single();
44
+
45
+ if (error || !user) {
46
+ res.status(401).json({ error: "User not found" });
47
+ return;
48
+ }
49
+
50
+ req.user = user as User;
51
+ req.userId = decoded.userId;
52
+ next();
53
+ } catch {
54
+ res.status(401).json({ error: "Invalid or expired token" });
55
+ }
56
+ }
@@ -0,0 +1,3 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["auth.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA0KxB,eAAe,MAAM,CAAC"}
@@ -0,0 +1,145 @@
1
+ import { Router } from "express";
2
+ import bcrypt from "bcrypt";
3
+ import jwt from "jsonwebtoken";
4
+ import { supabase } from "../config/database.js";
5
+ import { authMiddleware } from "../middleware/auth.js";
6
+ const router = Router();
7
+ // Register
8
+ router.post("/register", async (req, res) => {
9
+ try {
10
+ const { email, password, name } = req.body;
11
+ if (!email || !password) {
12
+ res.status(400).json({ error: "Email and password are required" });
13
+ return;
14
+ }
15
+ // Check if user exists
16
+ const { data: existingUser } = await supabase
17
+ .from("users")
18
+ .select("id")
19
+ .eq("email", email)
20
+ .single();
21
+ if (existingUser) {
22
+ res.status(409).json({ error: "Email already registered" });
23
+ return;
24
+ }
25
+ // Hash password
26
+ const passwordHash = await bcrypt.hash(password, 12);
27
+ // Get free credits from env
28
+ const freeCredits = parseInt(process.env.FREE_CREDITS_ON_SIGNUP ?? "10", 10);
29
+ // Create user
30
+ const { data: user, error } = await supabase
31
+ .from("users")
32
+ .insert({
33
+ email,
34
+ password_hash: passwordHash,
35
+ name: name ?? email.split("@")[0],
36
+ credits: freeCredits,
37
+ })
38
+ .select()
39
+ .single();
40
+ if (error) {
41
+ console.error("Registration error:", error);
42
+ res.status(500).json({ error: "Failed to create user" });
43
+ return;
44
+ }
45
+ // Log credit transaction
46
+ await supabase.from("credit_transactions").insert({
47
+ user_id: user.id,
48
+ amount: freeCredits,
49
+ type: "bonus",
50
+ description: "Welcome bonus credits",
51
+ });
52
+ // Generate token
53
+ const jwtSecret = process.env.JWT_SECRET ?? "default_secret";
54
+ const token = jwt.sign({ userId: user.id, email: user.email }, jwtSecret, {
55
+ expiresIn: "30d",
56
+ });
57
+ res.status(201).json({
58
+ message: "Registration successful",
59
+ token,
60
+ user: {
61
+ id: user.id,
62
+ email: user.email,
63
+ name: user.name,
64
+ credits: user.credits,
65
+ },
66
+ });
67
+ }
68
+ catch (error) {
69
+ console.error("Registration error:", error);
70
+ res.status(500).json({ error: "Internal server error" });
71
+ }
72
+ });
73
+ // Login
74
+ router.post("/login", async (req, res) => {
75
+ try {
76
+ const { email, password } = req.body;
77
+ if (!email || !password) {
78
+ res.status(400).json({ error: "Email and password are required" });
79
+ return;
80
+ }
81
+ // Find user
82
+ const { data: user, error } = await supabase
83
+ .from("users")
84
+ .select("*")
85
+ .eq("email", email)
86
+ .single();
87
+ if (error || !user) {
88
+ res.status(401).json({ error: "Invalid email or password" });
89
+ return;
90
+ }
91
+ // Verify password
92
+ const validPassword = await bcrypt.compare(password, user.password_hash);
93
+ if (!validPassword) {
94
+ res.status(401).json({ error: "Invalid email or password" });
95
+ return;
96
+ }
97
+ // Generate token
98
+ const jwtSecret = process.env.JWT_SECRET ?? "default_secret";
99
+ const token = jwt.sign({ userId: user.id, email: user.email }, jwtSecret, {
100
+ expiresIn: "30d",
101
+ });
102
+ res.json({
103
+ message: "Login successful",
104
+ token,
105
+ user: {
106
+ id: user.id,
107
+ email: user.email,
108
+ name: user.name,
109
+ credits: user.credits,
110
+ },
111
+ });
112
+ }
113
+ catch (error) {
114
+ console.error("Login error:", error);
115
+ res.status(500).json({ error: "Internal server error" });
116
+ }
117
+ });
118
+ // Get current user
119
+ router.get("/me", authMiddleware, async (req, res) => {
120
+ const user = req.user;
121
+ res.json({
122
+ user: {
123
+ id: user.id,
124
+ email: user.email,
125
+ credits: user.credits,
126
+ },
127
+ });
128
+ });
129
+ // Get credit balance
130
+ router.get("/credits", authMiddleware, async (req, res) => {
131
+ const user = req.user;
132
+ // Get transaction history
133
+ const { data: transactions } = await supabase
134
+ .from("credit_transactions")
135
+ .select("*")
136
+ .eq("user_id", user.id)
137
+ .order("created_at", { ascending: false })
138
+ .limit(10);
139
+ res.json({
140
+ credits: user.credits,
141
+ transactions: transactions ?? [],
142
+ });
143
+ });
144
+ export default router;
145
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ import { Router } from "express";
2
+ import bcrypt from "bcrypt";
3
+ import jwt from "jsonwebtoken";
4
+ import { supabase } from "../config/database.js";
5
+ import { authMiddleware, type AuthRequest } from "../middleware/auth.js";
6
+
7
+ const router = Router();
8
+
9
+ // Register
10
+ router.post("/register", async (req, res) => {
11
+ try {
12
+ const { email, password, name, country } = req.body as {
13
+ email?: string;
14
+ password?: string;
15
+ name?: string;
16
+ country?: string;
17
+ };
18
+
19
+ if (!email || !password) {
20
+ res.status(400).json({ error: "Email and password are required" });
21
+ return;
22
+ }
23
+
24
+ // Check if user exists
25
+ const { data: existingUser } = await supabase
26
+ .from("users")
27
+ .select("id")
28
+ .eq("email", email)
29
+ .single();
30
+
31
+ if (existingUser) {
32
+ res.status(409).json({ error: "Email already registered" });
33
+ return;
34
+ }
35
+
36
+ // Hash password
37
+ const passwordHash = await bcrypt.hash(password, 12);
38
+
39
+ // Get free credits from env
40
+ const freeCredits = parseInt(
41
+ process.env.FREE_CREDITS_ON_SIGNUP ?? "10",
42
+ 10,
43
+ );
44
+
45
+ // Create user
46
+ const { data: user, error } = await supabase
47
+ .from("users")
48
+ .insert({
49
+ email,
50
+ password_hash: passwordHash,
51
+ name: name ?? email.split("@")[0],
52
+ country,
53
+ credits: freeCredits,
54
+ })
55
+ .select()
56
+ .single();
57
+
58
+ if (error) {
59
+ console.error("Registration error:", error);
60
+ res.status(500).json({ error: "Failed to create user" });
61
+ return;
62
+ }
63
+
64
+ // Log credit transaction
65
+ await supabase.from("credit_transactions").insert({
66
+ user_id: user.id,
67
+ amount: freeCredits,
68
+ type: "bonus",
69
+ description: "Welcome bonus credits",
70
+ });
71
+
72
+ // Generate token
73
+ const jwtSecret = process.env.JWT_SECRET ?? "default_secret";
74
+ const token = jwt.sign({ userId: user.id, email: user.email }, jwtSecret, {
75
+ expiresIn: "30d",
76
+ });
77
+
78
+ res.status(201).json({
79
+ message: "Registration successful",
80
+ token,
81
+ user: {
82
+ id: user.id,
83
+ email: user.email,
84
+ name: user.name,
85
+ country: user.country,
86
+ credits: user.credits,
87
+ },
88
+ });
89
+ } catch (error) {
90
+ console.error("Registration error:", error);
91
+ res.status(500).json({ error: "Internal server error" });
92
+ }
93
+ });
94
+
95
+ // Login
96
+ router.post("/login", async (req, res) => {
97
+ try {
98
+ const { email, password } = req.body as {
99
+ email?: string;
100
+ password?: string;
101
+ };
102
+
103
+ if (!email || !password) {
104
+ res.status(400).json({ error: "Email and password are required" });
105
+ return;
106
+ }
107
+
108
+ // Find user
109
+ const { data: user, error } = await supabase
110
+ .from("users")
111
+ .select("*")
112
+ .eq("email", email)
113
+ .single();
114
+
115
+ if (error || !user) {
116
+ res.status(401).json({ error: "Invalid email or password" });
117
+ return;
118
+ }
119
+
120
+ // Verify password
121
+ const validPassword = await bcrypt.compare(password, user.password_hash);
122
+ if (!validPassword) {
123
+ res.status(401).json({ error: "Invalid email or password" });
124
+ return;
125
+ }
126
+
127
+ // Generate token
128
+ const jwtSecret = process.env.JWT_SECRET ?? "default_secret";
129
+ const token = jwt.sign({ userId: user.id, email: user.email }, jwtSecret, {
130
+ expiresIn: "30d",
131
+ });
132
+
133
+ res.json({
134
+ message: "Login successful",
135
+ token,
136
+ user: {
137
+ id: user.id,
138
+ email: user.email,
139
+ name: user.name,
140
+ country: user.country,
141
+ credits: user.credits,
142
+ },
143
+ });
144
+ } catch (error) {
145
+ console.error("Login error:", error);
146
+ res.status(500).json({ error: "Internal server error" });
147
+ }
148
+ });
149
+
150
+ // Get current user
151
+ router.get("/me", authMiddleware, async (req: AuthRequest, res) => {
152
+ const user = req.user!;
153
+
154
+ res.json({
155
+ user: {
156
+ id: user.id,
157
+ email: user.email,
158
+ name: user.name,
159
+ country: user.country,
160
+ credits: user.credits,
161
+ createdAt: user.created_at,
162
+ updatedAt: user.updated_at,
163
+ },
164
+ });
165
+ });
166
+
167
+ // Get credit balance
168
+ router.get("/credits", authMiddleware, async (req: AuthRequest, res) => {
169
+ const user = req.user!;
170
+
171
+ // Get transaction history
172
+ const { data: transactions } = await supabase
173
+ .from("credit_transactions")
174
+ .select("*")
175
+ .eq("user_id", user.id)
176
+ .order("created_at", { ascending: false })
177
+ .limit(10);
178
+
179
+ res.json({
180
+ credits: user.credits,
181
+ transactions: transactions ?? [],
182
+ });
183
+ });
184
+
185
+ export default router;