ownkey 1.0.0 → 1.0.2
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/LICENSE +21 -21
- package/README.md +256 -81
- package/dist/ai/factory.js +2 -2
- package/dist/ai/factory.js.map +1 -1
- package/dist/ai/gemini.d.ts.map +1 -1
- package/dist/ai/gemini.js +13 -3
- package/dist/ai/gemini.js.map +1 -1
- package/dist/ai/ollama.d.ts +0 -2
- package/dist/ai/ollama.d.ts.map +1 -1
- package/dist/ai/ollama.js +20 -93
- package/dist/ai/ollama.js.map +1 -1
- package/dist/ai/openai.d.ts +4 -1
- package/dist/ai/openai.d.ts.map +1 -1
- package/dist/ai/openai.js +7 -3
- package/dist/ai/openai.js.map +1 -1
- package/dist/ai/provider.d.ts +4 -0
- package/dist/ai/provider.d.ts.map +1 -1
- package/dist/ai/provider.js +80 -47
- package/dist/ai/provider.js.map +1 -1
- package/dist/commands/apply.d.ts.map +1 -1
- package/dist/commands/apply.js +82 -47
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +249 -101
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/suggest.d.ts.map +1 -1
- package/dist/commands/suggest.js +44 -34
- package/dist/commands/suggest.js.map +1 -1
- package/dist/commands/undo.d.ts.map +1 -1
- package/dist/commands/undo.js +35 -25
- package/dist/commands/undo.js.map +1 -1
- package/dist/config/keychain.d.ts.map +1 -1
- package/dist/config/keychain.js +5 -1
- package/dist/config/keychain.js.map +1 -1
- package/dist/config/manager.d.ts +15 -2
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +42 -13
- package/dist/config/manager.js.map +1 -1
- package/dist/core/apply/engine.d.ts +19 -12
- package/dist/core/apply/engine.d.ts.map +1 -1
- package/dist/core/apply/engine.js +160 -149
- package/dist/core/apply/engine.js.map +1 -1
- package/dist/core/apply/index.d.ts +4 -2
- package/dist/core/apply/index.d.ts.map +1 -1
- package/dist/core/apply/index.js.map +1 -1
- package/dist/core/apply/interactive.d.ts +1 -1
- package/dist/core/apply/interactive.d.ts.map +1 -1
- package/dist/core/apply/interactive.js.map +1 -1
- package/dist/core/backup/index.d.ts +2 -1
- package/dist/core/backup/index.d.ts.map +1 -1
- package/dist/core/backup/index.js.map +1 -1
- package/dist/core/backup/manager.d.ts +6 -1
- package/dist/core/backup/manager.d.ts.map +1 -1
- package/dist/core/backup/manager.js +26 -18
- package/dist/core/backup/manager.js.map +1 -1
- package/dist/core/diff/applier.d.ts +23 -8
- package/dist/core/diff/applier.d.ts.map +1 -1
- package/dist/core/diff/applier.js +85 -80
- package/dist/core/diff/applier.js.map +1 -1
- package/dist/core/diff/index.d.ts +6 -3
- package/dist/core/diff/index.d.ts.map +1 -1
- package/dist/core/diff/index.js.map +1 -1
- package/dist/core/diff/parser.d.ts +2 -0
- package/dist/core/diff/parser.d.ts.map +1 -1
- package/dist/core/diff/parser.js +15 -5
- package/dist/core/diff/parser.js.map +1 -1
- package/dist/core/diff/validator.d.ts +3 -8
- package/dist/core/diff/validator.d.ts.map +1 -1
- package/dist/core/diff/validator.js +13 -71
- package/dist/core/diff/validator.js.map +1 -1
- package/dist/db/client.d.ts +9 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +64 -86
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrations/001_init.sql +80 -80
- package/dist/db/migrations/002_applies.sql +33 -32
- package/dist/index.js +13 -20
- package/dist/index.js.map +1 -1
- package/dist/storage/local.d.ts +12 -0
- package/dist/storage/local.d.ts.map +1 -1
- package/dist/storage/local.js +28 -0
- package/dist/storage/local.js.map +1 -1
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/severity.d.ts +6 -0
- package/dist/utils/severity.d.ts.map +1 -0
- package/dist/utils/severity.js +19 -0
- package/dist/utils/severity.js.map +1 -0
- package/package.json +72 -72
package/dist/db/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import postgres from 'postgres';
|
|
2
2
|
import { drizzle } from 'drizzle-orm/postgres-js';
|
|
3
|
-
import { readFile } from 'fs/promises';
|
|
3
|
+
import { readFile, readdir } from 'fs/promises';
|
|
4
4
|
import { join, dirname } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { DatabaseError } from '../types/index.js';
|
|
@@ -17,42 +17,48 @@ export class DatabaseClient {
|
|
|
17
17
|
async connect(localOnly = false) {
|
|
18
18
|
if (localOnly) {
|
|
19
19
|
this.isLocalOnly = true;
|
|
20
|
-
logger.
|
|
20
|
+
logger.verbose('Running in local-only mode (--local-only)');
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
const config = await configManager.load();
|
|
24
|
+
const url = configManager.getDatabaseUrl(config);
|
|
25
|
+
if (!url) {
|
|
26
|
+
this.isLocalOnly = true;
|
|
27
|
+
// Database is optional: stay silent unless an old, unusable config is present.
|
|
28
|
+
if (config.supabaseUrl) {
|
|
29
|
+
logger.warn('Database skipped: OwnKey needs your Postgres connection string, not the Supabase project URL.');
|
|
30
|
+
logger.info('Fix: ownkey config --database-url "postgresql://..." (Supabase → Connect)');
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
logger.verbose('No database configured, using local storage');
|
|
30
34
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const connectionString = `postgresql://postgres:${config.supabaseServiceRoleKey}@db.${projectRef}.supabase.co:5432/postgres`;
|
|
38
|
-
this.sql = postgres(connectionString, {
|
|
39
|
-
max: 10,
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const isLocalHost = /@(localhost|127\.0\.0\.1)(:|\/)/.test(url);
|
|
39
|
+
this.sql = postgres(url, {
|
|
40
|
+
max: 1,
|
|
40
41
|
idle_timeout: 20,
|
|
41
42
|
connect_timeout: 10,
|
|
43
|
+
prepare: false, // required by Supabase's transaction pooler (port 6543)
|
|
44
|
+
ssl: isLocalHost || /sslmode=disable/.test(url) ? false : 'require',
|
|
45
|
+
onnotice: () => { },
|
|
42
46
|
});
|
|
43
47
|
this.db = drizzle(this.sql, { schema });
|
|
44
|
-
// Test connection
|
|
45
48
|
await this.sql `SELECT 1`;
|
|
46
49
|
logger.verbose('Database connection established');
|
|
47
|
-
// Run migrations
|
|
48
50
|
await this.runMigrations();
|
|
49
51
|
}
|
|
50
52
|
catch (error) {
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
logger.
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
const e = error;
|
|
54
|
+
const message = e?.message || e?.code || e?.errors?.[0]?.message || e?.errors?.[0]?.code || String(error);
|
|
55
|
+
logger.warn(`Database unavailable (${message}). Using local storage.`);
|
|
56
|
+
logger.debug(`Database error: ${error instanceof Error ? error.stack : message}`);
|
|
57
|
+
try {
|
|
58
|
+
await this.sql?.end({ timeout: 1 });
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// ignore
|
|
56
62
|
}
|
|
57
63
|
this.isLocalOnly = true;
|
|
58
64
|
this.sql = null;
|
|
@@ -94,75 +100,47 @@ export class DatabaseClient {
|
|
|
94
100
|
getClient() {
|
|
95
101
|
return this.sql;
|
|
96
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Apply every migrations/NNN_name.sql that has not been recorded in schema_migrations.
|
|
105
|
+
* Each migration runs in its own transaction together with its version record.
|
|
106
|
+
*/
|
|
97
107
|
async runMigrations() {
|
|
98
108
|
if (!this.sql) {
|
|
99
109
|
return;
|
|
100
110
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const versionCheck = await this.sql `
|
|
121
|
-
SELECT MAX(version) as version FROM schema_migrations;
|
|
122
|
-
`;
|
|
123
|
-
const version = versionCheck[0]?.version || 0;
|
|
124
|
-
logger.verbose(`Current schema version: ${version}`);
|
|
125
|
-
// Run pending migrations
|
|
126
|
-
const latestVersion = 1; // Update this as we add more migrations
|
|
127
|
-
if (version < latestVersion) {
|
|
128
|
-
for (let v = version + 1; v <= latestVersion; v++) {
|
|
129
|
-
await this.runMigration(v);
|
|
130
|
-
logger.success(`Applied migration ${v}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
logger.verbose('Database schema is up to date');
|
|
111
|
+
const sql = this.sql;
|
|
112
|
+
await sql `
|
|
113
|
+
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
114
|
+
version INTEGER PRIMARY KEY,
|
|
115
|
+
applied_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
116
|
+
)
|
|
117
|
+
`;
|
|
118
|
+
const rows = await sql `SELECT version FROM schema_migrations`;
|
|
119
|
+
const applied = new Set(rows.map((r) => Number(r.version)));
|
|
120
|
+
for (const migration of await DatabaseClient.listMigrations()) {
|
|
121
|
+
if (applied.has(migration.version))
|
|
122
|
+
continue;
|
|
123
|
+
logger.verbose(`Applying database migration ${migration.file}`);
|
|
124
|
+
const body = await readFile(migration.path, 'utf-8');
|
|
125
|
+
try {
|
|
126
|
+
await sql.begin(async (tx) => {
|
|
127
|
+
await tx.unsafe(body);
|
|
128
|
+
await tx.unsafe('INSERT INTO schema_migrations (version) VALUES ($1) ON CONFLICT (version) DO NOTHING', [migration.version]);
|
|
129
|
+
});
|
|
135
130
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
139
|
-
logger.error(`Migration error: ${errorMsg}`);
|
|
140
|
-
if (error instanceof Error && error.stack) {
|
|
141
|
-
logger.debug(`Migration stack: ${error.stack}`);
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw new DatabaseError(`Migration ${migration.file} failed: ${error.message}`, error);
|
|
142
133
|
}
|
|
143
|
-
throw new DatabaseError('Failed to run migrations', error);
|
|
144
134
|
}
|
|
145
135
|
}
|
|
146
|
-
async
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
logger.debug(`Migration SQL length: ${migrationSql.length} characters`);
|
|
155
|
-
await this.sql.unsafe(migrationSql);
|
|
156
|
-
logger.verbose(`Migration ${version} applied successfully`);
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
160
|
-
logger.error(`Migration ${version} failed: ${errorMsg}`);
|
|
161
|
-
if (error instanceof Error && error.stack) {
|
|
162
|
-
logger.debug(`Migration ${version} stack: ${error.stack}`);
|
|
163
|
-
}
|
|
164
|
-
throw new DatabaseError(`Failed to apply migration ${version}`, error);
|
|
165
|
-
}
|
|
136
|
+
static async listMigrations() {
|
|
137
|
+
const dir = join(__dirname, 'migrations');
|
|
138
|
+
const files = await readdir(dir);
|
|
139
|
+
return files
|
|
140
|
+
.map((file) => ({ file, match: /^(\d+)_.+\.sql$/.exec(file) }))
|
|
141
|
+
.filter((f) => f.match)
|
|
142
|
+
.map((f) => ({ version: Number(f.match[1]), file: f.file, path: join(dir, f.file) }))
|
|
143
|
+
.sort((a, b) => a.version - b.version);
|
|
166
144
|
}
|
|
167
145
|
}
|
|
168
146
|
export const dbClient = new DatabaseClient();
|
package/dist/db/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
-- OwnKey CLI Initial Schema Migration
|
|
2
|
-
-- Version: 001
|
|
3
|
-
-- Description: Create all initial tables for OwnKey CLI
|
|
4
|
-
|
|
5
|
-
-- Projects table
|
|
6
|
-
CREATE TABLE IF NOT EXISTS projects (
|
|
7
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
8
|
-
name TEXT NOT NULL,
|
|
9
|
-
root_path TEXT NOT NULL,
|
|
10
|
-
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
|
|
11
|
-
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
-- Runs table
|
|
15
|
-
CREATE TABLE IF NOT EXISTS runs (
|
|
16
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
17
|
-
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
18
|
-
command TEXT NOT NULL,
|
|
19
|
-
status TEXT NOT NULL CHECK (status IN ('running', 'completed', 'failed')),
|
|
20
|
-
summary TEXT,
|
|
21
|
-
started_at TIMESTAMP DEFAULT NOW() NOT NULL,
|
|
22
|
-
finished_at TIMESTAMP
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
-- Suggestions table
|
|
26
|
-
CREATE TABLE IF NOT EXISTS suggestions (
|
|
27
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
28
|
-
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
29
|
-
type TEXT NOT NULL CHECK (type IN ('bug', 'security', 'performance', 'refactor', 'style', 'architecture', 'test', 'documentation')),
|
|
30
|
-
severity TEXT NOT NULL CHECK (severity IN ('critical', 'high', 'medium', 'low', 'info')),
|
|
31
|
-
content TEXT NOT NULL,
|
|
32
|
-
diff TEXT NOT NULL,
|
|
33
|
-
file_path TEXT NOT NULL,
|
|
34
|
-
rationale TEXT NOT NULL,
|
|
35
|
-
tags JSONB,
|
|
36
|
-
created_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
-- Suggestion history table
|
|
40
|
-
CREATE TABLE IF NOT EXISTS suggestion_history (
|
|
41
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
42
|
-
suggestion_id UUID NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
|
|
43
|
-
action TEXT NOT NULL CHECK (action IN ('applied', 'rejected', 'undone')),
|
|
44
|
-
details TEXT,
|
|
45
|
-
acted_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
-- Run suggestions junction table
|
|
49
|
-
CREATE TABLE IF NOT EXISTS run_suggestions (
|
|
50
|
-
run_id UUID NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
|
|
51
|
-
suggestion_id UUID NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
|
|
52
|
-
PRIMARY KEY (run_id, suggestion_id)
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
-- User API keys table (fingerprints only)
|
|
56
|
-
CREATE TABLE IF NOT EXISTS user_api_keys (
|
|
57
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
58
|
-
project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
|
|
59
|
-
provider TEXT NOT NULL,
|
|
60
|
-
key_fingerprint TEXT NOT NULL,
|
|
61
|
-
added_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
-- Schema migrations table
|
|
65
|
-
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
66
|
-
version INTEGER PRIMARY KEY,
|
|
67
|
-
applied_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
-- Create indexes for better query performance
|
|
71
|
-
CREATE INDEX IF NOT EXISTS idx_runs_project_id ON runs(project_id);
|
|
72
|
-
CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status);
|
|
73
|
-
CREATE INDEX IF NOT EXISTS idx_suggestions_project_id ON suggestions(project_id);
|
|
74
|
-
CREATE INDEX IF NOT EXISTS idx_suggestions_type ON suggestions(type);
|
|
75
|
-
CREATE INDEX IF NOT EXISTS idx_suggestions_severity ON suggestions(severity);
|
|
76
|
-
CREATE INDEX IF NOT EXISTS idx_suggestion_history_suggestion_id ON suggestion_history(suggestion_id);
|
|
77
|
-
CREATE INDEX IF NOT EXISTS idx_user_api_keys_project_id ON user_api_keys(project_id);
|
|
78
|
-
|
|
79
|
-
-- Insert migration record
|
|
80
|
-
INSERT INTO schema_migrations (version) VALUES (1) ON CONFLICT (version) DO NOTHING;
|
|
1
|
+
-- OwnKey CLI Initial Schema Migration
|
|
2
|
+
-- Version: 001
|
|
3
|
+
-- Description: Create all initial tables for OwnKey CLI
|
|
4
|
+
|
|
5
|
+
-- Projects table
|
|
6
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
7
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
8
|
+
name TEXT NOT NULL,
|
|
9
|
+
root_path TEXT NOT NULL,
|
|
10
|
+
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
|
|
11
|
+
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- Runs table
|
|
15
|
+
CREATE TABLE IF NOT EXISTS runs (
|
|
16
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
17
|
+
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
18
|
+
command TEXT NOT NULL,
|
|
19
|
+
status TEXT NOT NULL CHECK (status IN ('running', 'completed', 'failed')),
|
|
20
|
+
summary TEXT,
|
|
21
|
+
started_at TIMESTAMP DEFAULT NOW() NOT NULL,
|
|
22
|
+
finished_at TIMESTAMP
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
-- Suggestions table
|
|
26
|
+
CREATE TABLE IF NOT EXISTS suggestions (
|
|
27
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
28
|
+
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
29
|
+
type TEXT NOT NULL CHECK (type IN ('bug', 'security', 'performance', 'refactor', 'style', 'architecture', 'test', 'documentation')),
|
|
30
|
+
severity TEXT NOT NULL CHECK (severity IN ('critical', 'high', 'medium', 'low', 'info')),
|
|
31
|
+
content TEXT NOT NULL,
|
|
32
|
+
diff TEXT NOT NULL,
|
|
33
|
+
file_path TEXT NOT NULL,
|
|
34
|
+
rationale TEXT NOT NULL,
|
|
35
|
+
tags JSONB,
|
|
36
|
+
created_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
-- Suggestion history table
|
|
40
|
+
CREATE TABLE IF NOT EXISTS suggestion_history (
|
|
41
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
42
|
+
suggestion_id UUID NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
|
|
43
|
+
action TEXT NOT NULL CHECK (action IN ('applied', 'rejected', 'undone')),
|
|
44
|
+
details TEXT,
|
|
45
|
+
acted_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
-- Run suggestions junction table
|
|
49
|
+
CREATE TABLE IF NOT EXISTS run_suggestions (
|
|
50
|
+
run_id UUID NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
|
|
51
|
+
suggestion_id UUID NOT NULL REFERENCES suggestions(id) ON DELETE CASCADE,
|
|
52
|
+
PRIMARY KEY (run_id, suggestion_id)
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
-- User API keys table (fingerprints only)
|
|
56
|
+
CREATE TABLE IF NOT EXISTS user_api_keys (
|
|
57
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
58
|
+
project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
|
|
59
|
+
provider TEXT NOT NULL,
|
|
60
|
+
key_fingerprint TEXT NOT NULL,
|
|
61
|
+
added_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
-- Schema migrations table
|
|
65
|
+
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
66
|
+
version INTEGER PRIMARY KEY,
|
|
67
|
+
applied_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
-- Create indexes for better query performance
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_runs_project_id ON runs(project_id);
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status);
|
|
73
|
+
CREATE INDEX IF NOT EXISTS idx_suggestions_project_id ON suggestions(project_id);
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_suggestions_type ON suggestions(type);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_suggestions_severity ON suggestions(severity);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_suggestion_history_suggestion_id ON suggestion_history(suggestion_id);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_user_api_keys_project_id ON user_api_keys(project_id);
|
|
78
|
+
|
|
79
|
+
-- Insert migration record
|
|
80
|
+
INSERT INTO schema_migrations (version) VALUES (1) ON CONFLICT (version) DO NOTHING;
|
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
-- Migration: Add applies table for tracking applied suggestions
|
|
2
|
-
-- Version: 002
|
|
3
|
-
|
|
4
|
-
CREATE TABLE IF NOT EXISTS applies (
|
|
5
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
6
|
-
suggestion_id UUID NOT NULL,
|
|
7
|
-
files_modified JSONB NOT NULL,
|
|
8
|
-
backup_id TEXT,
|
|
9
|
-
applied_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
10
|
-
status TEXT NOT NULL CHECK (status IN ('success', 'failed', 'rolled_back')),
|
|
11
|
-
error TEXT,
|
|
12
|
-
metadata JSONB,
|
|
13
|
-
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
-- Index for faster lookups
|
|
17
|
-
CREATE INDEX IF NOT EXISTS idx_applies_suggestion_id ON applies(suggestion_id);
|
|
18
|
-
CREATE INDEX IF NOT EXISTS idx_applies_applied_at ON applies(applied_at DESC);
|
|
19
|
-
CREATE INDEX IF NOT EXISTS idx_applies_status ON applies(status);
|
|
20
|
-
|
|
21
|
-
-- Add foreign key if suggestions table exists
|
|
22
|
-
-- Note: This will fail gracefully if suggestions table doesn't exist yet
|
|
23
|
-
DO $$
|
|
24
|
-
BEGIN
|
|
25
|
-
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'suggestions')
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
END
|
|
1
|
+
-- Migration: Add applies table for tracking applied suggestions
|
|
2
|
+
-- Version: 002
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS applies (
|
|
5
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
6
|
+
suggestion_id UUID NOT NULL,
|
|
7
|
+
files_modified JSONB NOT NULL,
|
|
8
|
+
backup_id TEXT,
|
|
9
|
+
applied_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
10
|
+
status TEXT NOT NULL CHECK (status IN ('success', 'failed', 'rolled_back')),
|
|
11
|
+
error TEXT,
|
|
12
|
+
metadata JSONB,
|
|
13
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
-- Index for faster lookups
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_applies_suggestion_id ON applies(suggestion_id);
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_applies_applied_at ON applies(applied_at DESC);
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_applies_status ON applies(status);
|
|
20
|
+
|
|
21
|
+
-- Add foreign key if suggestions table exists
|
|
22
|
+
-- Note: This will fail gracefully if suggestions table doesn't exist yet
|
|
23
|
+
DO $$
|
|
24
|
+
BEGIN
|
|
25
|
+
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'suggestions')
|
|
26
|
+
AND NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_applies_suggestion') THEN
|
|
27
|
+
ALTER TABLE applies
|
|
28
|
+
ADD CONSTRAINT fk_applies_suggestion
|
|
29
|
+
FOREIGN KEY (suggestion_id)
|
|
30
|
+
REFERENCES suggestions(id)
|
|
31
|
+
ON DELETE CASCADE;
|
|
32
|
+
END IF;
|
|
33
|
+
END $$;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { logger } from './utils/logger.js';
|
|
4
|
-
import { configManager } from './config/manager.js';
|
|
5
4
|
import { dbClient } from './db/client.js';
|
|
6
|
-
import
|
|
5
|
+
import { createRequire } from 'module';
|
|
7
6
|
// Import commands
|
|
8
7
|
import { configCommand } from './commands/config.js';
|
|
9
8
|
import { scanCommand } from './commands/scan.js';
|
|
@@ -14,7 +13,7 @@ const program = new Command();
|
|
|
14
13
|
program
|
|
15
14
|
.name('ownkey')
|
|
16
15
|
.description('Local-first AI coding agent for intelligent codebase analysis')
|
|
17
|
-
.version(
|
|
16
|
+
.version(createRequire(import.meta.url)('../package.json').version);
|
|
18
17
|
// Global options
|
|
19
18
|
program.option('--local-only', 'Run without database persistence');
|
|
20
19
|
program.option('--verbose', 'Enable verbose logging');
|
|
@@ -26,11 +25,13 @@ program.addCommand(scanCommand);
|
|
|
26
25
|
program.addCommand(suggestCommand);
|
|
27
26
|
program.addCommand(applyCommand);
|
|
28
27
|
program.addCommand(undoCommand);
|
|
29
|
-
// Pre-
|
|
30
|
-
program
|
|
28
|
+
// Pre-action hook: set up logging and storage.
|
|
29
|
+
// Note: the hook is registered on the root program, so `thisCommand` is always the
|
|
30
|
+
// root. The command actually being run is the second argument (`actionCommand`).
|
|
31
|
+
program.hook('preAction', async (thisCommand, actionCommand) => {
|
|
31
32
|
await logger.init();
|
|
33
|
+
// Global flags live on the root program
|
|
32
34
|
const opts = thisCommand.opts();
|
|
33
|
-
// Set log level
|
|
34
35
|
if (opts.debug) {
|
|
35
36
|
logger.setLevel('debug');
|
|
36
37
|
}
|
|
@@ -40,25 +41,17 @@ program.hook('preAction', async (thisCommand) => {
|
|
|
40
41
|
else if (opts.quiet) {
|
|
41
42
|
logger.setLevel('quiet');
|
|
42
43
|
}
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (!isConfigCommand) {
|
|
47
|
-
const configExists = await configManager.exists();
|
|
48
|
-
if (!configExists) {
|
|
49
|
-
console.log(chalk.yellow('\n⚠️ No configuration found.\n'));
|
|
50
|
-
console.log('OwnKey needs to be configured before use.');
|
|
51
|
-
console.log(chalk.cyan('\nRun: ownkey config\n'));
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
// Connect to database (or enter local-only mode)
|
|
55
|
-
await dbClient.connect(opts.localOnly);
|
|
44
|
+
// `config` must always run, even with no configuration yet; it never needs the database.
|
|
45
|
+
if (actionCommand.name() === 'config') {
|
|
46
|
+
return;
|
|
56
47
|
}
|
|
48
|
+
// Optional database (Supabase/Postgres). Silent no-op when not configured.
|
|
49
|
+
await dbClient.connect(Boolean(opts.localOnly));
|
|
57
50
|
});
|
|
58
51
|
// Post-action hook to clean up
|
|
59
52
|
program.hook('postAction', async () => {
|
|
60
53
|
await dbClient.disconnect();
|
|
61
54
|
});
|
|
62
55
|
// Parse arguments
|
|
63
|
-
program.
|
|
56
|
+
await program.parseAsync();
|
|
64
57
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,+DAA+D,CAAC;KAC5E,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC;AAExE,iBAAiB;AACjB,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,kCAAkC,CAAC,CAAC;AACnE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAC;AACtD,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;AAClD,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAAC;AAE3D,WAAW;AACX,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAEhC,+CAA+C;AAC/C,mFAAmF;AACnF,iFAAiF;AACjF,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE;IAC3D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IAEpB,wCAAwC;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAEhC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;SAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACtB,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;SAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,yFAAyF;IACzF,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO;IACX,CAAC;IAED,2EAA2E;IAC3E,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,+BAA+B;AAC/B,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;IAClC,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,kBAAkB;AAClB,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC"}
|
package/dist/storage/local.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ export interface StoredSuggestion extends Suggestion {
|
|
|
4
4
|
projectPath: string;
|
|
5
5
|
projectName: string;
|
|
6
6
|
createdAt: string;
|
|
7
|
+
/** Matching row id in the optional database */
|
|
8
|
+
dbId?: string;
|
|
9
|
+
appliedAt?: string;
|
|
10
|
+
backupId?: string;
|
|
7
11
|
}
|
|
8
12
|
export interface BackupInfo {
|
|
9
13
|
id: string;
|
|
@@ -37,6 +41,14 @@ export declare class LocalStorage {
|
|
|
37
41
|
* Load a single suggestion by ID
|
|
38
42
|
*/
|
|
39
43
|
loadSuggestion(id: string): Promise<StoredSuggestion | null>;
|
|
44
|
+
/**
|
|
45
|
+
* Merge fields into a stored suggestion (e.g. mark applied, link a database id)
|
|
46
|
+
*/
|
|
47
|
+
updateSuggestion(id: string, patch: Partial<StoredSuggestion>): Promise<StoredSuggestion | null>;
|
|
48
|
+
/**
|
|
49
|
+
* After an undo: mark the suggestions applied with this backup as pending again
|
|
50
|
+
*/
|
|
51
|
+
clearApplied(backupId: string): Promise<void>;
|
|
40
52
|
/**
|
|
41
53
|
* Load all suggestions for a specific project
|
|
42
54
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACrB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,UAAU,CAAS;;IAS3B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3B;;;OAGG;IACG,eAAe,CACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,UAAU,EAAE,GAC1B,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAgD9B;;OAEG;IACG,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKlE;;OAEG;IACG,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAKjF;;OAEG;YACW,kBAAkB;IAUhC;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBnF;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAaxD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC,CAAC;CAaL;AAGD,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACrB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,UAAU,CAAS;;IAS3B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3B;;;OAGG;IACG,eAAe,CACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,UAAU,EAAE,GAC1B,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAgD9B;;OAEG;IACG,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKlE;;OAEG;IACG,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAStG;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAanD;;OAEG;IACG,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAKjF;;OAEG;YACW,kBAAkB;IAUhC;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBnF;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAaxD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC,CAAC;CAaL;AAGD,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
package/dist/storage/local.js
CHANGED
|
@@ -91,6 +91,34 @@ export class LocalStorage {
|
|
|
91
91
|
const all = await this.loadAllSuggestions();
|
|
92
92
|
return all.find(s => s.id === id) || null;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Merge fields into a stored suggestion (e.g. mark applied, link a database id)
|
|
96
|
+
*/
|
|
97
|
+
async updateSuggestion(id, patch) {
|
|
98
|
+
const all = await this.loadAllSuggestions();
|
|
99
|
+
const index = all.findIndex((s) => s.id === id);
|
|
100
|
+
if (index === -1)
|
|
101
|
+
return null;
|
|
102
|
+
all[index] = { ...all[index], ...patch, id };
|
|
103
|
+
await writeFile(this.suggestionsFile, JSON.stringify(all, null, 2));
|
|
104
|
+
return all[index];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* After an undo: mark the suggestions applied with this backup as pending again
|
|
108
|
+
*/
|
|
109
|
+
async clearApplied(backupId) {
|
|
110
|
+
const all = await this.loadAllSuggestions();
|
|
111
|
+
let changed = false;
|
|
112
|
+
for (const s of all) {
|
|
113
|
+
if (s.backupId === backupId) {
|
|
114
|
+
delete s.appliedAt;
|
|
115
|
+
delete s.backupId;
|
|
116
|
+
changed = true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (changed)
|
|
120
|
+
await writeFile(this.suggestionsFile, JSON.stringify(all, null, 2));
|
|
121
|
+
}
|
|
94
122
|
/**
|
|
95
123
|
* Load all suggestions for a specific project
|
|
96
124
|
*/
|