cursor-history 0.5.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +385 -2
  3. package/dist/cli/commands/backup.d.ts +9 -0
  4. package/dist/cli/commands/backup.d.ts.map +1 -0
  5. package/dist/cli/commands/backup.js +168 -0
  6. package/dist/cli/commands/backup.js.map +1 -0
  7. package/dist/cli/commands/export.d.ts.map +1 -1
  8. package/dist/cli/commands/export.js +39 -7
  9. package/dist/cli/commands/export.js.map +1 -1
  10. package/dist/cli/commands/list-backups.d.ts +9 -0
  11. package/dist/cli/commands/list-backups.d.ts.map +1 -0
  12. package/dist/cli/commands/list-backups.js +166 -0
  13. package/dist/cli/commands/list-backups.js.map +1 -0
  14. package/dist/cli/commands/list.d.ts.map +1 -1
  15. package/dist/cli/commands/list.js +44 -9
  16. package/dist/cli/commands/list.js.map +1 -1
  17. package/dist/cli/commands/migrate-session.d.ts +12 -0
  18. package/dist/cli/commands/migrate-session.d.ts.map +1 -0
  19. package/dist/cli/commands/migrate-session.js +125 -0
  20. package/dist/cli/commands/migrate-session.js.map +1 -0
  21. package/dist/cli/commands/migrate.d.ts +13 -0
  22. package/dist/cli/commands/migrate.d.ts.map +1 -0
  23. package/dist/cli/commands/migrate.js +122 -0
  24. package/dist/cli/commands/migrate.js.map +1 -0
  25. package/dist/cli/commands/restore.d.ts +9 -0
  26. package/dist/cli/commands/restore.d.ts.map +1 -0
  27. package/dist/cli/commands/restore.js +192 -0
  28. package/dist/cli/commands/restore.js.map +1 -0
  29. package/dist/cli/commands/search.d.ts.map +1 -1
  30. package/dist/cli/commands/search.js +31 -3
  31. package/dist/cli/commands/search.js.map +1 -1
  32. package/dist/cli/commands/show.d.ts.map +1 -1
  33. package/dist/cli/commands/show.js +32 -4
  34. package/dist/cli/commands/show.js.map +1 -1
  35. package/dist/cli/errors.d.ts +56 -0
  36. package/dist/cli/errors.d.ts.map +1 -0
  37. package/dist/cli/errors.js +90 -0
  38. package/dist/cli/errors.js.map +1 -0
  39. package/dist/cli/index.js +11 -1
  40. package/dist/cli/index.js.map +1 -1
  41. package/dist/core/backup.d.ts +89 -0
  42. package/dist/core/backup.d.ts.map +1 -0
  43. package/dist/core/backup.js +709 -0
  44. package/dist/core/backup.js.map +1 -0
  45. package/dist/core/migrate.d.ts +40 -0
  46. package/dist/core/migrate.d.ts.map +1 -0
  47. package/dist/core/migrate.js +586 -0
  48. package/dist/core/migrate.js.map +1 -0
  49. package/dist/core/storage.d.ts +78 -6
  50. package/dist/core/storage.d.ts.map +1 -1
  51. package/dist/core/storage.js +327 -45
  52. package/dist/core/storage.js.map +1 -1
  53. package/dist/core/types.d.ts +280 -0
  54. package/dist/core/types.d.ts.map +1 -1
  55. package/dist/lib/backup.d.ts +98 -0
  56. package/dist/lib/backup.d.ts.map +1 -0
  57. package/dist/lib/backup.js +108 -0
  58. package/dist/lib/backup.js.map +1 -0
  59. package/dist/lib/config.d.ts +33 -0
  60. package/dist/lib/config.d.ts.map +1 -0
  61. package/dist/lib/config.js +81 -0
  62. package/dist/lib/config.js.map +1 -0
  63. package/dist/lib/errors.d.ts +257 -30
  64. package/dist/lib/errors.d.ts.map +1 -1
  65. package/dist/lib/errors.js +404 -54
  66. package/dist/lib/errors.js.map +1 -1
  67. package/dist/lib/index.d.ts +219 -0
  68. package/dist/lib/index.d.ts.map +1 -0
  69. package/dist/lib/index.js +520 -0
  70. package/dist/lib/index.js.map +1 -0
  71. package/dist/lib/platform.d.ts +11 -0
  72. package/dist/lib/platform.d.ts.map +1 -1
  73. package/dist/lib/platform.js +32 -0
  74. package/dist/lib/platform.js.map +1 -1
  75. package/dist/lib/types.d.ts +374 -0
  76. package/dist/lib/types.d.ts.map +1 -0
  77. package/dist/lib/types.js +9 -0
  78. package/dist/lib/types.js.map +1 -0
  79. package/dist/lib/utils.d.ts +17 -0
  80. package/dist/lib/utils.d.ts.map +1 -0
  81. package/dist/lib/utils.js +20 -0
  82. package/dist/lib/utils.js.map +1 -0
  83. package/package.json +32 -4
