@ycniuqton/devlens 0.1.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 (61) hide show
  1. package/README.md +164 -0
  2. package/bin/devlens.js +2 -0
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +205 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/init.d.ts +3 -0
  7. package/dist/init.js +239 -0
  8. package/dist/init.js.map +1 -0
  9. package/dist/routes/diff.d.ts +1 -0
  10. package/dist/routes/diff.js +39 -0
  11. package/dist/routes/diff.js.map +1 -0
  12. package/dist/routes/integrations.d.ts +1 -0
  13. package/dist/routes/integrations.js +132 -0
  14. package/dist/routes/integrations.js.map +1 -0
  15. package/dist/routes/rules.d.ts +1 -0
  16. package/dist/routes/rules.js +115 -0
  17. package/dist/routes/rules.js.map +1 -0
  18. package/dist/routes/tasks.d.ts +4 -0
  19. package/dist/routes/tasks.js +360 -0
  20. package/dist/routes/tasks.js.map +1 -0
  21. package/dist/server.d.ts +7 -0
  22. package/dist/server.js +112 -0
  23. package/dist/server.js.map +1 -0
  24. package/dist/services/claudeTasks.d.ts +23 -0
  25. package/dist/services/claudeTasks.js +160 -0
  26. package/dist/services/claudeTasks.js.map +1 -0
  27. package/dist/services/config.d.ts +3 -0
  28. package/dist/services/config.js +25 -0
  29. package/dist/services/config.js.map +1 -0
  30. package/dist/services/git.d.ts +8 -0
  31. package/dist/services/git.js +90 -0
  32. package/dist/services/git.js.map +1 -0
  33. package/dist/services/jira.d.ts +11 -0
  34. package/dist/services/jira.js +52 -0
  35. package/dist/services/jira.js.map +1 -0
  36. package/dist/services/linear.d.ts +9 -0
  37. package/dist/services/linear.js +69 -0
  38. package/dist/services/linear.js.map +1 -0
  39. package/dist/services/rules.d.ts +14 -0
  40. package/dist/services/rules.js +133 -0
  41. package/dist/services/rules.js.map +1 -0
  42. package/dist/services/taskStore.d.ts +27 -0
  43. package/dist/services/taskStore.js +261 -0
  44. package/dist/services/taskStore.js.map +1 -0
  45. package/dist/services/tunnel.d.ts +8 -0
  46. package/dist/services/tunnel.js +152 -0
  47. package/dist/services/tunnel.js.map +1 -0
  48. package/dist/services/watcher.d.ts +2 -0
  49. package/dist/services/watcher.js +30 -0
  50. package/dist/services/watcher.js.map +1 -0
  51. package/dist/types/index.d.ts +87 -0
  52. package/dist/types/index.js +3 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/package.json +53 -0
  55. package/public/css/style.css +1613 -0
  56. package/public/index.html +395 -0
  57. package/public/js/app.js +104 -0
  58. package/public/js/diff.js +337 -0
  59. package/public/js/integrations.js +194 -0
  60. package/public/js/rules.js +174 -0
  61. package/public/js/tasks.js +301 -0
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.diffRouter = void 0;
4
+ const express_1 = require("express");
5
+ exports.diffRouter = (0, express_1.Router)();
6
+ exports.diffRouter.get('/diff', async (req, res) => {
7
+ const gitService = req.app.locals.gitService;
8
+ try {
9
+ const filter = req.query.filter;
10
+ const diff = await gitService.getDiff(filter);
11
+ const files = await gitService.getStatus();
12
+ res.json({ diff, files });
13
+ }
14
+ catch (err) {
15
+ res.status(500).json({ error: err.message });
16
+ }
17
+ });
18
+ exports.diffRouter.get('/status', async (req, res) => {
19
+ const gitService = req.app.locals.gitService;
20
+ try {
21
+ const status = await gitService.getStatus();
22
+ res.json(status);
23
+ }
24
+ catch (err) {
25
+ res.status(500).json({ error: err.message });
26
+ }
27
+ });
28
+ exports.diffRouter.get('/log', async (req, res) => {
29
+ const gitService = req.app.locals.gitService;
30
+ try {
31
+ const limit = parseInt(req.query.limit) || 20;
32
+ const log = await gitService.getLog(limit);
33
+ res.json(log);
34
+ }
35
+ catch (err) {
36
+ res.status(500).json({ error: err.message });
37
+ }
38
+ });
39
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/routes/diff.ts"],"names":[],"mappings":";;;AAAA,qCAAoD;AAGvC,QAAA,UAAU,GAAG,IAAA,gBAAM,GAAE,CAAC;AAEnC,kBAAU,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;IAC5D,MAAM,UAAU,GAAe,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,MAA4B,CAAC;QACtD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;QAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,kBAAU,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;IAC9D,MAAM,UAAU,GAAe,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;QAC5C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,kBAAU,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;IAC3D,MAAM,UAAU,GAAe,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAe,CAAC,IAAI,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3C,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const integrationsRouter: import("express-serve-static-core").Router;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.integrationsRouter = void 0;
4
+ const express_1 = require("express");
5
+ const config_1 = require("../services/config");
6
+ const jira_1 = require("../services/jira");
7
+ const linear_1 = require("../services/linear");
8
+ const tunnel_1 = require("../services/tunnel");
9
+ exports.integrationsRouter = (0, express_1.Router)();
10
+ // Simple in-memory cache
11
+ const cache = new Map();
12
+ const CACHE_TTL = 60000; // 60 seconds
13
+ function getCached(key) {
14
+ const entry = cache.get(key);
15
+ if (entry && Date.now() - entry.timestamp < CACHE_TTL) {
16
+ return entry.data;
17
+ }
18
+ return null;
19
+ }
20
+ function setCache(key, data) {
21
+ cache.set(key, { data, timestamp: Date.now() });
22
+ }
23
+ exports.integrationsRouter.get('/status', (req, res) => {
24
+ const config = (0, config_1.loadConfig)(req.app.locals.projectDir);
25
+ res.json({
26
+ jira: !!(config.jira?.baseUrl && config.jira?.apiToken),
27
+ linear: !!config.linear?.apiKey,
28
+ tunnel: (0, tunnel_1.getTunnelStatus)(),
29
+ });
30
+ });
31
+ // Tunnel endpoints
32
+ exports.integrationsRouter.get('/tunnel/status', (_req, res) => {
33
+ res.json((0, tunnel_1.getTunnelStatus)());
34
+ });
35
+ exports.integrationsRouter.post('/tunnel/start', async (req, res) => {
36
+ const { provider } = req.body;
37
+ const port = req.app.locals.port || 5157;
38
+ try {
39
+ const url = await (0, tunnel_1.startTunnel)(port, provider || 'cloudflare');
40
+ res.json({ ok: true, url, provider: provider || 'cloudflare' });
41
+ }
42
+ catch (err) {
43
+ res.status(500).json({ error: err.message });
44
+ }
45
+ });
46
+ exports.integrationsRouter.post('/tunnel/stop', (_req, res) => {
47
+ (0, tunnel_1.stopTunnel)();
48
+ res.json({ ok: true });
49
+ });
50
+ exports.integrationsRouter.get('/jira/issues', async (req, res) => {
51
+ try {
52
+ const cached = getCached('jira');
53
+ if (cached)
54
+ return res.json(cached);
55
+ const config = (0, config_1.loadConfig)(req.app.locals.projectDir);
56
+ if (!config.jira)
57
+ return res.status(400).json({ error: 'Jira not configured' });
58
+ const client = (0, jira_1.createJiraClient)(config.jira);
59
+ const issues = await client.getIssues();
60
+ setCache('jira', issues);
61
+ res.json(issues);
62
+ }
63
+ catch (err) {
64
+ res.status(500).json({ error: err.message });
65
+ }
66
+ });
67
+ exports.integrationsRouter.get('/linear/issues', async (req, res) => {
68
+ try {
69
+ const cached = getCached('linear');
70
+ if (cached)
71
+ return res.json(cached);
72
+ const config = (0, config_1.loadConfig)(req.app.locals.projectDir);
73
+ if (!config.linear)
74
+ return res.status(400).json({ error: 'Linear not configured' });
75
+ const client = (0, linear_1.createLinearClient)(config.linear);
76
+ const issues = await client.getIssues();
77
+ setCache('linear', issues);
78
+ res.json(issues);
79
+ }
80
+ catch (err) {
81
+ res.status(500).json({ error: err.message });
82
+ }
83
+ });
84
+ exports.integrationsRouter.get('/all', async (req, res) => {
85
+ const config = (0, config_1.loadConfig)(req.app.locals.projectDir);
86
+ const results = [];
87
+ try {
88
+ if (config.jira?.baseUrl && config.jira?.apiToken) {
89
+ const cached = getCached('jira');
90
+ if (cached) {
91
+ results.push(...cached);
92
+ }
93
+ else {
94
+ const client = (0, jira_1.createJiraClient)(config.jira);
95
+ const issues = await client.getIssues();
96
+ setCache('jira', issues);
97
+ results.push(...issues);
98
+ }
99
+ }
100
+ }
101
+ catch { /* skip failed integration */ }
102
+ try {
103
+ if (config.linear?.apiKey) {
104
+ const cached = getCached('linear');
105
+ if (cached) {
106
+ results.push(...cached);
107
+ }
108
+ else {
109
+ const client = (0, linear_1.createLinearClient)(config.linear);
110
+ const issues = await client.getIssues();
111
+ setCache('linear', issues);
112
+ results.push(...issues);
113
+ }
114
+ }
115
+ }
116
+ catch { /* skip failed integration */ }
117
+ res.json(results);
118
+ });
119
+ exports.integrationsRouter.post('/config', (req, res) => {
120
+ try {
121
+ const projectDir = req.app.locals.projectDir;
122
+ const existing = (0, config_1.loadConfig)(projectDir);
123
+ const updated = { ...existing, ...req.body };
124
+ (0, config_1.saveConfig)(projectDir, updated);
125
+ cache.clear();
126
+ res.json({ ok: true });
127
+ }
128
+ catch (err) {
129
+ res.status(500).json({ error: err.message });
130
+ }
131
+ });
132
+ //# sourceMappingURL=integrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../src/routes/integrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const rulesRouter: import("express-serve-static-core").Router;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.rulesRouter = void 0;
7
+ const express_1 = require("express");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ exports.rulesRouter = (0, express_1.Router)();
11
+ // GET /api/rules — list all rules
12
+ exports.rulesRouter.get('/', (req, res) => {
13
+ const rules = req.app.locals.rulesService;
14
+ res.json(rules.getRules());
15
+ });
16
+ // POST /api/rules — add a new rule
17
+ exports.rulesRouter.post('/', (req, res) => {
18
+ const rules = req.app.locals.rulesService;
19
+ const broadcast = req.app.locals.broadcast;
20
+ const { content } = req.body;
21
+ if (!content || typeof content !== 'string') {
22
+ return res.status(400).json({ error: 'content is required' });
23
+ }
24
+ const rule = rules.addRule(content);
25
+ if (broadcast)
26
+ broadcast({ type: 'rules-update', payload: { rules: rules.getRules() } });
27
+ res.status(201).json(rule);
28
+ });
29
+ // DELETE /api/rules/:index — remove a rule
30
+ exports.rulesRouter.delete('/:index', (req, res) => {
31
+ const rules = req.app.locals.rulesService;
32
+ const broadcast = req.app.locals.broadcast;
33
+ const index = parseInt(req.params.index, 10);
34
+ if (isNaN(index))
35
+ return res.status(400).json({ error: 'invalid index' });
36
+ const ok = rules.removeRule(index);
37
+ if (!ok)
38
+ return res.status(403).json({ error: 'cannot delete protected rule or invalid index' });
39
+ if (broadcast)
40
+ broadcast({ type: 'rules-update', payload: { rules: rules.getRules() } });
41
+ res.json({ ok: true });
42
+ });
43
+ // PATCH /api/rules/:index/toggle — toggle active/inactive
44
+ exports.rulesRouter.patch('/:index/toggle', (req, res) => {
45
+ const rules = req.app.locals.rulesService;
46
+ const broadcast = req.app.locals.broadcast;
47
+ const index = parseInt(req.params.index, 10);
48
+ if (isNaN(index))
49
+ return res.status(400).json({ error: 'invalid index' });
50
+ const rule = rules.toggleRule(index);
51
+ if (!rule)
52
+ return res.status(404).json({ error: 'rule not found' });
53
+ if (broadcast)
54
+ broadcast({ type: 'rules-update', payload: { rules: rules.getRules() } });
55
+ res.json(rule);
56
+ });
57
+ // ============================================================
58
+ // Commit Approval
59
+ // ============================================================
60
+ function getApprovalFile(projectDir) {
61
+ return path_1.default.join(projectDir, '.devlens', 'commit-approved.md');
62
+ }
63
+ function getPendingFile(projectDir) {
64
+ return path_1.default.join(projectDir, '.devlens', 'commit-pending.md');
65
+ }
66
+ // GET /api/commit-approval/status — check pending + approved state
67
+ exports.rulesRouter.get('/commit-approval/status', (req, res) => {
68
+ const projectDir = req.app.locals.projectDir;
69
+ const pendingFile = getPendingFile(projectDir);
70
+ const approvedFile = getApprovalFile(projectDir);
71
+ let pending = null;
72
+ let approved = false;
73
+ let approvedAt = null;
74
+ if (fs_1.default.existsSync(pendingFile)) {
75
+ pending = fs_1.default.readFileSync(pendingFile, 'utf-8').trim();
76
+ }
77
+ if (fs_1.default.existsSync(approvedFile)) {
78
+ approved = true;
79
+ const content = fs_1.default.readFileSync(approvedFile, 'utf-8');
80
+ const match = content.match(/timestamp:\s*(.+)/);
81
+ if (match)
82
+ approvedAt = match[1].trim();
83
+ }
84
+ res.json({ pending, approved, approvedAt });
85
+ });
86
+ // POST /api/commit-approval/approve — user approves the pending commit
87
+ exports.rulesRouter.post('/commit-approval/approve', (req, res) => {
88
+ const projectDir = req.app.locals.projectDir;
89
+ const broadcast = req.app.locals.broadcast;
90
+ const pendingFile = getPendingFile(projectDir);
91
+ const approvedFile = getApprovalFile(projectDir);
92
+ if (!fs_1.default.existsSync(pendingFile)) {
93
+ return res.status(400).json({ error: 'no pending commit to approve' });
94
+ }
95
+ const message = fs_1.default.readFileSync(pendingFile, 'utf-8').trim();
96
+ const timestamp = new Date().toISOString();
97
+ const content = `# Commit Approved\n\ntimestamp: ${timestamp}\n\nmessage:\n${message}\n`;
98
+ fs_1.default.writeFileSync(approvedFile, content);
99
+ fs_1.default.unlinkSync(pendingFile);
100
+ if (broadcast)
101
+ broadcast({ type: 'commit-approval-update', payload: { pending: null, approved: true, approvedAt: timestamp } });
102
+ res.json({ ok: true, approvedAt: timestamp });
103
+ });
104
+ // POST /api/commit-approval/reject — user rejects the pending commit
105
+ exports.rulesRouter.post('/commit-approval/reject', (req, res) => {
106
+ const projectDir = req.app.locals.projectDir;
107
+ const broadcast = req.app.locals.broadcast;
108
+ const pendingFile = getPendingFile(projectDir);
109
+ if (fs_1.default.existsSync(pendingFile))
110
+ fs_1.default.unlinkSync(pendingFile);
111
+ if (broadcast)
112
+ broadcast({ type: 'commit-approval-update', payload: { pending: null, approved: false } });
113
+ res.json({ ok: true });
114
+ });
115
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/routes/rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { TaskStoreService } from '../services/taskStore';
2
+ export declare const tasksRouter: import("express-serve-static-core").Router;
3
+ declare function checkSessionLiveness(store: TaskStoreService): void;
4
+ export { checkSessionLiveness };