@skillsmith/core 2.0.2 → 2.1.1
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 +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analytics/AnalyticsRepository.d.ts +4 -0
- package/dist/src/analytics/AnalyticsRepository.d.ts.map +1 -1
- package/dist/src/analytics/AnalyticsRepository.js +26 -44
- package/dist/src/analytics/AnalyticsRepository.js.map +1 -1
- package/dist/src/api/client.d.ts +8 -8
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.js +2 -2
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/db/schema.d.ts +1 -1
- package/dist/src/db/schema.d.ts.map +1 -1
- package/dist/src/db/schema.js +41 -1
- package/dist/src/db/schema.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/repositories/SyncConfigRepository.d.ts +91 -0
- package/dist/src/repositories/SyncConfigRepository.d.ts.map +1 -0
- package/dist/src/repositories/SyncConfigRepository.js +202 -0
- package/dist/src/repositories/SyncConfigRepository.js.map +1 -0
- package/dist/src/repositories/SyncHistoryRepository.d.ts +104 -0
- package/dist/src/repositories/SyncHistoryRepository.d.ts.map +1 -0
- package/dist/src/repositories/SyncHistoryRepository.js +235 -0
- package/dist/src/repositories/SyncHistoryRepository.js.map +1 -0
- package/dist/src/scripts/github-import/github-client.d.ts +24 -0
- package/dist/src/scripts/github-import/github-client.d.ts.map +1 -1
- package/dist/src/scripts/github-import/github-client.js +103 -0
- package/dist/src/scripts/github-import/github-client.js.map +1 -1
- package/dist/src/scripts/github-import/index.js +3 -10
- package/dist/src/scripts/github-import/index.js.map +1 -1
- package/dist/src/scripts/merge-skills.d.ts +56 -0
- package/dist/src/scripts/merge-skills.d.ts.map +1 -0
- package/dist/src/scripts/merge-skills.js +411 -0
- package/dist/src/scripts/merge-skills.js.map +1 -0
- package/dist/src/scripts/skill-scanner/index.d.ts +9 -2
- package/dist/src/scripts/skill-scanner/index.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/index.js +98 -7
- package/dist/src/scripts/skill-scanner/index.js.map +1 -1
- package/dist/src/scripts/skill-scanner/logger.d.ts +51 -0
- package/dist/src/scripts/skill-scanner/logger.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/logger.js +255 -1
- package/dist/src/scripts/skill-scanner/logger.js.map +1 -1
- package/dist/src/scripts/skill-scanner/reporter.d.ts +1 -1
- package/dist/src/scripts/skill-scanner/reporter.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/reporter.js +67 -15
- package/dist/src/scripts/skill-scanner/reporter.js.map +1 -1
- package/dist/src/scripts/skill-scanner/scanner.d.ts +5 -2
- package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/scanner.js +156 -39
- package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
- package/dist/src/scripts/skill-scanner/types.d.ts +44 -0
- package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.d.ts +2 -0
- package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.js +51 -2
- package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
- package/dist/src/sync/BackgroundSyncService.d.ts +90 -0
- package/dist/src/sync/BackgroundSyncService.d.ts.map +1 -0
- package/dist/src/sync/BackgroundSyncService.js +214 -0
- package/dist/src/sync/BackgroundSyncService.js.map +1 -0
- package/dist/src/sync/SyncEngine.d.ts +76 -0
- package/dist/src/sync/SyncEngine.d.ts.map +1 -0
- package/dist/src/sync/SyncEngine.js +284 -0
- package/dist/src/sync/SyncEngine.js.map +1 -0
- package/dist/src/sync/index.d.ts +11 -0
- package/dist/src/sync/index.d.ts.map +1 -0
- package/dist/src/sync/index.js +14 -0
- package/dist/src/sync/index.js.map +1 -0
- package/dist/src/types.d.ts +3 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tests/security/ContinuousSecurity.test.js +10 -12
- package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
- package/dist/tests/sync/SyncConfigRepository.test.d.ts +7 -0
- package/dist/tests/sync/SyncConfigRepository.test.d.ts.map +1 -0
- package/dist/tests/sync/SyncConfigRepository.test.js +154 -0
- package/dist/tests/sync/SyncConfigRepository.test.js.map +1 -0
- package/dist/tests/sync/SyncEngine.test.d.ts +7 -0
- package/dist/tests/sync/SyncEngine.test.d.ts.map +1 -0
- package/dist/tests/sync/SyncEngine.test.js +300 -0
- package/dist/tests/sync/SyncEngine.test.js.map +1 -0
- package/dist/tests/sync/SyncHistoryRepository.test.d.ts +7 -0
- package/dist/tests/sync/SyncHistoryRepository.test.d.ts.map +1 -0
- package/dist/tests/sync/SyncHistoryRepository.test.js +220 -0
- package/dist/tests/sync/SyncHistoryRepository.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyncConfigRepository - Manages sync configuration state
|
|
3
|
+
*
|
|
4
|
+
* Handles the singleton sync_config record for registry sync settings.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Interval in milliseconds for each frequency
|
|
8
|
+
*/
|
|
9
|
+
export const FREQUENCY_INTERVALS = {
|
|
10
|
+
daily: 86400000, // 24 hours
|
|
11
|
+
weekly: 604800000, // 7 days
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Repository for sync configuration management
|
|
15
|
+
*/
|
|
16
|
+
export class SyncConfigRepository {
|
|
17
|
+
db;
|
|
18
|
+
stmts;
|
|
19
|
+
constructor(db) {
|
|
20
|
+
this.db = db;
|
|
21
|
+
this.ensureTable();
|
|
22
|
+
this.prepareStatements();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Ensure sync_config table exists and has default row
|
|
26
|
+
*/
|
|
27
|
+
ensureTable() {
|
|
28
|
+
// Check if table exists
|
|
29
|
+
const tableExists = this.db
|
|
30
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='sync_config'")
|
|
31
|
+
.get();
|
|
32
|
+
if (!tableExists) {
|
|
33
|
+
// Create table if it doesn't exist (handles pre-migration databases)
|
|
34
|
+
this.db.exec(`
|
|
35
|
+
CREATE TABLE IF NOT EXISTS sync_config (
|
|
36
|
+
id TEXT PRIMARY KEY DEFAULT 'default',
|
|
37
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
38
|
+
frequency TEXT NOT NULL DEFAULT 'daily' CHECK(frequency IN ('daily', 'weekly')),
|
|
39
|
+
interval_ms INTEGER NOT NULL DEFAULT 86400000,
|
|
40
|
+
last_sync_at TEXT,
|
|
41
|
+
next_sync_at TEXT,
|
|
42
|
+
last_sync_count INTEGER DEFAULT 0,
|
|
43
|
+
last_sync_error TEXT,
|
|
44
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
45
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
46
|
+
);
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
// Ensure default config exists
|
|
50
|
+
this.db.exec("INSERT OR IGNORE INTO sync_config (id) VALUES ('default')");
|
|
51
|
+
}
|
|
52
|
+
prepareStatements() {
|
|
53
|
+
this.stmts = {
|
|
54
|
+
get: this.db.prepare(`
|
|
55
|
+
SELECT * FROM sync_config WHERE id = 'default'
|
|
56
|
+
`),
|
|
57
|
+
update: this.db.prepare(`
|
|
58
|
+
UPDATE sync_config
|
|
59
|
+
SET enabled = ?, frequency = ?, interval_ms = ?, updated_at = datetime('now')
|
|
60
|
+
WHERE id = 'default'
|
|
61
|
+
`),
|
|
62
|
+
setLastSync: this.db.prepare(`
|
|
63
|
+
UPDATE sync_config
|
|
64
|
+
SET last_sync_at = ?, last_sync_count = ?, last_sync_error = NULL, updated_at = datetime('now')
|
|
65
|
+
WHERE id = 'default'
|
|
66
|
+
`),
|
|
67
|
+
setLastSyncError: this.db.prepare(`
|
|
68
|
+
UPDATE sync_config
|
|
69
|
+
SET last_sync_error = ?, updated_at = datetime('now')
|
|
70
|
+
WHERE id = 'default'
|
|
71
|
+
`),
|
|
72
|
+
setNextSync: this.db.prepare(`
|
|
73
|
+
UPDATE sync_config
|
|
74
|
+
SET next_sync_at = ?, updated_at = datetime('now')
|
|
75
|
+
WHERE id = 'default'
|
|
76
|
+
`),
|
|
77
|
+
clearError: this.db.prepare(`
|
|
78
|
+
UPDATE sync_config
|
|
79
|
+
SET last_sync_error = NULL, updated_at = datetime('now')
|
|
80
|
+
WHERE id = 'default'
|
|
81
|
+
`),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
rowToConfig(row) {
|
|
85
|
+
return {
|
|
86
|
+
id: row.id,
|
|
87
|
+
enabled: row.enabled === 1,
|
|
88
|
+
frequency: row.frequency,
|
|
89
|
+
intervalMs: row.interval_ms,
|
|
90
|
+
lastSyncAt: row.last_sync_at,
|
|
91
|
+
nextSyncAt: row.next_sync_at,
|
|
92
|
+
lastSyncCount: row.last_sync_count,
|
|
93
|
+
lastSyncError: row.last_sync_error,
|
|
94
|
+
createdAt: row.created_at,
|
|
95
|
+
updatedAt: row.updated_at,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get current sync configuration
|
|
100
|
+
*/
|
|
101
|
+
getConfig() {
|
|
102
|
+
const row = this.stmts.get.get();
|
|
103
|
+
if (!row) {
|
|
104
|
+
// Should never happen due to ensureTable(), but handle gracefully
|
|
105
|
+
return {
|
|
106
|
+
id: 'default',
|
|
107
|
+
enabled: true,
|
|
108
|
+
frequency: 'daily',
|
|
109
|
+
intervalMs: FREQUENCY_INTERVALS.daily,
|
|
110
|
+
lastSyncAt: null,
|
|
111
|
+
nextSyncAt: null,
|
|
112
|
+
lastSyncCount: 0,
|
|
113
|
+
lastSyncError: null,
|
|
114
|
+
createdAt: new Date().toISOString(),
|
|
115
|
+
updatedAt: new Date().toISOString(),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return this.rowToConfig(row);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Update sync configuration
|
|
122
|
+
*/
|
|
123
|
+
updateConfig(update) {
|
|
124
|
+
const current = this.getConfig();
|
|
125
|
+
const enabled = update.enabled ?? current.enabled;
|
|
126
|
+
const frequency = update.frequency ?? current.frequency;
|
|
127
|
+
const intervalMs = FREQUENCY_INTERVALS[frequency];
|
|
128
|
+
this.stmts.update.run(enabled ? 1 : 0, frequency, intervalMs);
|
|
129
|
+
// If frequency changed, recalculate next sync
|
|
130
|
+
if (update.frequency && current.lastSyncAt) {
|
|
131
|
+
const nextSync = this.calculateNextSync(current.lastSyncAt, intervalMs);
|
|
132
|
+
this.stmts.setNextSync.run(nextSync);
|
|
133
|
+
}
|
|
134
|
+
return this.getConfig();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Record successful sync completion
|
|
138
|
+
*/
|
|
139
|
+
setLastSync(timestamp, count) {
|
|
140
|
+
this.stmts.setLastSync.run(timestamp, count);
|
|
141
|
+
// Calculate next sync time
|
|
142
|
+
const config = this.getConfig();
|
|
143
|
+
const nextSync = this.calculateNextSync(timestamp, config.intervalMs);
|
|
144
|
+
this.stmts.setNextSync.run(nextSync);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Record sync error
|
|
148
|
+
*/
|
|
149
|
+
setLastSyncError(error) {
|
|
150
|
+
this.stmts.setLastSyncError.run(error);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Clear any stored error
|
|
154
|
+
*/
|
|
155
|
+
clearError() {
|
|
156
|
+
this.stmts.clearError.run();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Calculate next sync time based on last sync and interval
|
|
160
|
+
*/
|
|
161
|
+
calculateNextSync(lastSyncAt, intervalMs) {
|
|
162
|
+
const lastSync = new Date(lastSyncAt);
|
|
163
|
+
const nextSync = new Date(lastSync.getTime() + intervalMs);
|
|
164
|
+
return nextSync.toISOString();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Check if sync is due based on current time
|
|
168
|
+
*/
|
|
169
|
+
isSyncDue() {
|
|
170
|
+
const config = this.getConfig();
|
|
171
|
+
// If never synced, it's due
|
|
172
|
+
if (!config.lastSyncAt) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
// If no next sync calculated, calculate it
|
|
176
|
+
if (!config.nextSyncAt) {
|
|
177
|
+
const nextSync = this.calculateNextSync(config.lastSyncAt, config.intervalMs);
|
|
178
|
+
this.stmts.setNextSync.run(nextSync);
|
|
179
|
+
return new Date() >= new Date(nextSync);
|
|
180
|
+
}
|
|
181
|
+
return new Date() >= new Date(config.nextSyncAt);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Enable automatic sync
|
|
185
|
+
*/
|
|
186
|
+
enable() {
|
|
187
|
+
return this.updateConfig({ enabled: true });
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Disable automatic sync
|
|
191
|
+
*/
|
|
192
|
+
disable() {
|
|
193
|
+
return this.updateConfig({ enabled: false });
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Set sync frequency
|
|
197
|
+
*/
|
|
198
|
+
setFrequency(frequency) {
|
|
199
|
+
return this.updateConfig({ frequency });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=SyncConfigRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncConfigRepository.js","sourceRoot":"","sources":["../../../src/repositories/SyncConfigRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyncHistoryRepository - Tracks sync operation history
|
|
3
|
+
*
|
|
4
|
+
* Records each sync run with timing, counts, and status for monitoring.
|
|
5
|
+
*/
|
|
6
|
+
import type { Database as DatabaseType } from 'better-sqlite3';
|
|
7
|
+
/**
|
|
8
|
+
* Sync run status
|
|
9
|
+
*/
|
|
10
|
+
export type SyncStatus = 'running' | 'success' | 'failed' | 'partial';
|
|
11
|
+
/**
|
|
12
|
+
* Sync history entry
|
|
13
|
+
*/
|
|
14
|
+
export interface SyncHistoryEntry {
|
|
15
|
+
id: string;
|
|
16
|
+
startedAt: string;
|
|
17
|
+
completedAt: string | null;
|
|
18
|
+
status: SyncStatus;
|
|
19
|
+
skillsAdded: number;
|
|
20
|
+
skillsUpdated: number;
|
|
21
|
+
skillsUnchanged: number;
|
|
22
|
+
errorMessage: string | null;
|
|
23
|
+
durationMs: number | null;
|
|
24
|
+
createdAt: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Sync result for completing a run
|
|
28
|
+
*/
|
|
29
|
+
export interface SyncRunResult {
|
|
30
|
+
skillsAdded: number;
|
|
31
|
+
skillsUpdated: number;
|
|
32
|
+
skillsUnchanged: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Repository for sync history tracking
|
|
36
|
+
*/
|
|
37
|
+
export declare class SyncHistoryRepository {
|
|
38
|
+
private db;
|
|
39
|
+
private stmts;
|
|
40
|
+
constructor(db: DatabaseType);
|
|
41
|
+
/**
|
|
42
|
+
* Ensure sync_history table exists
|
|
43
|
+
*/
|
|
44
|
+
private ensureTable;
|
|
45
|
+
private prepareStatements;
|
|
46
|
+
private rowToEntry;
|
|
47
|
+
/**
|
|
48
|
+
* Start a new sync run
|
|
49
|
+
* @returns The sync run ID
|
|
50
|
+
*/
|
|
51
|
+
startRun(): string;
|
|
52
|
+
/**
|
|
53
|
+
* Complete a sync run successfully
|
|
54
|
+
*/
|
|
55
|
+
completeRun(id: string, result: SyncRunResult): void;
|
|
56
|
+
/**
|
|
57
|
+
* Mark a sync run as partially complete (some errors)
|
|
58
|
+
*/
|
|
59
|
+
completeRunPartial(id: string, result: SyncRunResult, errorMessage: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Mark a sync run as failed
|
|
62
|
+
*/
|
|
63
|
+
failRun(id: string, error: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Get a specific sync run by ID
|
|
66
|
+
*/
|
|
67
|
+
getById(id: string): SyncHistoryEntry | null;
|
|
68
|
+
/**
|
|
69
|
+
* Get sync history (most recent first)
|
|
70
|
+
*/
|
|
71
|
+
getHistory(limit?: number): SyncHistoryEntry[];
|
|
72
|
+
/**
|
|
73
|
+
* Get the last successful sync run
|
|
74
|
+
*/
|
|
75
|
+
getLastSuccessful(): SyncHistoryEntry | null;
|
|
76
|
+
/**
|
|
77
|
+
* Get any currently running sync operations
|
|
78
|
+
*/
|
|
79
|
+
getRunning(): SyncHistoryEntry[];
|
|
80
|
+
/**
|
|
81
|
+
* Check if a sync is currently running
|
|
82
|
+
*/
|
|
83
|
+
isRunning(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Clean up old history entries
|
|
86
|
+
* @param daysToKeep Number of days of history to retain
|
|
87
|
+
*/
|
|
88
|
+
cleanup(daysToKeep?: number): number;
|
|
89
|
+
/**
|
|
90
|
+
* Get total count of history entries
|
|
91
|
+
*/
|
|
92
|
+
count(): number;
|
|
93
|
+
/**
|
|
94
|
+
* Get sync statistics
|
|
95
|
+
*/
|
|
96
|
+
getStats(): {
|
|
97
|
+
totalRuns: number;
|
|
98
|
+
successfulRuns: number;
|
|
99
|
+
failedRuns: number;
|
|
100
|
+
lastSuccessAt: string | null;
|
|
101
|
+
averageDurationMs: number | null;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=SyncHistoryRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncHistoryRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/SyncHistoryRepository.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE9D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAErE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;CAClB;AAkBD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;CACxB;AAcD;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,KAAK,CAUZ;gBAEW,EAAE,EAAE,YAAY;IAM5B;;OAEG;IACH,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,iBAAiB;IA6CzB,OAAO,CAAC,UAAU;IAelB;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAOlB;;OAEG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI;IAyBpD;;OAEG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IA8BjF;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAYxC;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAK5C;;OAEG;IACH,UAAU,CAAC,KAAK,GAAE,MAAW,GAAG,gBAAgB,EAAE;IAKlD;;OAEG;IACH,iBAAiB,IAAI,gBAAgB,GAAG,IAAI;IAK5C;;OAEG;IACH,UAAU,IAAI,gBAAgB,EAAE;IAKhC;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;OAGG;IACH,OAAO,CAAC,UAAU,GAAE,MAAW,GAAG,MAAM;IAOxC;;OAEG;IACH,KAAK,IAAI,MAAM;IAKf;;OAEG;IACH,QAAQ,IAAI;QACV,SAAS,EAAE,MAAM,CAAA;QACjB,cAAc,EAAE,MAAM,CAAA;QACtB,UAAU,EAAE,MAAM,CAAA;QAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;QAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;KACjC;CA6BF"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyncHistoryRepository - Tracks sync operation history
|
|
3
|
+
*
|
|
4
|
+
* Records each sync run with timing, counts, and status for monitoring.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Generate a unique ID for sync runs
|
|
8
|
+
*/
|
|
9
|
+
function generateSyncId() {
|
|
10
|
+
const timestamp = new Date()
|
|
11
|
+
.toISOString()
|
|
12
|
+
.replace(/[-:T.Z]/g, '')
|
|
13
|
+
.slice(0, 14);
|
|
14
|
+
const random = Math.random().toString(36).slice(2, 8);
|
|
15
|
+
return `sync-${timestamp}-${random}`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Repository for sync history tracking
|
|
19
|
+
*/
|
|
20
|
+
export class SyncHistoryRepository {
|
|
21
|
+
db;
|
|
22
|
+
stmts;
|
|
23
|
+
constructor(db) {
|
|
24
|
+
this.db = db;
|
|
25
|
+
this.ensureTable();
|
|
26
|
+
this.prepareStatements();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Ensure sync_history table exists
|
|
30
|
+
*/
|
|
31
|
+
ensureTable() {
|
|
32
|
+
const tableExists = this.db
|
|
33
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='sync_history'")
|
|
34
|
+
.get();
|
|
35
|
+
if (!tableExists) {
|
|
36
|
+
this.db.exec(`
|
|
37
|
+
CREATE TABLE IF NOT EXISTS sync_history (
|
|
38
|
+
id TEXT PRIMARY KEY,
|
|
39
|
+
started_at TEXT NOT NULL,
|
|
40
|
+
completed_at TEXT,
|
|
41
|
+
status TEXT NOT NULL DEFAULT 'running' CHECK(status IN ('running', 'success', 'failed', 'partial')),
|
|
42
|
+
skills_added INTEGER DEFAULT 0,
|
|
43
|
+
skills_updated INTEGER DEFAULT 0,
|
|
44
|
+
skills_unchanged INTEGER DEFAULT 0,
|
|
45
|
+
error_message TEXT,
|
|
46
|
+
duration_ms INTEGER,
|
|
47
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_sync_history_started ON sync_history(started_at DESC);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_sync_history_status ON sync_history(status);
|
|
52
|
+
`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
prepareStatements() {
|
|
56
|
+
this.stmts = {
|
|
57
|
+
insert: this.db.prepare(`
|
|
58
|
+
INSERT INTO sync_history (id, started_at, status)
|
|
59
|
+
VALUES (?, ?, 'running')
|
|
60
|
+
`),
|
|
61
|
+
complete: this.db.prepare(`
|
|
62
|
+
UPDATE sync_history
|
|
63
|
+
SET completed_at = ?, status = ?, skills_added = ?, skills_updated = ?, skills_unchanged = ?, duration_ms = ?
|
|
64
|
+
WHERE id = ?
|
|
65
|
+
`),
|
|
66
|
+
fail: this.db.prepare(`
|
|
67
|
+
UPDATE sync_history
|
|
68
|
+
SET completed_at = ?, status = 'failed', error_message = ?, duration_ms = ?
|
|
69
|
+
WHERE id = ?
|
|
70
|
+
`),
|
|
71
|
+
getById: this.db.prepare(`
|
|
72
|
+
SELECT * FROM sync_history WHERE id = ?
|
|
73
|
+
`),
|
|
74
|
+
getHistory: this.db.prepare(`
|
|
75
|
+
SELECT * FROM sync_history ORDER BY started_at DESC LIMIT ?
|
|
76
|
+
`),
|
|
77
|
+
getLastSuccessful: this.db.prepare(`
|
|
78
|
+
SELECT * FROM sync_history WHERE status = 'success' ORDER BY started_at DESC LIMIT 1
|
|
79
|
+
`),
|
|
80
|
+
getRunning: this.db.prepare(`
|
|
81
|
+
SELECT * FROM sync_history WHERE status = 'running'
|
|
82
|
+
`),
|
|
83
|
+
deleteOld: this.db.prepare(`
|
|
84
|
+
DELETE FROM sync_history WHERE started_at < ?
|
|
85
|
+
`),
|
|
86
|
+
count: this.db.prepare(`
|
|
87
|
+
SELECT COUNT(*) as count FROM sync_history
|
|
88
|
+
`),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
rowToEntry(row) {
|
|
92
|
+
return {
|
|
93
|
+
id: row.id,
|
|
94
|
+
startedAt: row.started_at,
|
|
95
|
+
completedAt: row.completed_at,
|
|
96
|
+
status: row.status,
|
|
97
|
+
skillsAdded: row.skills_added,
|
|
98
|
+
skillsUpdated: row.skills_updated,
|
|
99
|
+
skillsUnchanged: row.skills_unchanged,
|
|
100
|
+
errorMessage: row.error_message,
|
|
101
|
+
durationMs: row.duration_ms,
|
|
102
|
+
createdAt: row.created_at,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Start a new sync run
|
|
107
|
+
* @returns The sync run ID
|
|
108
|
+
*/
|
|
109
|
+
startRun() {
|
|
110
|
+
const id = generateSyncId();
|
|
111
|
+
const startedAt = new Date().toISOString();
|
|
112
|
+
this.stmts.insert.run(id, startedAt);
|
|
113
|
+
return id;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Complete a sync run successfully
|
|
117
|
+
*/
|
|
118
|
+
completeRun(id, result) {
|
|
119
|
+
const completedAt = new Date().toISOString();
|
|
120
|
+
const entry = this.stmts.getById.get(id);
|
|
121
|
+
if (!entry) {
|
|
122
|
+
throw new Error(`Sync run not found: ${id}`);
|
|
123
|
+
}
|
|
124
|
+
const durationMs = new Date(completedAt).getTime() - new Date(entry.started_at).getTime();
|
|
125
|
+
// Determine status based on results
|
|
126
|
+
const status = result.skillsAdded > 0 || result.skillsUpdated > 0 ? 'success' : 'success';
|
|
127
|
+
this.stmts.complete.run(completedAt, status, result.skillsAdded, result.skillsUpdated, result.skillsUnchanged, durationMs, id);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Mark a sync run as partially complete (some errors)
|
|
131
|
+
*/
|
|
132
|
+
completeRunPartial(id, result, errorMessage) {
|
|
133
|
+
const completedAt = new Date().toISOString();
|
|
134
|
+
const entry = this.stmts.getById.get(id);
|
|
135
|
+
if (!entry) {
|
|
136
|
+
throw new Error(`Sync run not found: ${id}`);
|
|
137
|
+
}
|
|
138
|
+
const durationMs = new Date(completedAt).getTime() - new Date(entry.started_at).getTime();
|
|
139
|
+
// Use raw SQL for partial status since we need to include error
|
|
140
|
+
this.db
|
|
141
|
+
.prepare(`
|
|
142
|
+
UPDATE sync_history
|
|
143
|
+
SET completed_at = ?, status = 'partial', skills_added = ?, skills_updated = ?, skills_unchanged = ?, error_message = ?, duration_ms = ?
|
|
144
|
+
WHERE id = ?
|
|
145
|
+
`)
|
|
146
|
+
.run(completedAt, result.skillsAdded, result.skillsUpdated, result.skillsUnchanged, errorMessage, durationMs, id);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Mark a sync run as failed
|
|
150
|
+
*/
|
|
151
|
+
failRun(id, error) {
|
|
152
|
+
const completedAt = new Date().toISOString();
|
|
153
|
+
const entry = this.stmts.getById.get(id);
|
|
154
|
+
if (!entry) {
|
|
155
|
+
throw new Error(`Sync run not found: ${id}`);
|
|
156
|
+
}
|
|
157
|
+
const durationMs = new Date(completedAt).getTime() - new Date(entry.started_at).getTime();
|
|
158
|
+
this.stmts.fail.run(completedAt, error, durationMs, id);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get a specific sync run by ID
|
|
162
|
+
*/
|
|
163
|
+
getById(id) {
|
|
164
|
+
const row = this.stmts.getById.get(id);
|
|
165
|
+
return row ? this.rowToEntry(row) : null;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get sync history (most recent first)
|
|
169
|
+
*/
|
|
170
|
+
getHistory(limit = 10) {
|
|
171
|
+
const rows = this.stmts.getHistory.all(limit);
|
|
172
|
+
return rows.map((row) => this.rowToEntry(row));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get the last successful sync run
|
|
176
|
+
*/
|
|
177
|
+
getLastSuccessful() {
|
|
178
|
+
const row = this.stmts.getLastSuccessful.get();
|
|
179
|
+
return row ? this.rowToEntry(row) : null;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get any currently running sync operations
|
|
183
|
+
*/
|
|
184
|
+
getRunning() {
|
|
185
|
+
const rows = this.stmts.getRunning.all();
|
|
186
|
+
return rows.map((row) => this.rowToEntry(row));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Check if a sync is currently running
|
|
190
|
+
*/
|
|
191
|
+
isRunning() {
|
|
192
|
+
return this.getRunning().length > 0;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Clean up old history entries
|
|
196
|
+
* @param daysToKeep Number of days of history to retain
|
|
197
|
+
*/
|
|
198
|
+
cleanup(daysToKeep = 30) {
|
|
199
|
+
const cutoff = new Date();
|
|
200
|
+
cutoff.setDate(cutoff.getDate() - daysToKeep);
|
|
201
|
+
const result = this.stmts.deleteOld.run(cutoff.toISOString());
|
|
202
|
+
return result.changes;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get total count of history entries
|
|
206
|
+
*/
|
|
207
|
+
count() {
|
|
208
|
+
const result = this.stmts.count.get();
|
|
209
|
+
return result.count;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Get sync statistics
|
|
213
|
+
*/
|
|
214
|
+
getStats() {
|
|
215
|
+
const stats = this.db
|
|
216
|
+
.prepare(`
|
|
217
|
+
SELECT
|
|
218
|
+
COUNT(*) as total_runs,
|
|
219
|
+
SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as successful_runs,
|
|
220
|
+
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_runs,
|
|
221
|
+
MAX(CASE WHEN status = 'success' THEN completed_at ELSE NULL END) as last_success_at,
|
|
222
|
+
AVG(CASE WHEN status = 'success' THEN duration_ms ELSE NULL END) as avg_duration_ms
|
|
223
|
+
FROM sync_history
|
|
224
|
+
`)
|
|
225
|
+
.get();
|
|
226
|
+
return {
|
|
227
|
+
totalRuns: stats.total_runs,
|
|
228
|
+
successfulRuns: stats.successful_runs ?? 0,
|
|
229
|
+
failedRuns: stats.failed_runs ?? 0,
|
|
230
|
+
lastSuccessAt: stats.last_success_at,
|
|
231
|
+
averageDurationMs: stats.avg_duration_ms ? Math.round(stats.avg_duration_ms) : null,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=SyncHistoryRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncHistoryRepository.js","sourceRoot":"","sources":["../../../src/repositories/SyncHistoryRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,21 @@
|
|
|
3
3
|
* SMI-1445: Added GitHub App authentication support
|
|
4
4
|
*/
|
|
5
5
|
import { SearchQuery, ImportedSkill } from './types.js';
|
|
6
|
+
export interface RateLimitInfo {
|
|
7
|
+
remaining: number;
|
|
8
|
+
limit: number;
|
|
9
|
+
resetTime: Date;
|
|
10
|
+
used: number;
|
|
11
|
+
}
|
|
12
|
+
export interface RateLimitStatus {
|
|
13
|
+
core: RateLimitInfo | null;
|
|
14
|
+
search: RateLimitInfo | null;
|
|
15
|
+
}
|
|
16
|
+
declare let getRateLimitStatus: () => Promise<RateLimitStatus>;
|
|
17
|
+
/**
|
|
18
|
+
* Display rate limit status from response headers (lightweight, no API call).
|
|
19
|
+
*/
|
|
20
|
+
export declare function displayRateLimitFromHeaders(response: Response, label?: string): void;
|
|
6
21
|
/**
|
|
7
22
|
* Fetches a URL with exponential backoff retry logic.
|
|
8
23
|
* Handles rate limiting (429) and server errors (5xx).
|
|
@@ -18,6 +33,15 @@ export declare function fetchWithRetry(url: string, options?: RequestInit): Prom
|
|
|
18
33
|
* Tries GitHub App authentication first (5K req/hr), then falls back to PAT.
|
|
19
34
|
*/
|
|
20
35
|
export declare function getGitHubHeaders(): Promise<Record<string, string>>;
|
|
36
|
+
export { getRateLimitStatus };
|
|
37
|
+
/**
|
|
38
|
+
* Initialize rate limit tracking at the start of an import.
|
|
39
|
+
*/
|
|
40
|
+
export declare function initRateLimitTracking(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Display a summary of rate limit usage during the import session.
|
|
43
|
+
*/
|
|
44
|
+
export declare function displayRateLimitSummary(): Promise<void>;
|
|
21
45
|
/** Check and display GitHub rate limit status */
|
|
22
46
|
export declare function checkRateLimit(): Promise<void>;
|
|
23
47
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-client.d.ts","sourceRoot":"","sources":["../../../../src/scripts/github-import/github-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAU,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"github-client.d.ts","sourceRoot":"","sources":["../../../../src/scripts/github-import/github-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAU,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAO/D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,IAAI,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;CAC7B;AAYD,QAAA,IAAI,kBAAkB,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAA;AAEtD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,SAAe,GAAG,IAAI,CAU1F;AAmOD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmD9F;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAmBxE;AAqDD,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAE7B;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAO3D;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAuB7D;AAED,iDAAiD;AACjD,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA4BpD;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,WAAW,EACxB,SAAS,SAAI,EACb,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACpD,OAAO,CAAC,aAAa,EAAE,CAAC,CAwG1B"}
|