@@ -0,0 +1,520 @@
1
+ /**
2
+ * cursor-history Library API
3
+ *
4
+ * IMPORTANT: This is a library interface for direct import and use in TypeScript/JavaScript
5
+ * projects, NOT a network/REST API. Functions are imported directly:
6
+ * `import { listSessions, getSession, searchSessions } from 'cursor-history'`
7
+ */
8
+ // Export error classes
9
+ export { DatabaseLockedError, DatabaseNotFoundError, InvalidConfigError, SessionNotFoundError, WorkspaceNotFoundError, SameWorkspaceError, NoSessionsFoundError, DestinationHasSessionsError,
10
+ // Backup errors
11
+ BackupError, NoDataError, FileExistsError, InsufficientSpaceError, RestoreError, BackupNotFoundError, InvalidBackupError, TargetExistsError, IntegrityError,
12
+ // Type guards
13
+ isDatabaseLockedError, isDatabaseNotFoundError, isInvalidConfigError, isSessionNotFoundError, isWorkspaceNotFoundError, isSameWorkspaceError, isNoSessionsFoundError, isDestinationHasSessionsError,
14
+ // Backup type guards
15
+ isBackupError, isNoDataError, isFileExistsError, isInsufficientSpaceError, isRestoreError, isBackupNotFoundError, isInvalidBackupError, isTargetExistsError, isIntegrityError, } from './errors.js';
16
+ // Export utility functions
17
+ export { getDefaultDataPath } from './utils.js';
18
+ import { mergeWithDefaults } from './config.js';
19
+ import { DatabaseLockedError, DatabaseNotFoundError } from './errors.js';
20
+ import * as storage from '../core/storage.js';
21
+ import * as migrate from '../core/migrate.js';
22
+ import { exportToJson, exportToMarkdown } from '../core/parser.js';
23
+ import { expandPath } from './platform.js';
24
+ /**
25
+ * Convert core ChatSession to library Session
26
+ */
27
+ function convertToLibrarySession(coreSession) {
28
+ return {
29
+ id: coreSession.id,
30
+ workspace: coreSession.workspacePath ?? 'unknown',
31
+ timestamp: coreSession.createdAt.toISOString(),
32
+ messages: coreSession.messages.map((msg) => ({
33
+ role: msg.role === 'user' ? 'user' : 'assistant',
34
+ content: msg.content,
35
+ timestamp: msg.timestamp.toISOString(),
36
+ toolCalls: msg.toolCalls,
37
+ thinking: msg.thinking,
38
+ metadata: msg.metadata,
39
+ })),
40
+ messageCount: coreSession.messageCount,
41
+ metadata: {
42
+ lastModified: coreSession.lastUpdatedAt.toISOString(),
43
+ },
44
+ };
45
+ }
46
+ /**
47
+ * List all chat sessions, optionally filtered and paginated.
48
+ *
49
+ * @param config - Optional configuration (dataPath, workspace filter, pagination)
50
+ * @returns Paginated result with sessions and metadata
51
+ * @throws {DatabaseLockedError} If database is locked by Cursor
52
+ * @throws {DatabaseNotFoundError} If database path does not exist
53
+ * @throws {InvalidConfigError} If config parameters are invalid
54
+ *
55
+ * @example
56
+ * // List all sessions
57
+ * const result = listSessions();
58
+ * console.log(result.data); // Session[]
59
+ *
60
+ * @example
61
+ * // List sessions with pagination
62
+ * const page1 = listSessions({ limit: 10, offset: 0 });
63
+ * const page2 = listSessions({ limit: 10, offset: 10 });
64
+ *
65
+ * @example
66
+ * // List sessions for specific workspace
67
+ * const result = listSessions({ workspace: '/path/to/project' });
68
+ */
69
+ export function listSessions(config) {
70
+ try {
71
+ const resolved = mergeWithDefaults(config);
72
+ // Get all sessions using core storage layer
73
+ const coreSessions = storage.listSessions({
74
+ limit: -1, // Get all, we'll paginate ourselves
75
+ all: true,
76
+ workspacePath: resolved.workspace,
77
+ }, resolved.dataPath, resolved.backupPath);
78
+ // Total count before pagination
79
+ const total = coreSessions.length;
80
+ // Apply offset and limit
81
+ const start = resolved.offset;
82
+ const end = Math.min(start + resolved.limit, total);
83
+ const paginatedSessions = coreSessions.slice(start, end);
84
+ // Convert to library Session format
85
+ // We need full sessions, not summaries, so we'll fetch each one
86
+ const sessions = paginatedSessions.map((summary) => {
87
+ const fullSession = storage.getSession(summary.index, resolved.dataPath, resolved.backupPath);
88
+ if (!fullSession) {
89
+ throw new DatabaseNotFoundError(`Session ${summary.index} not found`);
90
+ }
91
+ return convertToLibrarySession(fullSession);
92
+ });
93
+ return {
94
+ data: sessions,
95
+ pagination: {
96
+ total,
97
+ limit: resolved.limit,
98
+ offset: resolved.offset,
99
+ hasMore: end < total,
100
+ },
101
+ };
102
+ }
103
+ catch (err) {
104
+ // Check for SQLite BUSY error (database locked)
105
+ if (err instanceof Error && err.message.includes('SQLITE_BUSY')) {
106
+ throw new DatabaseLockedError(config?.dataPath ?? 'default path');
107
+ }
108
+ // Check for file not found errors
109
+ if (err instanceof Error && (err.message.includes('ENOENT') || err.message.includes('no such file'))) {
110
+ throw new DatabaseNotFoundError(config?.dataPath ?? 'default path');
111
+ }
112
+ // Re-throw library errors as-is
113
+ if (err instanceof DatabaseLockedError || err instanceof DatabaseNotFoundError) {
114
+ throw err;
115
+ }
116
+ // Wrap other errors
117
+ throw new Error(`Failed to list sessions: ${err instanceof Error ? err.message : String(err)}`);
118
+ }
119
+ }
120
+ /**
121
+ * Get a specific session by index.
122
+ *
123
+ * @param index - Zero-based session index (from listSessions result)
124
+ * @param config - Optional configuration (dataPath)
125
+ * @returns Complete session with all messages
126
+ * @throws {DatabaseLockedError} If database is locked by Cursor
127
+ * @throws {DatabaseNotFoundError} If database path does not exist
128
+ * @throws {InvalidConfigError} If index is out of bounds
129
+ *
130
+ * @example
131
+ * const session = getSession(0);
132
+ * console.log(session.messages); // Message[]
133
+ *
134
+ * @example
135
+ * // Get session from custom data path
136
+ * const session = getSession(5, { dataPath: '/custom/cursor/data' });
137
+ */
138
+ export function getSession(index, config) {
139
+ try {
140
+ const resolved = mergeWithDefaults(config);
141
+ // Core storage uses 1-based indexing, so we add 1
142
+ const coreIndex = index + 1;
143
+ const coreSession = storage.getSession(coreIndex, resolved.dataPath, resolved.backupPath);
144
+ if (!coreSession) {
145
+ throw new DatabaseNotFoundError(`Session at index ${index} not found`);
146
+ }
147
+ return convertToLibrarySession(coreSession);
148
+ }
149
+ catch (err) {
150
+ // Check for SQLite BUSY error (database locked)
151
+ if (err instanceof Error && err.message.includes('SQLITE_BUSY')) {
152
+ throw new DatabaseLockedError(config?.dataPath ?? 'default path');
153
+ }
154
+ // Check for file not found errors
155
+ if (err instanceof Error && (err.message.includes('ENOENT') || err.message.includes('no such file'))) {
156
+ throw new DatabaseNotFoundError(config?.dataPath ?? 'default path');
157
+ }
158
+ // Re-throw library errors as-is
159
+ if (err instanceof DatabaseLockedError || err instanceof DatabaseNotFoundError) {
160
+ throw err;
161
+ }
162
+ // Wrap other errors
163
+ throw new Error(`Failed to get session: ${err instanceof Error ? err.message : String(err)}`);
164
+ }
165
+ }
166
+ /**
167
+ * Search across all sessions for matching content.
168
+ *
169
+ * @param query - Search query string (case-insensitive substring match)
170
+ * @param config - Optional configuration (dataPath, workspace filter, context lines)
171
+ * @returns Array of search results with context
172
+ * @throws {DatabaseLockedError} If database is locked by Cursor
173
+ * @throws {DatabaseNotFoundError} If database path does not exist
174
+ *
175
+ * @example
176
+ * // Basic search
177
+ * const results = searchSessions('authentication');
178
+ *
179
+ * @example
180
+ * // Search with context lines
181
+ * const results = searchSessions('error', { context: 2 });
182
+ * results.forEach(r => {
183
+ * console.log(r.contextBefore); // 2 lines before match
184
+ * console.log(r.match); // matched line
185
+ * console.log(r.contextAfter); // 2 lines after match
186
+ * });
187
+ *
188
+ * @example
189
+ * // Search within specific workspace
190
+ * const results = searchSessions('bug', { workspace: '/path/to/project' });
191
+ */
192
+ export function searchSessions(query, config) {
193
+ try {
194
+ const resolved = mergeWithDefaults(config);
195
+ // Search using core storage layer
196
+ const coreResults = storage.searchSessions(query, {
197
+ limit: resolved.limit === Number.MAX_SAFE_INTEGER ? 0 : resolved.limit,
198
+ contextChars: resolved.context * 80, // Rough estimate: 1 line = 80 chars
199
+ workspacePath: resolved.workspace,
200
+ }, resolved.dataPath, resolved.backupPath);
201
+ // Convert core results to library format
202
+ return coreResults.map((coreResult) => {
203
+ // Get full session for reference
204
+ const fullSession = storage.getSession(coreResult.index, resolved.dataPath, resolved.backupPath);
205
+ if (!fullSession) {
206
+ throw new DatabaseNotFoundError(`Session ${coreResult.index} not found`);
207
+ }
208
+ // Find the first match to get offset and context
209
+ const firstSnippet = coreResult.snippets[0];
210
+ const match = firstSnippet?.text ?? '';
211
+ const offset = firstSnippet?.matchPositions[0]?.[0] ?? 0;
212
+ // Extract context lines (split by newlines)
213
+ const lines = match.split('\n');
214
+ const contextBefore = [];
215
+ const contextAfter = [];
216
+ // Find the line containing the match
217
+ let matchLineIndex = 0;
218
+ for (let i = 0; i < lines.length; i++) {
219
+ const line = lines[i];
220
+ if (line && line.includes(query)) {
221
+ matchLineIndex = i;
222
+ break;
223
+ }
224
+ }
225
+ // Get context lines before and after
226
+ if (resolved.context > 0) {
227
+ const start = Math.max(0, matchLineIndex - resolved.context);
228
+ const end = Math.min(lines.length, matchLineIndex + resolved.context + 1);
229
+ for (let i = start; i < matchLineIndex; i++) {
230
+ const line = lines[i];
231
+ if (line)
232
+ contextBefore.push(line);
233
+ }
234
+ for (let i = matchLineIndex + 1; i < end; i++) {
235
+ const line = lines[i];
236
+ if (line)
237
+ contextAfter.push(line);
238
+ }
239
+ }
240
+ return {
241
+ session: convertToLibrarySession(fullSession),
242
+ match: lines[matchLineIndex] ?? match,
243
+ messageIndex: 0, // Would need to track which message contains the match
244
+ offset,
245
+ contextBefore: contextBefore.length > 0 ? contextBefore : undefined,
246
+ contextAfter: contextAfter.length > 0 ? contextAfter : undefined,
247
+ };
248
+ });
249
+ }
250
+ catch (err) {
251
+ // Check for SQLite BUSY error (database locked)
252
+ if (err instanceof Error && err.message.includes('SQLITE_BUSY')) {
253
+ throw new DatabaseLockedError(config?.dataPath ?? 'default path');
254
+ }
255
+ // Check for file not found errors
256
+ if (err instanceof Error && (err.message.includes('ENOENT') || err.message.includes('no such file'))) {
257
+ throw new DatabaseNotFoundError(config?.dataPath ?? 'default path');
258
+ }
259
+ // Re-throw library errors as-is
260
+ if (err instanceof DatabaseLockedError || err instanceof DatabaseNotFoundError) {
261
+ throw err;
262
+ }
263
+ // Wrap other errors
264
+ throw new Error(`Failed to search sessions: ${err instanceof Error ? err.message : String(err)}`);
265
+ }
266
+ }
267
+ /**
268
+ * Export a session to JSON format.
269
+ *
270
+ * @param index - Zero-based session index (from listSessions result)
271
+ * @param config - Optional configuration (dataPath)
272
+ * @returns JSON string representation of session
273
+ * @throws {DatabaseLockedError} If database is locked by Cursor
274
+ * @throws {DatabaseNotFoundError} If database path does not exist
275
+ * @throws {InvalidConfigError} If index is out of bounds
276
+ *
277
+ * @example
278
+ * const json = exportSessionToJson(0);
279
+ * fs.writeFileSync('session.json', json);
280
+ */
281
+ export function exportSessionToJson(index, config) {
282
+ try {
283
+ const resolved = mergeWithDefaults(config);
284
+ const coreIndex = index + 1; // Convert to 1-based indexing
285
+ const coreSession = storage.getSession(coreIndex, resolved.dataPath, resolved.backupPath);
286
+ if (!coreSession) {
287
+ throw new DatabaseNotFoundError(`Session at index ${index} not found`);
288
+ }
289
+ return exportToJson(coreSession, coreSession.workspacePath);
290
+ }
291
+ catch (err) {
292
+ if (err instanceof DatabaseLockedError || err instanceof DatabaseNotFoundError) {
293
+ throw err;
294
+ }
295
+ throw new Error(`Failed to export session to JSON: ${err instanceof Error ? err.message : String(err)}`);
296
+ }
297
+ }
298
+ /**
299
+ * Export a session to Markdown format.
300
+ *
301
+ * @param index - Zero-based session index (from listSessions result)
302
+ * @param config - Optional configuration (dataPath)
303
+ * @returns Markdown formatted string
304
+ * @throws {DatabaseLockedError} If database is locked by Cursor
305
+ * @throws {DatabaseNotFoundError} If database path does not exist
306
+ * @throws {InvalidConfigError} If index is out of bounds
307
+ *
308
+ * @example
309
+ * const markdown = exportSessionToMarkdown(0);
310
+ * fs.writeFileSync('session.md', markdown);
311
+ */
312
+ export function exportSessionToMarkdown(index, config) {
313
+ try {
314
+ const resolved = mergeWithDefaults(config);
315
+ const coreIndex = index + 1; // Convert to 1-based indexing
316
+ const coreSession = storage.getSession(coreIndex, resolved.dataPath, resolved.backupPath);
317
+ if (!coreSession) {
318
+ throw new DatabaseNotFoundError(`Session at index ${index} not found`);
319
+ }
320
+ return exportToMarkdown(coreSession, coreSession.workspacePath);
321
+ }
322
+ catch (err) {
323
+ if (err instanceof DatabaseLockedError || err instanceof DatabaseNotFoundError) {
324
+ throw err;
325
+ }
326
+ throw new Error(`Failed to export session to Markdown: ${err instanceof Error ? err.message : String(err)}`);
327
+ }
328
+ }
329
+ /**
330
+ * Export all sessions to JSON format.
331
+ *
332
+ * @param config - Optional configuration (dataPath, workspace filter)
333
+ * @returns JSON string with array of all sessions
334
+ * @throws {DatabaseLockedError} If database is locked by Cursor
335
+ * @throws {DatabaseNotFoundError} If database path does not exist
336
+ *
337
+ * @example
338
+ * const json = exportAllSessionsToJson();
339
+ * fs.writeFileSync('all-sessions.json', json);
340
+ *
341
+ * @example
342
+ * // Export sessions from specific workspace
343
+ * const json = exportAllSessionsToJson({ workspace: '/path/to/project' });
344
+ */
345
+ export function exportAllSessionsToJson(config) {
346
+ try {
347
+ const resolved = mergeWithDefaults(config);
348
+ // Get all sessions
349
+ const coreSessions = storage.listSessions({
350
+ limit: -1,
351
+ all: true,
352
+ workspacePath: resolved.workspace,
353
+ }, resolved.dataPath, resolved.backupPath);
354
+ // Export each session
355
+ const exportedSessions = coreSessions.map((summary) => {
356
+ const session = storage.getSession(summary.index, resolved.dataPath, resolved.backupPath);
357
+ if (!session)
358
+ return null;
359
+ return JSON.parse(exportToJson(session, session.workspacePath));
360
+ }).filter((s) => s !== null);
361
+ return JSON.stringify(exportedSessions, null, 2);
362
+ }
363
+ catch (err) {
364
+ if (err instanceof DatabaseLockedError || err instanceof DatabaseNotFoundError) {
365
+ throw err;
366
+ }
367
+ throw new Error(`Failed to export all sessions to JSON: ${err instanceof Error ? err.message : String(err)}`);
368
+ }
369
+ }
370
+ /**
371
+ * Export all sessions to Markdown format.
372
+ *
373
+ * @param config - Optional configuration (dataPath, workspace filter)
374
+ * @returns Markdown formatted string with all sessions
375
+ * @throws {DatabaseLockedError} If database is locked by Cursor
376
+ * @throws {DatabaseNotFoundError} If database path does not exist
377
+ *
378
+ * @example
379
+ * const markdown = exportAllSessionsToMarkdown();
380
+ * fs.writeFileSync('all-sessions.md', markdown);
381
+ */
382
+ export function exportAllSessionsToMarkdown(config) {
383
+ try {
384
+ const resolved = mergeWithDefaults(config);
385
+ // Get all sessions
386
+ const coreSessions = storage.listSessions({
387
+ limit: -1,
388
+ all: true,
389
+ workspacePath: resolved.workspace,
390
+ }, resolved.dataPath, resolved.backupPath);
391
+ // Export each session
392
+ const parts = [];
393
+ for (const summary of coreSessions) {
394
+ const session = storage.getSession(summary.index, resolved.dataPath, resolved.backupPath);
395
+ if (!session)
396
+ continue;
397
+ parts.push(exportToMarkdown(session, session.workspacePath));
398
+ parts.push('\n\n---\n\n'); // Separator between sessions
399
+ }
400
+ return parts.join('');
401
+ }
402
+ catch (err) {
403
+ if (err instanceof DatabaseLockedError || err instanceof DatabaseNotFoundError) {
404
+ throw err;
405
+ }
406
+ throw new Error(`Failed to export all sessions to Markdown: ${err instanceof Error ? err.message : String(err)}`);
407
+ }
408
+ }
409
+ // ============================================================================
410
+ // Migration Functions
411
+ // ============================================================================
412
+ /**
413
+ * Migrate one or more sessions to a different workspace.
414
+ *
415
+ * This is the primary migration function for session-level operations.
416
+ * Supports moving (removing from source) or copying (keeping source intact).
417
+ *
418
+ * @param config - Migration configuration
419
+ * @returns Array of results for each session migrated
420
+ * @throws {SessionNotFoundError} If a session cannot be found
421
+ * @throws {WorkspaceNotFoundError} If destination workspace doesn't exist
422
+ * @throws {SameWorkspaceError} If source and destination are the same
423
+ * @throws {DatabaseLockedError} If database is locked by Cursor
424
+ *
425
+ * @example
426
+ * // Move a single session by index
427
+ * const results = migrateSession({
428
+ * sessions: 3,
429
+ * destination: '/path/to/new/project'
430
+ * });
431
+ *
432
+ * @example
433
+ * // Copy multiple sessions
434
+ * const results = migrateSession({
435
+ * sessions: [1, 3, 5],
436
+ * destination: '/path/to/project',
437
+ * mode: 'copy'
438
+ * });
439
+ *
440
+ * @example
441
+ * // Dry run to preview what would happen
442
+ * const results = migrateSession({
443
+ * sessions: '1,3,5',
444
+ * destination: '/path/to/project',
445
+ * dryRun: true
446
+ * });
447
+ */
448
+ export function migrateSession(config) {
449
+ // Resolve session identifiers to IDs
450
+ const sessionIds = storage.resolveSessionIdentifiers(config.sessions, config.dataPath);
451
+ // Expand ~ in destination path
452
+ const destination = expandPath(config.destination);
453
+ // Call core migration function
454
+ return migrate.migrateSessions({
455
+ sessionIds,
456
+ destination,
457
+ mode: config.mode ?? 'move',
458
+ dryRun: config.dryRun ?? false,
459
+ force: config.force ?? false,
460
+ dataPath: config.dataPath,
461
+ });
462
+ }
463
+ /**
464
+ * Migrate all sessions from one workspace to another.
465
+ *
466
+ * This is a convenience function for workspace-level migration.
467
+ * Uses migrateSession internally for each session in the source workspace.
468
+ *
469
+ * @param config - Workspace migration configuration
470
+ * @returns Aggregate result with per-session details
471
+ * @throws {WorkspaceNotFoundError} If source or destination workspace doesn't exist
472
+ * @throws {SameWorkspaceError} If source and destination are the same
473
+ * @throws {NoSessionsFoundError} If source workspace has no sessions
474
+ * @throws {DestinationHasSessionsError} If destination has sessions and force not set
475
+ * @throws {DatabaseLockedError} If database is locked by Cursor
476
+ *
477
+ * @example
478
+ * // Move all sessions from old to new project
479
+ * const result = migrateWorkspace({
480
+ * source: '/old/project',
481
+ * destination: '/new/project'
482
+ * });
483
+ * console.log(`Migrated ${result.successCount} sessions`);
484
+ *
485
+ * @example
486
+ * // Create backup copy of all sessions
487
+ * const result = migrateWorkspace({
488
+ * source: '/project',
489
+ * destination: '/backup/project',
490
+ * mode: 'copy'
491
+ * });
492
+ *
493
+ * @example
494
+ * // Force merge with existing destination sessions
495
+ * const result = migrateWorkspace({
496
+ * source: '/old/project',
497
+ * destination: '/existing/project',
498
+ * force: true
499
+ * });
500
+ */
501
+ export function migrateWorkspace(config) {
502
+ // Expand ~ in paths
503
+ const source = expandPath(config.source);
504
+ const destination = expandPath(config.destination);
505
+ // Call core migration function
506
+ return migrate.migrateWorkspace({
507
+ source,
508
+ destination,
509
+ mode: config.mode ?? 'move',
510
+ dryRun: config.dryRun ?? false,
511
+ force: config.force ?? false,
512
+ dataPath: config.dataPath,
513
+ });
514
+ }
515
+ // ============================================================================
516
+ // Backup Functions
517
+ // ============================================================================
518
+ // Re-export backup functions from backup module
519
+ export { createBackup, restoreBackup, validateBackup, listBackups, getDefaultBackupDir, } from './backup.js';
520
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"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"}
@@ -22,4 +22,15 @@ export declare function expandPath(path: string): string;
22
22
  * Contract a path by replacing home directory with ~
