resolve-solo 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.
- package/README.md +199 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +214 -0
- package/dist/cli.js.map +1 -0
- package/dist/demo-generator.d.ts +12 -0
- package/dist/demo-generator.d.ts.map +1 -0
- package/dist/demo-generator.js +352 -0
- package/dist/demo-generator.js.map +1 -0
- package/dist/demo-output.d.ts +13 -0
- package/dist/demo-output.d.ts.map +1 -0
- package/dist/demo-output.js +116 -0
- package/dist/demo-output.js.map +1 -0
- package/dist/demo-schema.d.ts +66 -0
- package/dist/demo-schema.d.ts.map +1 -0
- package/dist/demo-schema.js +11 -0
- package/dist/demo-schema.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/investigation-types.d.ts +47 -0
- package/dist/investigation-types.d.ts.map +1 -0
- package/dist/investigation-types.js +5 -0
- package/dist/investigation-types.js.map +1 -0
- package/dist/investigation.d.ts +24 -0
- package/dist/investigation.d.ts.map +1 -0
- package/dist/investigation.js +135 -0
- package/dist/investigation.js.map +1 -0
- package/dist/output.d.ts +20 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +151 -0
- package/dist/output.js.map +1 -0
- package/dist/parser.d.ts +16 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +146 -0
- package/dist/parser.js.map +1 -0
- package/dist/storage.d.ts +47 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +133 -0
- package/dist/storage.js.map +1 -0
- package/dist/timeline.d.ts +27 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +145 -0
- package/dist/timeline.js.map +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
package/dist/storage.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage utilities for local data persistence
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
/**
|
|
7
|
+
* Get the .resolveai directory path (project-local)
|
|
8
|
+
*/
|
|
9
|
+
export function getResolveaiDir() {
|
|
10
|
+
return path.join(process.cwd(), '.resolveai');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the demo data directory path
|
|
14
|
+
*/
|
|
15
|
+
export function getDemoDataDir() {
|
|
16
|
+
return path.join(getResolveaiDir(), 'demo-data');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Ensure a directory exists (create if missing)
|
|
20
|
+
*/
|
|
21
|
+
export function ensureDir(dirPath) {
|
|
22
|
+
if (!fs.existsSync(dirPath)) {
|
|
23
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if demo data exists
|
|
28
|
+
*/
|
|
29
|
+
export function demoDataExists() {
|
|
30
|
+
const demoDir = getDemoDataDir();
|
|
31
|
+
if (!fs.existsSync(demoDir)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Check for required files
|
|
35
|
+
const requiredFiles = [
|
|
36
|
+
'services.json',
|
|
37
|
+
'deploys.json',
|
|
38
|
+
'logs.json',
|
|
39
|
+
'incidents.json',
|
|
40
|
+
'metadata.json',
|
|
41
|
+
];
|
|
42
|
+
return requiredFiles.every((file) => fs.existsSync(path.join(demoDir, file)));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Save demo dataset to disk
|
|
46
|
+
*/
|
|
47
|
+
export function saveDemoData(dataset) {
|
|
48
|
+
const demoDir = getDemoDataDir();
|
|
49
|
+
ensureDir(demoDir);
|
|
50
|
+
// Write each data type to separate file for easier inspection
|
|
51
|
+
fs.writeFileSync(path.join(demoDir, 'services.json'), JSON.stringify(dataset.services, null, 2));
|
|
52
|
+
fs.writeFileSync(path.join(demoDir, 'deploys.json'), JSON.stringify(dataset.deploys, null, 2));
|
|
53
|
+
fs.writeFileSync(path.join(demoDir, 'logs.json'), JSON.stringify(dataset.logs, null, 2));
|
|
54
|
+
fs.writeFileSync(path.join(demoDir, 'incidents.json'), JSON.stringify(dataset.incidents, null, 2));
|
|
55
|
+
fs.writeFileSync(path.join(demoDir, 'metadata.json'), JSON.stringify(dataset.metadata, null, 2));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Load demo dataset from disk
|
|
59
|
+
*/
|
|
60
|
+
export function loadDemoData() {
|
|
61
|
+
if (!demoDataExists()) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const demoDir = getDemoDataDir();
|
|
65
|
+
try {
|
|
66
|
+
const services = JSON.parse(fs.readFileSync(path.join(demoDir, 'services.json'), 'utf-8'));
|
|
67
|
+
const deploys = JSON.parse(fs.readFileSync(path.join(demoDir, 'deploys.json'), 'utf-8'));
|
|
68
|
+
const logs = JSON.parse(fs.readFileSync(path.join(demoDir, 'logs.json'), 'utf-8'));
|
|
69
|
+
const incidents = JSON.parse(fs.readFileSync(path.join(demoDir, 'incidents.json'), 'utf-8'));
|
|
70
|
+
const metadata = JSON.parse(fs.readFileSync(path.join(demoDir, 'metadata.json'), 'utf-8'));
|
|
71
|
+
return {
|
|
72
|
+
services,
|
|
73
|
+
deploys,
|
|
74
|
+
logs,
|
|
75
|
+
incidents,
|
|
76
|
+
metadata,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error('Failed to load demo data:', error);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Delete all demo data
|
|
86
|
+
*/
|
|
87
|
+
export function deleteDemoData() {
|
|
88
|
+
const demoDir = getDemoDataDir();
|
|
89
|
+
if (fs.existsSync(demoDir)) {
|
|
90
|
+
fs.rmSync(demoDir, { recursive: true, force: true });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get storage info (sizes, counts)
|
|
95
|
+
*/
|
|
96
|
+
export function getStorageInfo() {
|
|
97
|
+
const demoDir = getDemoDataDir();
|
|
98
|
+
const exists = demoDataExists();
|
|
99
|
+
if (!exists) {
|
|
100
|
+
return { exists: false, path: demoDir };
|
|
101
|
+
}
|
|
102
|
+
const dataset = loadDemoData();
|
|
103
|
+
if (!dataset) {
|
|
104
|
+
return { exists: false, path: demoDir };
|
|
105
|
+
}
|
|
106
|
+
// Calculate total size
|
|
107
|
+
const files = [
|
|
108
|
+
'services.json',
|
|
109
|
+
'deploys.json',
|
|
110
|
+
'logs.json',
|
|
111
|
+
'incidents.json',
|
|
112
|
+
'metadata.json',
|
|
113
|
+
];
|
|
114
|
+
let totalSize = 0;
|
|
115
|
+
for (const file of files) {
|
|
116
|
+
const filePath = path.join(demoDir, file);
|
|
117
|
+
if (fs.existsSync(filePath)) {
|
|
118
|
+
totalSize += fs.statSync(filePath).size;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
exists: true,
|
|
123
|
+
path: demoDir,
|
|
124
|
+
size: totalSize,
|
|
125
|
+
counts: {
|
|
126
|
+
services: dataset.services.length,
|
|
127
|
+
deploys: dataset.deploys.length,
|
|
128
|
+
logs: dataset.logs.length,
|
|
129
|
+
incidents: dataset.incidents.length,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeline builder for investigation
|
|
3
|
+
*
|
|
4
|
+
* Merges deploys, logs, and incidents into a unified timeline.
|
|
5
|
+
*/
|
|
6
|
+
import type { DemoDataset } from './demo-schema.js';
|
|
7
|
+
import type { TimelineItem } from './investigation-types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Build a timeline from demo dataset
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildTimeline(dataset: DemoDataset, options?: {
|
|
12
|
+
hoursAgo?: number;
|
|
13
|
+
maxItems?: number;
|
|
14
|
+
relevantServices?: string[];
|
|
15
|
+
baseDate?: Date;
|
|
16
|
+
}): TimelineItem[];
|
|
17
|
+
/**
|
|
18
|
+
* Get services affected in timeline
|
|
19
|
+
*/
|
|
20
|
+
export declare function getAffectedServices(timeline: TimelineItem[]): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Deduplicate timeline items (e.g., multiple errors from same service)
|
|
23
|
+
*/
|
|
24
|
+
export declare function deduplicateTimeline(timeline: TimelineItem[], options?: {
|
|
25
|
+
maxPerService?: number;
|
|
26
|
+
}): TimelineItem[];
|
|
27
|
+
//# sourceMappingURL=timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,0BAA0B,CAAC;AAEzE;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,IAAI,CAAC;CACZ,GACL,YAAY,EAAE,CAuHhB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,CAMtE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,YAAY,EAAE,CAuBhB"}
|
package/dist/timeline.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeline builder for investigation
|
|
3
|
+
*
|
|
4
|
+
* Merges deploys, logs, and incidents into a unified timeline.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Build a timeline from demo dataset
|
|
8
|
+
*/
|
|
9
|
+
export function buildTimeline(dataset, options = {}) {
|
|
10
|
+
const { hoursAgo = 24, maxItems = 15, relevantServices, baseDate } = options;
|
|
11
|
+
const now = baseDate || new Date();
|
|
12
|
+
const cutoffTime = new Date(now.getTime() - hoursAgo * 60 * 60 * 1000);
|
|
13
|
+
const items = [];
|
|
14
|
+
// Add deploys
|
|
15
|
+
for (const deploy of dataset.deploys) {
|
|
16
|
+
const deployTime = new Date(deploy.timestamp);
|
|
17
|
+
if (deployTime < cutoffTime)
|
|
18
|
+
continue;
|
|
19
|
+
// Filter by relevant services if specified
|
|
20
|
+
if (relevantServices && !relevantServices.includes(deploy.service)) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const service = dataset.services.find((s) => s.id === deploy.service);
|
|
24
|
+
const serviceName = service?.displayName || deploy.service;
|
|
25
|
+
items.push({
|
|
26
|
+
id: deploy.id,
|
|
27
|
+
timestamp: deploy.timestamp,
|
|
28
|
+
signal: 'deploy',
|
|
29
|
+
target: serviceName,
|
|
30
|
+
summary: `Deploy ${deploy.version} to ${serviceName}`,
|
|
31
|
+
whyItMatters: deploy.status === 'failed'
|
|
32
|
+
? 'Failed deploy could cause downstream issues'
|
|
33
|
+
: deploy.status === 'rolled_back'
|
|
34
|
+
? 'Rollback indicates problems with this version'
|
|
35
|
+
: 'New code deployed, potential source of change',
|
|
36
|
+
confidence: deploy.status === 'failed' ? 'high' : 'medium',
|
|
37
|
+
details: {
|
|
38
|
+
version: deploy.version,
|
|
39
|
+
deployer: deploy.deployer,
|
|
40
|
+
commitMessage: deploy.commitMessage,
|
|
41
|
+
status: deploy.status,
|
|
42
|
+
},
|
|
43
|
+
isDemo: true,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// Add error logs (high signal)
|
|
47
|
+
for (const log of dataset.logs) {
|
|
48
|
+
const logTime = new Date(log.timestamp);
|
|
49
|
+
if (logTime < cutoffTime)
|
|
50
|
+
continue;
|
|
51
|
+
if (log.level !== 'error')
|
|
52
|
+
continue; // Only errors in timeline
|
|
53
|
+
// Filter by relevant services if specified
|
|
54
|
+
if (relevantServices && !relevantServices.includes(log.service)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const service = dataset.services.find((s) => s.id === log.service);
|
|
58
|
+
const serviceName = service?.displayName || log.service;
|
|
59
|
+
items.push({
|
|
60
|
+
id: log.id,
|
|
61
|
+
timestamp: log.timestamp,
|
|
62
|
+
signal: 'log',
|
|
63
|
+
target: serviceName,
|
|
64
|
+
summary: `Error: ${log.message}`,
|
|
65
|
+
whyItMatters: 'Error log indicates potential failure point',
|
|
66
|
+
confidence: 'high',
|
|
67
|
+
details: {
|
|
68
|
+
level: log.level,
|
|
69
|
+
message: log.message,
|
|
70
|
+
metadata: log.metadata,
|
|
71
|
+
},
|
|
72
|
+
isDemo: true,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// Add recent incidents (for context)
|
|
76
|
+
for (const incident of dataset.incidents) {
|
|
77
|
+
const incidentTime = new Date(incident.createdAt);
|
|
78
|
+
// Include incidents from last 30 days for recall context
|
|
79
|
+
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
80
|
+
if (incidentTime < thirtyDaysAgo)
|
|
81
|
+
continue;
|
|
82
|
+
// Check if any relevant services are affected
|
|
83
|
+
if (relevantServices) {
|
|
84
|
+
const hasOverlap = incident.affectedServices.some((s) => relevantServices.includes(s));
|
|
85
|
+
if (!hasOverlap)
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
items.push({
|
|
89
|
+
id: incident.id,
|
|
90
|
+
timestamp: incident.createdAt,
|
|
91
|
+
signal: 'incident',
|
|
92
|
+
target: incident.affectedServices
|
|
93
|
+
.map((sid) => dataset.services.find((s) => s.id === sid)?.displayName || sid)
|
|
94
|
+
.join(', '),
|
|
95
|
+
summary: `Past incident: ${incident.title}`,
|
|
96
|
+
whyItMatters: 'Similar past incident, check for patterns',
|
|
97
|
+
confidence: 'medium',
|
|
98
|
+
details: {
|
|
99
|
+
severity: incident.severity,
|
|
100
|
+
symptoms: incident.symptoms,
|
|
101
|
+
resolution: incident.resolution,
|
|
102
|
+
timeToResolve: incident.timeToResolveMinutes,
|
|
103
|
+
},
|
|
104
|
+
isDemo: true,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// Sort by timestamp (most recent first)
|
|
108
|
+
items.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
109
|
+
// Limit to maxItems
|
|
110
|
+
return items.slice(0, maxItems);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get services affected in timeline
|
|
114
|
+
*/
|
|
115
|
+
export function getAffectedServices(timeline) {
|
|
116
|
+
const services = new Set();
|
|
117
|
+
for (const item of timeline) {
|
|
118
|
+
services.add(item.target);
|
|
119
|
+
}
|
|
120
|
+
return Array.from(services);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Deduplicate timeline items (e.g., multiple errors from same service)
|
|
124
|
+
*/
|
|
125
|
+
export function deduplicateTimeline(timeline, options = {}) {
|
|
126
|
+
const { maxPerService = 3 } = options;
|
|
127
|
+
const serviceCount = new Map();
|
|
128
|
+
const result = [];
|
|
129
|
+
for (const item of timeline) {
|
|
130
|
+
const count = serviceCount.get(item.target) || 0;
|
|
131
|
+
// Keep high-confidence items regardless
|
|
132
|
+
if (item.confidence === 'high') {
|
|
133
|
+
result.push(item);
|
|
134
|
+
serviceCount.set(item.target, count + 1);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// Limit medium/low confidence items per service
|
|
138
|
+
if (count < maxPerService) {
|
|
139
|
+
result.push(item);
|
|
140
|
+
serviceCount.set(item.target, count + 1);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for Resolve Solo
|
|
3
|
+
*/
|
|
4
|
+
export type Intent = 'help' | 'demo' | 'demo-seed' | 'demo-reset' | 'investigate' | 'details' | 'note' | 'close' | 'report-weekly' | 'doctor' | 'uninstall' | 'unknown';
|
|
5
|
+
export interface ParsedCommand {
|
|
6
|
+
intent: Intent;
|
|
7
|
+
args: string[];
|
|
8
|
+
raw: string;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,MAAM,GACd,MAAM,GACN,MAAM,GACN,WAAW,GACX,YAAY,GACZ,aAAa,GACb,SAAS,GACT,MAAM,GACN,OAAO,GACP,eAAe,GACf,QAAQ,GACR,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "resolve-solo",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Local-first CLI on-call assistant for individual engineers",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"resolveai": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev": "tsx src/cli.ts",
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest",
|
|
15
|
+
"test:coverage": "vitest run --coverage",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"oncall",
|
|
21
|
+
"incident-response",
|
|
22
|
+
"investigation",
|
|
23
|
+
"cli",
|
|
24
|
+
"devtools"
|
|
25
|
+
],
|
|
26
|
+
"author": "Resolve.ai",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.cbhq.net/srinath-sinha/resolve-solo.git"
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.cbhq.net/srinath-sinha/resolve-solo/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.cbhq.net/srinath-sinha/resolve-solo#readme",
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"chalk": "^5.3.0",
|
|
45
|
+
"commander": "^12.1.0"
|
|
46
|
+
},
|
|
47
|
+
"optionalDependencies": {
|
|
48
|
+
"better-sqlite3": "^11.7.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
52
|
+
"@types/node": "^20.17.10",
|
|
53
|
+
"tsx": "^4.19.2",
|
|
54
|
+
"typescript": "^5.7.3",
|
|
55
|
+
"vitest": "^2.1.8"
|
|
56
|
+
}
|
|
57
|
+
}
|