@openqa/cli 1.0.6 → 1.0.7

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/dist/cli/index.js CHANGED
@@ -12,123 +12,171 @@ import { Tracer } from "@orka-js/observability";
12
12
  import { EventEmitter as EventEmitter3 } from "events";
13
13
 
14
14
  // database/index.ts
15
- import Database from "better-sqlite3";
16
- import { readFileSync } from "fs";
17
- import { join, dirname } from "path";
15
+ import { Low } from "lowdb";
16
+ import { JSONFile } from "lowdb/node";
17
+ import { dirname } from "path";
18
18
  import { fileURLToPath } from "url";
19
19
  import { mkdirSync } from "fs";
20
20
  var __filename = fileURLToPath(import.meta.url);
21
21
  var __dirname = dirname(__filename);
22
22
  var OpenQADatabase = class {
23
- db;
24
- constructor(dbPath = "./data/openqa.db") {
25
- const dir = dirname(dbPath);
26
- mkdirSync(dir, { recursive: true });
27
- this.db = new Database(dbPath);
23
+ constructor(dbPath = "./data/openqa.json") {
24
+ this.dbPath = dbPath;
28
25
  this.initialize();
29
26
  }
27
+ db = null;
30
28
  initialize() {
31
- const schema = readFileSync(join(__dirname, "schema.sql"), "utf-8");
32
- this.db.exec(schema);
33
- }
34
- getConfig(key) {
35
- const row = this.db.prepare("SELECT value FROM config WHERE key = ?").get(key);
36
- return row?.value || null;
37
- }
38
- setConfig(key, value) {
39
- this.db.prepare("INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)").run(key, value);
40
- }
41
- getAllConfig() {
42
- const rows = this.db.prepare("SELECT key, value FROM config").all();
43
- return Object.fromEntries(rows.map((r) => [r.key, r.value]));
44
- }
45
- createSession(id, metadata) {
46
- this.db.prepare("INSERT INTO test_sessions (id, status, metadata) VALUES (?, ?, ?)").run(
47
- id,
48
- "running",
49
- metadata ? JSON.stringify(metadata) : null
50
- );
51
- return this.getSession(id);
52
- }
53
- getSession(id) {
54
- return this.db.prepare("SELECT * FROM test_sessions WHERE id = ?").get(id);
29
+ const dir = dirname(this.dbPath);
30
+ mkdirSync(dir, { recursive: true });
31
+ const adapter = new JSONFile(this.dbPath);
32
+ this.db = new Low(adapter, {
33
+ config: {},
34
+ test_sessions: [],
35
+ actions: [],
36
+ bugs: [],
37
+ kanban_tickets: []
38
+ });
39
+ this.db.read();
40
+ if (!this.db.data) {
41
+ this.db.data = {
42
+ config: {},
43
+ test_sessions: [],
44
+ actions: [],
45
+ bugs: [],
46
+ kanban_tickets: []
47
+ };
48
+ this.db.write();
49
+ }
55
50
  }
56
- updateSession(id, updates) {
57
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
58
- const values = [...Object.values(updates), id];
59
- this.db.prepare(`UPDATE test_sessions SET ${fields} WHERE id = ?`).run(...values);
51
+ async ensureInitialized() {
52
+ if (!this.db) {
53
+ this.initialize();
54
+ }
55
+ await this.db.read();
60
56
  }
61
- getRecentSessions(limit = 10) {
62
- return this.db.prepare("SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?").all(limit);
57
+ async getConfig(key) {
58
+ await this.ensureInitialized();
59
+ return this.db.data.config[key] || null;
63
60
  }
64
- createAction(action) {
65
- const id = `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
66
- this.db.prepare("INSERT INTO actions (id, session_id, type, description, input, output, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?)").run(
67
- id,
68
- action.session_id,
69
- action.type,
70
- action.description,
71
- action.input || null,
72
- action.output || null,
73
- action.screenshot_path || null
74
- );
75
- return this.db.prepare("SELECT * FROM actions WHERE id = ?").get(id);
61
+ async setConfig(key, value) {
62
+ await this.ensureInitialized();
63
+ this.db.data.config[key] = value;
64
+ await this.db.write();
76
65
  }
77
- getSessionActions(sessionId) {
78
- return this.db.prepare("SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC").all(sessionId);
66
+ async getAllConfig() {
67
+ await this.ensureInitialized();
68
+ return this.db.data.config;
79
69
  }
80
- createBug(bug) {
81
- const id = `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
82
- this.db.prepare("INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
70
+ async createSession(id, metadata) {
71
+ await this.ensureInitialized();
72
+ const session = {
83
73
  id,
84
- bug.session_id,
85
- bug.title,
86
- bug.description,
87
- bug.severity,
88
- bug.status,
89
- bug.github_issue_url || null,
90
- bug.screenshot_path || null
91
- );
92
- return this.db.prepare("SELECT * FROM bugs WHERE id = ?").get(id);
93
- }
94
- updateBug(id, updates) {
95
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
96
- const values = [...Object.values(updates), id];
97
- this.db.prepare(`UPDATE bugs SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
98
- }
99
- getAllBugs() {
100
- return this.db.prepare("SELECT * FROM bugs ORDER BY created_at DESC").all();
74
+ started_at: (/* @__PURE__ */ new Date()).toISOString(),
75
+ status: "running",
76
+ total_actions: 0,
77
+ bugs_found: 0,
78
+ metadata: metadata ? JSON.stringify(metadata) : void 0
79
+ };
80
+ this.db.data.test_sessions.push(session);
81
+ await this.db.write();
82
+ return session;
83
+ }
84
+ async getSession(id) {
85
+ await this.ensureInitialized();
86
+ return this.db.data.test_sessions.find((s) => s.id === id) || null;
87
+ }
88
+ async updateSession(id, updates) {
89
+ await this.ensureInitialized();
90
+ const index = this.db.data.test_sessions.findIndex((s) => s.id === id);
91
+ if (index !== -1) {
92
+ this.db.data.test_sessions[index] = { ...this.db.data.test_sessions[index], ...updates };
93
+ await this.db.write();
94
+ }
101
95
  }
102
- getBugsByStatus(status) {
103
- return this.db.prepare("SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC").all(status);
96
+ async getRecentSessions(limit = 10) {
97
+ await this.ensureInitialized();
98
+ return this.db.data.test_sessions.sort((a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime()).slice(0, limit);
104
99
  }
105
- createKanbanTicket(ticket) {
106
- const id = `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
107
- this.db.prepare("INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
108
- id,
109
- ticket.bug_id || null,
110
- ticket.title,
111
- ticket.description,
112
- ticket.priority,
113
- ticket.column,
114
- ticket.tags || null,
115
- ticket.screenshot_url || null
116
- );
117
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE id = ?").get(id);
100
+ async createAction(action) {
101
+ await this.ensureInitialized();
102
+ const newAction = {
103
+ id: `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
104
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
105
+ ...action
106
+ };
107
+ this.db.data.actions.push(newAction);
108
+ await this.db.write();
109
+ return newAction;
110
+ }
111
+ async getSessionActions(sessionId) {
112
+ await this.ensureInitialized();
113
+ return this.db.data.actions.filter((a) => a.session_id === sessionId).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
114
+ }
115
+ async createBug(bug) {
116
+ await this.ensureInitialized();
117
+ const newBug = {
118
+ id: `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
119
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
120
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
121
+ ...bug
122
+ };
123
+ this.db.data.bugs.push(newBug);
124
+ await this.db.write();
125
+ return newBug;
126
+ }
127
+ async updateBug(id, updates) {
128
+ await this.ensureInitialized();
129
+ const index = this.db.data.bugs.findIndex((b) => b.id === id);
130
+ if (index !== -1) {
131
+ this.db.data.bugs[index] = {
132
+ ...this.db.data.bugs[index],
133
+ ...updates,
134
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
135
+ };
136
+ await this.db.write();
137
+ }
118
138
  }
119
- updateKanbanTicket(id, updates) {
120
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
121
- const values = [...Object.values(updates), id];
122
- this.db.prepare(`UPDATE kanban_tickets SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
139
+ async getAllBugs() {
140
+ await this.ensureInitialized();
141
+ return this.db.data.bugs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
142
+ }
143
+ async getBugsByStatus(status) {
144
+ await this.ensureInitialized();
145
+ return this.db.data.bugs.filter((b) => b.status === status).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
146
+ }
147
+ async createKanbanTicket(ticket) {
148
+ await this.ensureInitialized();
149
+ const newTicket = {
150
+ id: `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
151
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
152
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
153
+ ...ticket
154
+ };
155
+ this.db.data.kanban_tickets.push(newTicket);
156
+ await this.db.write();
157
+ return newTicket;
158
+ }
159
+ async updateKanbanTicket(id, updates) {
160
+ await this.ensureInitialized();
161
+ const index = this.db.data.kanban_tickets.findIndex((t) => t.id === id);
162
+ if (index !== -1) {
163
+ this.db.data.kanban_tickets[index] = {
164
+ ...this.db.data.kanban_tickets[index],
165
+ ...updates,
166
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
167
+ };
168
+ await this.db.write();
169
+ }
123
170
  }
124
- getKanbanTickets() {
125
- return this.db.prepare("SELECT * FROM kanban_tickets ORDER BY created_at DESC").all();
171
+ async getKanbanTickets() {
172
+ await this.ensureInitialized();
173
+ return this.db.data.kanban_tickets.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
126
174
  }
127
- getKanbanTicketsByColumn(column) {
128
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE column = ? ORDER BY created_at DESC").all(column);
175
+ async getKanbanTicketsByColumn(column) {
176
+ await this.ensureInitialized();
177
+ return this.db.data.kanban_tickets.filter((t) => t.column === column).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
129
178
  }
130
- close() {
131
- this.db.close();
179
+ async close() {
132
180
  }
133
181
  };
134
182
 
@@ -1583,7 +1631,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
1583
1631
 
1584
1632
  // cli/index.ts
1585
1633
  import { spawn } from "child_process";
1586
- import { writeFileSync, readFileSync as readFileSync2, existsSync, unlinkSync } from "fs";
1634
+ import { writeFileSync as writeFileSync2, readFileSync as readFileSync2, existsSync, unlinkSync } from "fs";
1587
1635
  import { join as join3 } from "path";
1588
1636
  import chalk from "chalk";
1589
1637
  import ora from "ora";
@@ -1611,7 +1659,7 @@ program.command("start").description("Start the OpenQA agent and web UI").option
1611
1659
  stdio: "ignore"
1612
1660
  });
1613
1661
  child.unref();
1614
- writeFileSync(PID_FILE, child.pid.toString());
1662
+ writeFileSync2(PID_FILE, child.pid.toString());
1615
1663
  spinner.succeed(chalk.green("OpenQA started in daemon mode"));
1616
1664
  console.log(chalk.cyan(`PID: ${child.pid}`));
1617
1665
  } else {
@@ -1,121 +1,169 @@
1
1
  // database/index.ts
2
- import Database from "better-sqlite3";
3
- import { readFileSync } from "fs";
4
- import { join, dirname } from "path";
2
+ import { Low } from "lowdb";
3
+ import { JSONFile } from "lowdb/node";
4
+ import { dirname } from "path";
5
5
  import { fileURLToPath } from "url";
6
6
  import { mkdirSync } from "fs";
7
7
  var __filename = fileURLToPath(import.meta.url);
8
8
  var __dirname = dirname(__filename);
9
9
  var OpenQADatabase = class {
10
- db;
11
- constructor(dbPath = "./data/openqa.db") {
12
- const dir = dirname(dbPath);
13
- mkdirSync(dir, { recursive: true });
14
- this.db = new Database(dbPath);
10
+ constructor(dbPath = "./data/openqa.json") {
11
+ this.dbPath = dbPath;
15
12
  this.initialize();
16
13
  }
14
+ db = null;
17
15
  initialize() {
18
- const schema = readFileSync(join(__dirname, "schema.sql"), "utf-8");
19
- this.db.exec(schema);
20
- }
21
- getConfig(key) {
22
- const row = this.db.prepare("SELECT value FROM config WHERE key = ?").get(key);
23
- return row?.value || null;
24
- }
25
- setConfig(key, value) {
26
- this.db.prepare("INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)").run(key, value);
27
- }
28
- getAllConfig() {
29
- const rows = this.db.prepare("SELECT key, value FROM config").all();
30
- return Object.fromEntries(rows.map((r) => [r.key, r.value]));
31
- }
32
- createSession(id, metadata) {
33
- this.db.prepare("INSERT INTO test_sessions (id, status, metadata) VALUES (?, ?, ?)").run(
34
- id,
35
- "running",
36
- metadata ? JSON.stringify(metadata) : null
37
- );
38
- return this.getSession(id);
39
- }
40
- getSession(id) {
41
- return this.db.prepare("SELECT * FROM test_sessions WHERE id = ?").get(id);
42
- }
43
- updateSession(id, updates) {
44
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
45
- const values = [...Object.values(updates), id];
46
- this.db.prepare(`UPDATE test_sessions SET ${fields} WHERE id = ?`).run(...values);
47
- }
48
- getRecentSessions(limit = 10) {
49
- return this.db.prepare("SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?").all(limit);
50
- }
51
- createAction(action) {
52
- const id = `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
53
- this.db.prepare("INSERT INTO actions (id, session_id, type, description, input, output, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?)").run(
54
- id,
55
- action.session_id,
56
- action.type,
57
- action.description,
58
- action.input || null,
59
- action.output || null,
60
- action.screenshot_path || null
61
- );
62
- return this.db.prepare("SELECT * FROM actions WHERE id = ?").get(id);
63
- }
64
- getSessionActions(sessionId) {
65
- return this.db.prepare("SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC").all(sessionId);
66
- }
67
- createBug(bug) {
68
- const id = `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
69
- this.db.prepare("INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
70
- id,
71
- bug.session_id,
72
- bug.title,
73
- bug.description,
74
- bug.severity,
75
- bug.status,
76
- bug.github_issue_url || null,
77
- bug.screenshot_path || null
78
- );
79
- return this.db.prepare("SELECT * FROM bugs WHERE id = ?").get(id);
80
- }
81
- updateBug(id, updates) {
82
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
83
- const values = [...Object.values(updates), id];
84
- this.db.prepare(`UPDATE bugs SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
85
- }
86
- getAllBugs() {
87
- return this.db.prepare("SELECT * FROM bugs ORDER BY created_at DESC").all();
88
- }
89
- getBugsByStatus(status) {
90
- return this.db.prepare("SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC").all(status);
91
- }
92
- createKanbanTicket(ticket) {
93
- const id = `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
94
- this.db.prepare("INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(
16
+ const dir = dirname(this.dbPath);
17
+ mkdirSync(dir, { recursive: true });
18
+ const adapter = new JSONFile(this.dbPath);
19
+ this.db = new Low(adapter, {
20
+ config: {},
21
+ test_sessions: [],
22
+ actions: [],
23
+ bugs: [],
24
+ kanban_tickets: []
25
+ });
26
+ this.db.read();
27
+ if (!this.db.data) {
28
+ this.db.data = {
29
+ config: {},
30
+ test_sessions: [],
31
+ actions: [],
32
+ bugs: [],
33
+ kanban_tickets: []
34
+ };
35
+ this.db.write();
36
+ }
37
+ }
38
+ async ensureInitialized() {
39
+ if (!this.db) {
40
+ this.initialize();
41
+ }
42
+ await this.db.read();
43
+ }
44
+ async getConfig(key) {
45
+ await this.ensureInitialized();
46
+ return this.db.data.config[key] || null;
47
+ }
48
+ async setConfig(key, value) {
49
+ await this.ensureInitialized();
50
+ this.db.data.config[key] = value;
51
+ await this.db.write();
52
+ }
53
+ async getAllConfig() {
54
+ await this.ensureInitialized();
55
+ return this.db.data.config;
56
+ }
57
+ async createSession(id, metadata) {
58
+ await this.ensureInitialized();
59
+ const session = {
95
60
  id,
96
- ticket.bug_id || null,
97
- ticket.title,
98
- ticket.description,
99
- ticket.priority,
100
- ticket.column,
101
- ticket.tags || null,
102
- ticket.screenshot_url || null
103
- );
104
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE id = ?").get(id);
105
- }
106
- updateKanbanTicket(id, updates) {
107
- const fields = Object.keys(updates).map((k) => `${k} = ?`).join(", ");
108
- const values = [...Object.values(updates), id];
109
- this.db.prepare(`UPDATE kanban_tickets SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
110
- }
111
- getKanbanTickets() {
112
- return this.db.prepare("SELECT * FROM kanban_tickets ORDER BY created_at DESC").all();
113
- }
114
- getKanbanTicketsByColumn(column) {
115
- return this.db.prepare("SELECT * FROM kanban_tickets WHERE column = ? ORDER BY created_at DESC").all(column);
116
- }
117
- close() {
118
- this.db.close();
61
+ started_at: (/* @__PURE__ */ new Date()).toISOString(),
62
+ status: "running",
63
+ total_actions: 0,
64
+ bugs_found: 0,
65
+ metadata: metadata ? JSON.stringify(metadata) : void 0
66
+ };
67
+ this.db.data.test_sessions.push(session);
68
+ await this.db.write();
69
+ return session;
70
+ }
71
+ async getSession(id) {
72
+ await this.ensureInitialized();
73
+ return this.db.data.test_sessions.find((s) => s.id === id) || null;
74
+ }
75
+ async updateSession(id, updates) {
76
+ await this.ensureInitialized();
77
+ const index = this.db.data.test_sessions.findIndex((s) => s.id === id);
78
+ if (index !== -1) {
79
+ this.db.data.test_sessions[index] = { ...this.db.data.test_sessions[index], ...updates };
80
+ await this.db.write();
81
+ }
82
+ }
83
+ async getRecentSessions(limit = 10) {
84
+ await this.ensureInitialized();
85
+ return this.db.data.test_sessions.sort((a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime()).slice(0, limit);
86
+ }
87
+ async createAction(action) {
88
+ await this.ensureInitialized();
89
+ const newAction = {
90
+ id: `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
91
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
92
+ ...action
93
+ };
94
+ this.db.data.actions.push(newAction);
95
+ await this.db.write();
96
+ return newAction;
97
+ }
98
+ async getSessionActions(sessionId) {
99
+ await this.ensureInitialized();
100
+ return this.db.data.actions.filter((a) => a.session_id === sessionId).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
101
+ }
102
+ async createBug(bug) {
103
+ await this.ensureInitialized();
104
+ const newBug = {
105
+ id: `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
106
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
107
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
108
+ ...bug
109
+ };
110
+ this.db.data.bugs.push(newBug);
111
+ await this.db.write();
112
+ return newBug;
113
+ }
114
+ async updateBug(id, updates) {
115
+ await this.ensureInitialized();
116
+ const index = this.db.data.bugs.findIndex((b) => b.id === id);
117
+ if (index !== -1) {
118
+ this.db.data.bugs[index] = {
119
+ ...this.db.data.bugs[index],
120
+ ...updates,
121
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
122
+ };
123
+ await this.db.write();
124
+ }
125
+ }
126
+ async getAllBugs() {
127
+ await this.ensureInitialized();
128
+ return this.db.data.bugs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
129
+ }
130
+ async getBugsByStatus(status) {
131
+ await this.ensureInitialized();
132
+ return this.db.data.bugs.filter((b) => b.status === status).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
133
+ }
134
+ async createKanbanTicket(ticket) {
135
+ await this.ensureInitialized();
136
+ const newTicket = {
137
+ id: `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
138
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
139
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
140
+ ...ticket
141
+ };
142
+ this.db.data.kanban_tickets.push(newTicket);
143
+ await this.db.write();
144
+ return newTicket;
145
+ }
146
+ async updateKanbanTicket(id, updates) {
147
+ await this.ensureInitialized();
148
+ const index = this.db.data.kanban_tickets.findIndex((t) => t.id === id);
149
+ if (index !== -1) {
150
+ this.db.data.kanban_tickets[index] = {
151
+ ...this.db.data.kanban_tickets[index],
152
+ ...updates,
153
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
154
+ };
155
+ await this.db.write();
156
+ }
157
+ }
158
+ async getKanbanTickets() {
159
+ await this.ensureInitialized();
160
+ return this.db.data.kanban_tickets.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
161
+ }
162
+ async getKanbanTicketsByColumn(column) {
163
+ await this.ensureInitialized();
164
+ return this.db.data.kanban_tickets.filter((t) => t.column === column).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
165
+ }
166
+ async close() {
119
167
  }
120
168
  };
121
169
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../database/index.ts"],"sourcesContent":["import Database from 'better-sqlite3';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { mkdirSync } from 'fs';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface TestSession {\n id: string;\n started_at: string;\n ended_at?: string;\n status: 'running' | 'completed' | 'failed';\n total_actions: number;\n bugs_found: number;\n metadata?: string;\n}\n\nexport interface Action {\n id: string;\n session_id: string;\n timestamp: string;\n type: string;\n description: string;\n input?: string;\n output?: string;\n screenshot_path?: string;\n}\n\nexport interface Bug {\n id: string;\n session_id: string;\n title: string;\n description: string;\n severity: 'low' | 'medium' | 'high' | 'critical';\n status: 'open' | 'in-progress' | 'resolved' | 'closed';\n github_issue_url?: string;\n screenshot_path?: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface KanbanTicket {\n id: string;\n bug_id?: string;\n title: string;\n description: string;\n priority: 'low' | 'medium' | 'high' | 'critical';\n column: 'backlog' | 'to-do' | 'in-progress' | 'done';\n tags?: string;\n screenshot_url?: string;\n created_at: string;\n updated_at: string;\n}\n\nexport class OpenQADatabase {\n private db: Database.Database;\n\n constructor(dbPath: string = './data/openqa.db') {\n const dir = dirname(dbPath);\n mkdirSync(dir, { recursive: true });\n\n this.db = new Database(dbPath);\n this.initialize();\n }\n\n private initialize() {\n const schema = readFileSync(join(__dirname, 'schema.sql'), 'utf-8');\n this.db.exec(schema);\n }\n\n getConfig(key: string): string | null {\n const row = this.db.prepare('SELECT value FROM config WHERE key = ?').get(key) as { value: string } | undefined;\n return row?.value || null;\n }\n\n setConfig(key: string, value: string) {\n this.db.prepare('INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)').run(key, value);\n }\n\n getAllConfig(): Record<string, string> {\n const rows = this.db.prepare('SELECT key, value FROM config').all() as { key: string; value: string }[];\n return Object.fromEntries(rows.map(r => [r.key, r.value]));\n }\n\n createSession(id: string, metadata?: any): TestSession {\n this.db.prepare('INSERT INTO test_sessions (id, status, metadata) VALUES (?, ?, ?)').run(\n id,\n 'running',\n metadata ? JSON.stringify(metadata) : null\n );\n return this.getSession(id)!;\n }\n\n getSession(id: string): TestSession | null {\n return this.db.prepare('SELECT * FROM test_sessions WHERE id = ?').get(id) as TestSession | null;\n }\n\n updateSession(id: string, updates: Partial<TestSession>) {\n const fields = Object.keys(updates).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(updates), id];\n this.db.prepare(`UPDATE test_sessions SET ${fields} WHERE id = ?`).run(...values);\n }\n\n getRecentSessions(limit: number = 10): TestSession[] {\n return this.db.prepare('SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?').all(limit) as TestSession[];\n }\n\n createAction(action: Omit<Action, 'id' | 'timestamp'>): Action {\n const id = `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.db.prepare('INSERT INTO actions (id, session_id, type, description, input, output, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?)').run(\n id,\n action.session_id,\n action.type,\n action.description,\n action.input || null,\n action.output || null,\n action.screenshot_path || null\n );\n return this.db.prepare('SELECT * FROM actions WHERE id = ?').get(id) as Action;\n }\n\n getSessionActions(sessionId: string): Action[] {\n return this.db.prepare('SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC').all(sessionId) as Action[];\n }\n\n createBug(bug: Omit<Bug, 'id' | 'created_at' | 'updated_at'>): Bug {\n const id = `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.db.prepare('INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)').run(\n id,\n bug.session_id,\n bug.title,\n bug.description,\n bug.severity,\n bug.status,\n bug.github_issue_url || null,\n bug.screenshot_path || null\n );\n return this.db.prepare('SELECT * FROM bugs WHERE id = ?').get(id) as Bug;\n }\n\n updateBug(id: string, updates: Partial<Bug>) {\n const fields = Object.keys(updates).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(updates), id];\n this.db.prepare(`UPDATE bugs SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);\n }\n\n getAllBugs(): Bug[] {\n return this.db.prepare('SELECT * FROM bugs ORDER BY created_at DESC').all() as Bug[];\n }\n\n getBugsByStatus(status: Bug['status']): Bug[] {\n return this.db.prepare('SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC').all(status) as Bug[];\n }\n\n createKanbanTicket(ticket: Omit<KanbanTicket, 'id' | 'created_at' | 'updated_at'>): KanbanTicket {\n const id = `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.db.prepare('INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)').run(\n id,\n ticket.bug_id || null,\n ticket.title,\n ticket.description,\n ticket.priority,\n ticket.column,\n ticket.tags || null,\n ticket.screenshot_url || null\n );\n return this.db.prepare('SELECT * FROM kanban_tickets WHERE id = ?').get(id) as KanbanTicket;\n }\n\n updateKanbanTicket(id: string, updates: Partial<KanbanTicket>) {\n const fields = Object.keys(updates).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(updates), id];\n this.db.prepare(`UPDATE kanban_tickets SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);\n }\n\n getKanbanTickets(): KanbanTicket[] {\n return this.db.prepare('SELECT * FROM kanban_tickets ORDER BY created_at DESC').all() as KanbanTicket[];\n }\n\n getKanbanTicketsByColumn(column: KanbanTicket['column']): KanbanTicket[] {\n return this.db.prepare('SELECT * FROM kanban_tickets WHERE column = ? ORDER BY created_at DESC').all(column) as KanbanTicket[];\n }\n\n close() {\n this.db.close();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../database/index.ts"],"sourcesContent":["import { Low } from 'lowdb';\nimport { JSONFile } from 'lowdb/node';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { mkdirSync, writeFileSync, readFileSync } from 'fs';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface TestSession {\n id: string;\n started_at: string;\n ended_at?: string;\n status: 'running' | 'completed' | 'failed';\n total_actions: number;\n bugs_found: number;\n metadata?: string;\n}\n\nexport interface Action {\n id: string;\n session_id: string;\n timestamp: string;\n type: string;\n description: string;\n input?: string;\n output?: string;\n screenshot_path?: string;\n}\n\nexport interface Bug {\n id: string;\n session_id: string;\n title: string;\n description: string;\n severity: 'low' | 'medium' | 'high' | 'critical';\n status: 'open' | 'in-progress' | 'resolved' | 'closed';\n github_issue_url?: string;\n screenshot_path?: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface KanbanTicket {\n id: string;\n bug_id?: string;\n title: string;\n description: string;\n priority: 'low' | 'medium' | 'high' | 'critical';\n column: 'backlog' | 'to-do' | 'in-progress' | 'done';\n tags?: string;\n screenshot_url?: string;\n created_at: string;\n updated_at: string;\n}\n\ninterface DatabaseSchema {\n config: Record<string, string>;\n test_sessions: TestSession[];\n actions: Action[];\n bugs: Bug[];\n kanban_tickets: KanbanTicket[];\n}\n\nexport class OpenQADatabase {\n private db: Low<DatabaseSchema> | null = null;\n\n constructor(private dbPath: string = './data/openqa.json') {\n this.initialize();\n }\n\n private initialize() {\n const dir = dirname(this.dbPath);\n mkdirSync(dir, { recursive: true });\n\n const adapter = new JSONFile<DatabaseSchema>(this.dbPath);\n this.db = new Low<DatabaseSchema>(adapter, {\n config: {},\n test_sessions: [],\n actions: [],\n bugs: [],\n kanban_tickets: []\n });\n\n this.db.read();\n if (!this.db.data) {\n this.db.data = {\n config: {},\n test_sessions: [],\n actions: [],\n bugs: [],\n kanban_tickets: []\n };\n this.db.write();\n }\n }\n\n private async ensureInitialized() {\n if (!this.db) {\n this.initialize();\n }\n await this.db!.read();\n }\n\n async getConfig(key: string): Promise<string | null> {\n await this.ensureInitialized();\n return this.db!.data.config[key] || null;\n }\n\n async setConfig(key: string, value: string) {\n await this.ensureInitialized();\n this.db!.data.config[key] = value;\n await this.db!.write();\n }\n\n async getAllConfig(): Promise<Record<string, string>> {\n await this.ensureInitialized();\n return this.db!.data.config;\n }\n\n async createSession(id: string, metadata?: any): Promise<TestSession> {\n await this.ensureInitialized();\n const session: TestSession = {\n id,\n started_at: new Date().toISOString(),\n status: 'running',\n total_actions: 0,\n bugs_found: 0,\n metadata: metadata ? JSON.stringify(metadata) : undefined\n };\n this.db!.data.test_sessions.push(session);\n await this.db!.write();\n return session;\n }\n\n async getSession(id: string): Promise<TestSession | null> {\n await this.ensureInitialized();\n return this.db!.data.test_sessions.find(s => s.id === id) || null;\n }\n\n async updateSession(id: string, updates: Partial<TestSession>) {\n await this.ensureInitialized();\n const index = this.db!.data.test_sessions.findIndex(s => s.id === id);\n if (index !== -1) {\n this.db!.data.test_sessions[index] = { ...this.db!.data.test_sessions[index], ...updates };\n await this.db!.write();\n }\n }\n\n async getRecentSessions(limit: number = 10): Promise<TestSession[]> {\n await this.ensureInitialized();\n return this.db!.data.test_sessions\n .sort((a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime())\n .slice(0, limit);\n }\n\n async createAction(action: Omit<Action, 'id' | 'timestamp'>): Promise<Action> {\n await this.ensureInitialized();\n const newAction: Action = {\n id: `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n timestamp: new Date().toISOString(),\n ...action\n };\n this.db!.data.actions.push(newAction);\n await this.db!.write();\n return newAction;\n }\n\n async getSessionActions(sessionId: string): Promise<Action[]> {\n await this.ensureInitialized();\n return this.db!.data.actions\n .filter(a => a.session_id === sessionId)\n .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n }\n\n async createBug(bug: Omit<Bug, 'id' | 'created_at' | 'updated_at'>): Promise<Bug> {\n await this.ensureInitialized();\n const newBug: Bug = {\n id: `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...bug\n };\n this.db!.data.bugs.push(newBug);\n await this.db!.write();\n return newBug;\n }\n\n async updateBug(id: string, updates: Partial<Bug>) {\n await this.ensureInitialized();\n const index = this.db!.data.bugs.findIndex(b => b.id === id);\n if (index !== -1) {\n this.db!.data.bugs[index] = { \n ...this.db!.data.bugs[index], \n ...updates, \n updated_at: new Date().toISOString() \n };\n await this.db!.write();\n }\n }\n\n async getAllBugs(): Promise<Bug[]> {\n await this.ensureInitialized();\n return this.db!.data.bugs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async getBugsByStatus(status: Bug['status']): Promise<Bug[]> {\n await this.ensureInitialized();\n return this.db!.data.bugs\n .filter(b => b.status === status)\n .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async createKanbanTicket(ticket: Omit<KanbanTicket, 'id' | 'created_at' | 'updated_at'>): Promise<KanbanTicket> {\n await this.ensureInitialized();\n const newTicket: KanbanTicket = {\n id: `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...ticket\n };\n this.db!.data.kanban_tickets.push(newTicket);\n await this.db!.write();\n return newTicket;\n }\n\n async updateKanbanTicket(id: string, updates: Partial<KanbanTicket>) {\n await this.ensureInitialized();\n const index = this.db!.data.kanban_tickets.findIndex(t => t.id === id);\n if (index !== -1) {\n this.db!.data.kanban_tickets[index] = { \n ...this.db!.data.kanban_tickets[index], \n ...updates, \n updated_at: new Date().toISOString() \n };\n await this.db!.write();\n }\n }\n\n async getKanbanTickets(): Promise<KanbanTicket[]> {\n await this.ensureInitialized();\n return this.db!.data.kanban_tickets.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async getKanbanTicketsByColumn(column: KanbanTicket['column']): Promise<KanbanTicket[]> {\n await this.ensureInitialized();\n return this.db!.data.kanban_tickets\n .filter(t => t.column === column)\n .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async close() {\n // LowDB doesn't need explicit closing\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openqa/cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Autonomous QA testing agent powered by Orka.js",
5
5
  "type": "module",
6
6
  "main": "./dist/cli/index.js",
@@ -52,7 +52,7 @@
52
52
  "@orka-js/memory-store": "^1.0.0",
53
53
  "@orka-js/observability": "^1.0.0",
54
54
  "@orka-js/openai": "^1.0.0",
55
- "better-sqlite3": "^12.8.0",
55
+ "lowdb": "^6.1.0",
56
56
  "chalk": "^5.3.0",
57
57
  "commander": "^11.1.0",
58
58
  "dotenv": "^16.3.1",
@@ -62,7 +62,6 @@
62
62
  "ws": "^8.16.0"
63
63
  },
64
64
  "devDependencies": {
65
- "@types/better-sqlite3": "^7.6.8",
66
65
  "@types/express": "^4.17.21",
67
66
  "@types/node": "^20.10.6",
68
67
  "@types/ws": "^8.5.10",