@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.
Files changed (87) hide show
  1. package/README.md +1 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/analytics/AnalyticsRepository.d.ts +4 -0
  4. package/dist/src/analytics/AnalyticsRepository.d.ts.map +1 -1
  5. package/dist/src/analytics/AnalyticsRepository.js +26 -44
  6. package/dist/src/analytics/AnalyticsRepository.js.map +1 -1
  7. package/dist/src/api/client.d.ts +8 -8
  8. package/dist/src/api/client.d.ts.map +1 -1
  9. package/dist/src/api/client.js +2 -2
  10. package/dist/src/api/client.js.map +1 -1
  11. package/dist/src/db/schema.d.ts +1 -1
  12. package/dist/src/db/schema.d.ts.map +1 -1
  13. package/dist/src/db/schema.js +41 -1
  14. package/dist/src/db/schema.js.map +1 -1
  15. package/dist/src/index.d.ts +1 -0
  16. package/dist/src/index.d.ts.map +1 -1
  17. package/dist/src/index.js +2 -0
  18. package/dist/src/index.js.map +1 -1
  19. package/dist/src/repositories/SyncConfigRepository.d.ts +91 -0
  20. package/dist/src/repositories/SyncConfigRepository.d.ts.map +1 -0
  21. package/dist/src/repositories/SyncConfigRepository.js +202 -0
  22. package/dist/src/repositories/SyncConfigRepository.js.map +1 -0
  23. package/dist/src/repositories/SyncHistoryRepository.d.ts +104 -0
  24. package/dist/src/repositories/SyncHistoryRepository.d.ts.map +1 -0
  25. package/dist/src/repositories/SyncHistoryRepository.js +235 -0
  26. package/dist/src/repositories/SyncHistoryRepository.js.map +1 -0
  27. package/dist/src/scripts/github-import/github-client.d.ts +24 -0
  28. package/dist/src/scripts/github-import/github-client.d.ts.map +1 -1
  29. package/dist/src/scripts/github-import/github-client.js +103 -0
  30. package/dist/src/scripts/github-import/github-client.js.map +1 -1
  31. package/dist/src/scripts/github-import/index.js +3 -10
  32. package/dist/src/scripts/github-import/index.js.map +1 -1
  33. package/dist/src/scripts/merge-skills.d.ts +56 -0
  34. package/dist/src/scripts/merge-skills.d.ts.map +1 -0
  35. package/dist/src/scripts/merge-skills.js +411 -0
  36. package/dist/src/scripts/merge-skills.js.map +1 -0
  37. package/dist/src/scripts/skill-scanner/index.d.ts +9 -2
  38. package/dist/src/scripts/skill-scanner/index.d.ts.map +1 -1
  39. package/dist/src/scripts/skill-scanner/index.js +98 -7
  40. package/dist/src/scripts/skill-scanner/index.js.map +1 -1
  41. package/dist/src/scripts/skill-scanner/logger.d.ts +51 -0
  42. package/dist/src/scripts/skill-scanner/logger.d.ts.map +1 -1
  43. package/dist/src/scripts/skill-scanner/logger.js +255 -1
  44. package/dist/src/scripts/skill-scanner/logger.js.map +1 -1
  45. package/dist/src/scripts/skill-scanner/reporter.d.ts +1 -1
  46. package/dist/src/scripts/skill-scanner/reporter.d.ts.map +1 -1
  47. package/dist/src/scripts/skill-scanner/reporter.js +67 -15
  48. package/dist/src/scripts/skill-scanner/reporter.js.map +1 -1
  49. package/dist/src/scripts/skill-scanner/scanner.d.ts +5 -2
  50. package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
  51. package/dist/src/scripts/skill-scanner/scanner.js +156 -39
  52. package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
  53. package/dist/src/scripts/skill-scanner/types.d.ts +44 -0
  54. package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -1
  55. package/dist/src/security/scanner/SecurityScanner.d.ts +2 -0
  56. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  57. package/dist/src/security/scanner/SecurityScanner.js +51 -2
  58. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  59. package/dist/src/sync/BackgroundSyncService.d.ts +90 -0
  60. package/dist/src/sync/BackgroundSyncService.d.ts.map +1 -0
  61. package/dist/src/sync/BackgroundSyncService.js +214 -0
  62. package/dist/src/sync/BackgroundSyncService.js.map +1 -0
  63. package/dist/src/sync/SyncEngine.d.ts +76 -0
  64. package/dist/src/sync/SyncEngine.d.ts.map +1 -0
  65. package/dist/src/sync/SyncEngine.js +284 -0
  66. package/dist/src/sync/SyncEngine.js.map +1 -0
  67. package/dist/src/sync/index.d.ts +11 -0
  68. package/dist/src/sync/index.d.ts.map +1 -0
  69. package/dist/src/sync/index.js +14 -0
  70. package/dist/src/sync/index.js.map +1 -0
  71. package/dist/src/types.d.ts +3 -0
  72. package/dist/src/types.d.ts.map +1 -1
  73. package/dist/tests/security/ContinuousSecurity.test.js +10 -12
  74. package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
  75. package/dist/tests/sync/SyncConfigRepository.test.d.ts +7 -0
  76. package/dist/tests/sync/SyncConfigRepository.test.d.ts.map +1 -0
  77. package/dist/tests/sync/SyncConfigRepository.test.js +154 -0
  78. package/dist/tests/sync/SyncConfigRepository.test.js.map +1 -0
  79. package/dist/tests/sync/SyncEngine.test.d.ts +7 -0
  80. package/dist/tests/sync/SyncEngine.test.d.ts.map +1 -0
  81. package/dist/tests/sync/SyncEngine.test.js +300 -0
  82. package/dist/tests/sync/SyncEngine.test.js.map +1 -0
  83. package/dist/tests/sync/SyncHistoryRepository.test.d.ts +7 -0
  84. package/dist/tests/sync/SyncHistoryRepository.test.d.ts.map +1 -0
  85. package/dist/tests/sync/SyncHistoryRepository.test.js +220 -0
  86. package/dist/tests/sync/SyncHistoryRepository.test.js.map +1 -0
  87. 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;AAoO/D;;;;;;;;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;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,CAqG1B"}
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"}