File size: 7,450 Bytes
34367da
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// @ts-nocheck - better-sqlite3 not yet installed
// import Database from 'better-sqlite3';
import { getDatabaseAdapter } from '../platform/db/PrismaDatabaseAdapter.js';

// Placeholder type
type Database = any;
import { logger } from '../utils/logger.js';
import fs from 'fs';
import path from 'path';

/**

 * SQLite to PostgreSQL Migration Script

 * 

 * This script migrates data from the old SQLite database to the new PostgreSQL database.

 * Run this AFTER starting Docker containers and running Prisma migrations.

 */

interface MigrationStats {
    table: string;
    migrated: number;
    failed: number;
}

async function migrateSQLiteToPostgres() {
    logger.info('๐Ÿš€ Starting SQLite -> PostgreSQL migration...');

    const stats: MigrationStats[] = [];

    // Check if SQLite database exists
    const sqlitePath = path.join(process.cwd(), 'widget-tdc.db');
    if (!fs.existsSync(sqlitePath)) {
        logger.warn('โš ๏ธ  No SQLite database found. Skipping migration.');
        return;
    }

    const sqlite = new Database(sqlitePath, { readonly: true });
    const prisma = getDatabaseAdapter().getClient();

    try {
        // Migrate Widgets
        logger.info('๐Ÿ“ฆ Migrating widgets...');
        const widgets = sqlite.prepare('SELECT * FROM widgets').all() as any[];
        let widgetCount = 0;
        for (const widget of widgets) {
            try {
                await prisma.widget.upsert({
                    where: { id: widget.id },
                    create: {
                        id: widget.id,
                        name: widget.name,
                        type: widget.type,
                        config: widget.config ? JSON.parse(widget.config) : null,
                        active: Boolean(widget.active),
                        createdAt: new Date(widget.created_at),
                        updatedAt: new Date(widget.updated_at || widget.created_at),
                    },
                    update: {},
                });
                widgetCount++;
            } catch (err: any) {
                logger.error(`Failed to migrate widget ${widget.id}:`, err.message);
            }
        }
        stats.push({ table: 'widgets', migrated: widgetCount, failed: widgets.length - widgetCount });

        // Migrate Layouts
        logger.info('๐Ÿ“ Migrating layouts...');
        const layouts = sqlite.prepare('SELECT * FROM layouts').all() as any[];
        let layoutCount = 0;
        for (const layout of layouts) {
            try {
                await prisma.layout.upsert({
                    where: { userId_orgId: { userId: layout.user_id, orgId: layout.org_id } },
                    create: {
                        userId: layout.user_id,
                        orgId: layout.org_id,
                        layoutData: JSON.parse(layout.layout_data),
                        createdAt: new Date(layout.created_at),
                        updatedAt: new Date(layout.updated_at || layout.created_at),
                    },
                    update: {},
                });
                layoutCount++;
            } catch (err: any) {
                logger.error(`Failed to migrate layout for user ${layout.user_id}:`, err.message);
            }
        }
        stats.push({ table: 'layouts', migrated: layoutCount, failed: layouts.length - layoutCount });

        // Migrate Memory Entities
        logger.info('๐Ÿง  Migrating memory entities...');
        try {
            const entities = sqlite.prepare('SELECT * FROM memory_entities').all() as any[];
            let entityCount = 0;
            for (const entity of entities) {
                try {
                    await prisma.memoryEntity.upsert({
                        where: { id: entity.id },
                        create: {
                            id: entity.id,
                            type: entity.type,
                            label: entity.label,
                            properties: entity.properties ? JSON.parse(entity.properties) : null,
                            userId: entity.user_id || 'system',
                            orgId: entity.org_id || 'default',
                            createdAt: new Date(entity.created_at),
                            updatedAt: new Date(entity.updated_at || entity.created_at),
                        },
                        update: {},
                    });
                    entityCount++;
                } catch (err: any) {
                    logger.error(`Failed to migrate entity ${entity.id}:`, err.message);
                }
            }
            stats.push({ table: 'memory_entities', migrated: entityCount, failed: entities.length - entityCount });
        } catch (err: any) {
            logger.warn('memory_entities table not found in SQLite, skipping');
            stats.push({ table: 'memory_entities', migrated: 0, failed: 0 });
        }

        // Migrate Data Sources
        logger.info('๐Ÿ“ก Migrating data sources...');
        try {
            const sources = sqlite.prepare('SELECT * FROM data_sources').all() as any[];
            let sourceCount = 0;
            for (const source of sources) {
                try {
                    await prisma.dataSource.upsert({
                        where: { name: source.name },
                        create: {
                            name: source.name,
                            type: source.type,
                            description: source.description,
                            enabled: Boolean(source.enabled),
                            requiresApproval: Boolean(source.requires_approval ?? true),
                            config: source.config ? JSON.parse(source.config) : null,
                            lastUsedAt: source.last_used_at ? new Date(source.last_used_at) : null,
                            createdAt: new Date(source.created_at),
                            updatedAt: new Date(source.updated_at || source.created_at),
                        },
                        update: {},
                    });
                    sourceCount++;
                } catch (err: any) {
                    logger.error(`Failed to migrate data source ${source.name}:`, err.message);
                }
            }
            stats.push({ table: 'data_sources', migrated: sourceCount, failed: sources.length - sourceCount });
        } catch (err: any) {
            logger.warn('data_sources table not found in SQLite, skipping');
            stats.push({ table: 'data_sources', migrated: 0, failed: 0 });
        }

        // Print migration summary
        logger.info('\nโœ… Migration Complete!\n');
        console.table(stats);

    } catch (error: any) {
        logger.error('โŒ Migration failed:', { error: error.message });
        throw error;
    } finally {
        sqlite.close();
    }
}

// Run migration if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
    migrateSQLiteToPostgres()
        .then(() => {
            logger.info('๐ŸŽ‰ Migration successful!');
            process.exit(0);
        })
        .catch((err) => {
            logger.error('Migration error:', err);
            process.exit(1);
        });
}

export { migrateSQLiteToPostgres };