23
23
  */
24
24
  export declare function contractPath(path: string): string;
25
+ /**
26
+ * Normalize a file path for consistent comparison
27
+ * - Resolves ~ to home directory
28
+ * - Removes trailing slashes
29
+ * - Normalizes path separators
30
+ */
31
+ export declare function normalizePath(filePath: string): string;
32
+ /**
33
+ * Compare two paths for equality (case-sensitive on Unix, case-insensitive on Windows)
34
+ */
35
+ export declare function pathsEqual(path1: string, path2: string): boolean;
25
36
  //# sourceMappingURL=platform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/lib/platform.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;GAEG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CASzC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,CAuBpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAY7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD"}
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/lib/platform.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;GAEG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CASzC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,CAuBpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAY7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgBtD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAShE"}
@@ -63,4 +63,36 @@ export function contractPath(path) {
63
63
  }
64
64
  return path;
65
65
  }
66
+ /**
67
+ * Normalize a file path for consistent comparison
68
+ * - Resolves ~ to home directory
69
+ * - Removes trailing slashes
70
+ * - Normalizes path separators
71
+ */
72
+ export function normalizePath(filePath) {
73
+ // Expand ~ to home directory
74
+ let normalized = filePath;
75
+ if (normalized.startsWith('~')) {
76
+ normalized = join(homedir(), normalized.slice(1));
77
+ }
78
+ // Remove trailing slashes (but keep root /)
79
+ while (normalized.length > 1 && normalized.endsWith('/')) {
80
+ normalized = normalized.slice(0, -1);
81
+ }
82
+ while (normalized.length > 1 && normalized.endsWith('\\')) {
83
+ normalized = normalized.slice(0, -1);
84
+ }
85
+ return normalized;
86
+ }
87
+ /**
88
+ * Compare two paths for equality (case-sensitive on Unix, case-insensitive on Windows)
89
+ */
90
+ export function pathsEqual(path1, path2) {
91
+ const normalized1 = normalizePath(path1);
92
+ const normalized2 = normalizePath(path2);
93
+ if (process.platform === 'win32') {
94
+ return normalized1.toLowerCase() === normalized2.toLowerCase();
95
+ }
96
+ return normalized1 === normalized2;
97
+ }
66
98
  //# sourceMappingURL=platform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/lib/platform.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,QAAQ,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzB,KAAK,OAAO;YACV,OAAO,SAAS,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAmB;IAC1D,MAAM,CAAC,GAAG,QAAQ,IAAI,cAAc,EAAE,CAAC;IAEvC,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,SAAS;YACZ,OAAO,IAAI,CACT,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,EAC/D,QAAQ,EACR,MAAM,EACN,kBAAkB,CACnB,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,IAAI,CACT,OAAO,EAAE,EACT,SAAS,EACT,qBAAqB,EACrB,QAAQ,EACR,MAAM,EACN,kBAAkB,CACnB,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAmB;IACnD,4CAA4C;IAC5C,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,wBAAwB,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/lib/platform.ts"],"names":[],"mappings":"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"}