@programinglive/dev-workflow-mcp-server 1.7.12 → 1.7.14

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.
package/web/package.json CHANGED
@@ -1,25 +1,36 @@
1
1
  {
2
2
  "name": "web",
3
- "version": "0.1.0",
3
+ "version": "1.7.18",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "node server.js",
8
8
  "build": "next build",
9
- "start": "NODE_ENV=production node server.js",
9
+ "start": "cross-env NODE_ENV=production node server.js",
10
10
  "lint": "next lint"
11
11
  },
12
12
  "dependencies": {
13
+ "bcrypt": "^6.0.0",
14
+ "connect-pg-simple": "^10.0.0",
15
+ "cors": "^2.8.5",
16
+ "dotenv": "^17.2.3",
17
+ "express": "^5.2.1",
18
+ "express-session": "^1.18.2",
19
+ "jsonwebtoken": "^9.0.3",
13
20
  "lucide-react": "^0.555.0",
14
21
  "next": "^16.0.10",
22
+ "pg": "^8.16.3",
15
23
  "react": "19.2.0",
16
24
  "react-dom": "19.2.0"
17
25
  },
18
26
  "devDependencies": {
27
+ "@netlify/plugin-nextjs": "^5.15.2",
19
28
  "@types/node": "^20",
29
+ "@types/pg": "^8.16.0",
20
30
  "@types/react": "^19",
21
31
  "@types/react-dom": "^19",
22
32
  "autoprefixer": "^10.4.22",
33
+ "cross-env": "^10.1.0",
23
34
  "eslint": "^9",
24
35
  "eslint-config-next": "16.0.4",
25
36
  "postcss": "^8.5.6",
@@ -0,0 +1,120 @@
1
+ import pg from 'pg';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ import { fileURLToPath } from 'url';
5
+ import dotenv from 'dotenv';
6
+ import { createRequire } from 'module';
7
+
8
+ const require = createRequire(import.meta.url);
9
+ const { Pool } = pg;
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ // Silence stdout during dotenv loading to prevent noise in API output
15
+ const originalWrite = process.stdout.write;
16
+ process.stdout.write = () => true; // No-op
17
+
18
+ try {
19
+ // Try web/.env
20
+ dotenv.config({ path: path.join(__dirname, '../.env') });
21
+ // Try root .env
22
+ dotenv.config({ path: path.join(__dirname, '../../.env') });
23
+ } catch (e) {
24
+ // dotenv might not be available
25
+ } finally {
26
+ // Restore stdout
27
+ process.stdout.write = originalWrite;
28
+ }
29
+
30
+ const defaultUrl = 'postgres://devworkflow:devworkflow_secure_password_change_me@localhost:5432/devworkflow';
31
+ const connectionString = process.env.DEV_WORKFLOW_DB_URL || defaultUrl;
32
+ const rawSid = process.argv[2]; // Passed from API
33
+
34
+ // DEBUG: output connection details to stderr (so it doesn't break JSON on stdout)
35
+ try {
36
+ const urlStr = connectionString.startsWith('postgres') ? connectionString : `postgres://${connectionString}`; // handle simpler strings if needed
37
+ // Simple heuristic parsing or URL object
38
+ const u = new URL(urlStr);
39
+ console.error(`DEBUG: Connecting to Host: ${u.hostname}, Port: ${u.port}, User: ${u.username}`);
40
+ } catch (err) {
41
+ console.error('DEBUG: Could not parse connection string for logging');
42
+ }
43
+
44
+ if (!connectionString) {
45
+ // Should be unreachable with defaultUrl, but good for safety
46
+ console.error(JSON.stringify({ error: 'Database configuration missing' }));
47
+ process.exit(1);
48
+ }
49
+
50
+ const pool = new Pool({ connectionString });
51
+
52
+ async function run() {
53
+ try {
54
+ let userId = null;
55
+
56
+ // 1. Validate Session if provided
57
+ if (rawSid) {
58
+ // Parse 's:session_id.signature' -> 'session_id'
59
+ // Simplified logic: between 's:' and '.'
60
+ let sid = rawSid;
61
+ if (rawSid.startsWith('s:')) {
62
+ sid = rawSid.slice(2, rawSid.lastIndexOf('.'));
63
+ } else if (rawSid.includes('.')) {
64
+ // heuristic for signed cookie without s: prefix?
65
+ sid = rawSid.slice(0, rawSid.lastIndexOf('.'));
66
+ }
67
+
68
+ // Try lookup
69
+ const sessionRes = await pool.query("SELECT sess FROM session WHERE sid = $1", [sid]);
70
+ if (sessionRes.rows.length > 0) {
71
+ const sessionData = sessionRes.rows[0].sess;
72
+ if (sessionData && sessionData.userId) {
73
+ userId = sessionData.userId;
74
+ }
75
+ }
76
+ }
77
+
78
+ // 2. Fallback if no valid session found (for dev/recovery comfort)
79
+ if (!userId) {
80
+ // Try admin
81
+ const userRes = await pool.query("SELECT id FROM users WHERE LOWER(username) = 'admin'");
82
+ if (userRes.rows.length > 0) {
83
+ userId = userRes.rows[0].id;
84
+ } else {
85
+ const anyUser = await pool.query("SELECT id FROM users LIMIT 1");
86
+ if (anyUser.rows.length > 0) {
87
+ userId = anyUser.rows[0].id;
88
+ } else {
89
+ throw new Error('No user found');
90
+ }
91
+ }
92
+ }
93
+
94
+ // 3. (Self-healing removed as it was causing schema errors)
95
+
96
+ const result = await pool.query(`
97
+ SELECT
98
+ id,
99
+ task_type,
100
+ description,
101
+ commit_message,
102
+ completed_at,
103
+ tests_passed,
104
+ documentation_type
105
+ FROM workflow_history
106
+ WHERE user_id = $1
107
+ ORDER BY completed_at DESC LIMIT 100
108
+ `, [userId]);
109
+
110
+ console.log(JSON.stringify({ history: result.rows }));
111
+
112
+ } catch (error) {
113
+ console.error(JSON.stringify({ error: error.message, stack: error.stack }));
114
+ process.exit(1);
115
+ } finally {
116
+ await pool.end();
117
+ }
118
+ }
119
+
120
+ run();
package/web/server.js CHANGED
@@ -5,6 +5,15 @@ import express from 'express';
5
5
  import session from 'express-session';
6
6
  import connectPgSimple from 'connect-pg-simple';
7
7
  import pg from 'pg';
8
+ import dotenv from 'dotenv';
9
+ import path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ // Load env from root
16
+ dotenv.config({ path: path.resolve(__dirname, '../.env') });
8
17
 
9
18
  const pgSession = connectPgSimple(session);
10
19
  const { Pool } = pg;
@@ -130,7 +139,8 @@ app.prepare().then(() => {
130
139
  try {
131
140
  // Get user details to filter history
132
141
  // We assume workflow_history.user_id stores the username (based on schema)
133
- const user = req.session.username; // This should be populated during login
142
+ // We use userId (integer) to query the foreign key column
143
+ const userId = req.session.userId;
134
144
 
135
145
  let query = `
136
146
  SELECT
@@ -146,11 +156,9 @@ app.prepare().then(() => {
146
156
 
147
157
  const params = [];
148
158
 
149
- // If we have a username, filter by it.
150
- // Note: DB schema has user_id just as text, assuming it matches username
151
- if (user) {
159
+ if (userId) {
152
160
  query += ` WHERE user_id = $1 `;
153
- params.push(user);
161
+ params.push(userId);
154
162
  }
155
163
 
156
164
  query += ` ORDER BY timestamp DESC LIMIT 100`;
@@ -1,52 +0,0 @@
1
- #!/usr/bin/env node
2
- import 'dotenv/config';
3
- import pg from 'pg';
4
- import { createUser } from '../web/lib/auth.js';
5
-
6
- const { Pool } = pg;
7
-
8
- // Get database configuration from environment
9
- const dbUrl = process.env.DEV_WORKFLOW_DB_URL;
10
-
11
- if (!dbUrl) {
12
- console.error('Error: DEV_WORKFLOW_DB_URL environment variable is not set');
13
- process.exit(1);
14
- }
15
-
16
- const pool = new Pool({ connectionString: dbUrl });
17
-
18
- async function addUser() {
19
- const username = process.argv[2];
20
- const password = process.argv[3];
21
- const email = process.argv[4];
22
-
23
- if (!username || !password) {
24
- console.error('Usage: node scripts/add-user.js <username> <password> [email]');
25
- process.exit(1);
26
- }
27
-
28
- try {
29
- // Check if user already exists
30
- const existing = await pool.query('SELECT id FROM users WHERE username = $1', [username]);
31
-
32
- if (existing.rows.length > 0) {
33
- console.log(`✗ User '${username}' already exists`);
34
- process.exit(1);
35
- }
36
-
37
- // Create user
38
- const user = await createUser(pool, username, password, email);
39
- console.log(`✓ Created user: ${user.username}`);
40
- if (user.email) {
41
- console.log(` Email: ${user.email}`);
42
- }
43
-
44
- } catch (error) {
45
- console.error('Error creating user:', error.message);
46
- process.exit(1);
47
- } finally {
48
- await pool.end();
49
- }
50
- }
51
-
52
- addUser();