twenty-migrate-espocrm 1.0.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.
package/.env.example ADDED
@@ -0,0 +1,15 @@
1
+ # EspoCRM API Configuration
2
+ ESPOCRM_URL=http://localhost/espocrm
3
+ ESPOCRM_API_KEY=your_espocrm_api_key_here
4
+ ESPOCRM_USERNAME=your_espocrm_username
5
+ ESPOCRM_PASSWORD=your_espocrm_password
6
+
7
+ # Twenty CRM Configuration
8
+ TWENTY_URL=http://localhost:3000
9
+ TWENTY_API_KEY=your_twenty_api_key_here
10
+
11
+ # Migration Settings
12
+ BATCH_SIZE=60
13
+ RATE_LIMIT_DELAY=600
14
+ DRY_RUN=false
15
+ OBJECTS=contacts,accounts,opportunities,notes
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const extract_1 = require("./extract");
6
+ const transform_1 = require("./transform");
7
+ const load_1 = require("./load");
8
+ const reporter_1 = require("./reporter");
9
+ const program = new commander_1.Command();
10
+ program
11
+ .name('twenty-migrate-espocrm')
12
+ .description('CLI migration tool for EspoCRM to Twenty CRM')
13
+ .version('1.0.0');
14
+ program
15
+ .requiredOption('-u, --url <url>', 'EspoCRM URL')
16
+ .option('-k, --api-key <key>', 'EspoCRM API key (alternative to username/password)')
17
+ .option('-n, --username <username>', 'EspoCRM username (alternative to API key)')
18
+ .option('-p, --password <password>', 'EspoCRM password (alternative to API key)')
19
+ .requiredOption('-t, --twenty-url <url>', 'Twenty CRM URL')
20
+ .requiredOption('-s, --twenty-key <key>', 'Twenty CRM API key')
21
+ .option('-d, --dry-run', 'Preview migration without writing data', false)
22
+ .option('-o, --objects <objects>', 'Objects to migrate (comma-separated)', 'contacts,accounts,opportunities,notes')
23
+ .option('-b, --batch <number>', 'Batch size for API calls', '60')
24
+ .parse();
25
+ const options = program.opts();
26
+ async function main() {
27
+ try {
28
+ console.log('๐Ÿ”„ EspoCRM to Twenty CRM Migration Tool');
29
+ console.log(`๐Ÿ”— EspoCRM URL: ${options.url}`);
30
+ console.log(`๐Ÿ”‘ EspoCRM Auth: ${options.apiKey ? 'API Key' : options.username ? 'Username/Password' : 'โŒ Missing'}`);
31
+ console.log(`๐ŸŽฏ Twenty CRM: ${options.twentyUrl}`);
32
+ console.log(`๐Ÿ”‘ Twenty API: ${options.twentyKey ? 'โœ… Configured' : 'โŒ Missing'}`);
33
+ console.log(`๐Ÿงช Dry Run: ${options.dryRun ? 'YES' : 'NO'}`);
34
+ console.log(`๐Ÿ“ฆ Objects: ${options.objects}`);
35
+ // Validate authentication
36
+ if (!options.apiKey && (!options.username || !options.password)) {
37
+ console.error('โŒ Please provide either API key (--api-key) or username and password (--username, --password)');
38
+ process.exit(1);
39
+ }
40
+ // Parse objects
41
+ const objects = options.objects.split(',').map(obj => obj.trim().toLowerCase());
42
+ // Validate objects
43
+ const validObjects = ['contacts', 'accounts', 'opportunities', 'notes'];
44
+ const invalidObjects = objects.filter(obj => !validObjects.includes(obj));
45
+ if (invalidObjects.length > 0) {
46
+ console.error(`โŒ Invalid objects: ${invalidObjects.join(', ')}`);
47
+ console.error(`Valid objects: ${validObjects.join(', ')}`);
48
+ process.exit(1);
49
+ }
50
+ console.log('\n๐Ÿ“Š Starting migration...');
51
+ const progressBar = (0, reporter_1.showProgress)(0);
52
+ // Extract data from EspoCRM
53
+ console.log('\n๐Ÿ“ฅ Extracting data from EspoCRM...');
54
+ const espocrmData = await (0, extract_1.extractFromEspoCRM)(options.url, options.apiKey, options.username, options.password, objects, progressBar);
55
+ console.log(`โœ… Extracted ${Object.keys(espocrmData).length} object types from EspoCRM`);
56
+ // Show summary for dry run
57
+ if (options.dryRun) {
58
+ console.log('\n๐Ÿ‘€ DRY RUN - Migration Summary:');
59
+ Object.entries(espocrmData).forEach(([objectType, data]) => {
60
+ console.log(`๐Ÿ“Š ${objectType}: ${data.length} records`);
61
+ });
62
+ console.log('\n๐Ÿ“‹ Total records to migrate:');
63
+ const totalRecords = Object.values(espocrmData).reduce((sum, data) => sum + data.length, 0);
64
+ console.log(`๐Ÿ“ˆ Total: ${totalRecords} records`);
65
+ progressBar.stop();
66
+ console.log('\nโœ… Dry run completed. Use --dry-run=false to execute migration.');
67
+ return;
68
+ }
69
+ // Transform data
70
+ console.log('\n๐Ÿ”„ Transforming data for Twenty CRM...');
71
+ const transformedData = await (0, transform_1.transformData)(espocrmData);
72
+ console.log(`โœ… Transformed ${Object.keys(transformedData).length} object types`);
73
+ // Load data to Twenty CRM
74
+ console.log('\n๐Ÿ“ค Loading data to Twenty CRM...');
75
+ const batchSize = parseInt(options.batch?.toString() || '60');
76
+ const result = await (0, load_1.loadToTwenty)(transformedData, options.twentyUrl, options.twentyKey, batchSize, progressBar);
77
+ progressBar.stop();
78
+ // Generate report
79
+ await (0, reporter_1.generateMigrationReport)(result, options.objects);
80
+ console.log('\nโœ… Migration completed!');
81
+ console.log(`๐Ÿ“Š Success: ${result.success}`);
82
+ console.log(`โŒ Errors: ${result.errors}`);
83
+ if (result.errors > 0) {
84
+ console.log(`๐Ÿ“„ Error log: migration-errors-${Date.now()}.log`);
85
+ console.log('\n๐Ÿ” Error details:');
86
+ result.errorLog.forEach(error => {
87
+ console.log(` โŒ ${error}`);
88
+ });
89
+ }
90
+ }
91
+ catch (error) {
92
+ console.error('โŒ Migration failed:', error.message);
93
+ process.exit(1);
94
+ }
95
+ }
96
+ main();
97
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,uCAA+C;AAC/C,2CAA4C;AAC5C,iCAAsC;AACtC,yCAAmE;AAgBnE,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,wBAAwB,CAAC;KAC9B,WAAW,CAAC,8CAA8C,CAAC;KAC3D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,cAAc,CAAC,iBAAiB,EAAE,aAAa,CAAC;KAChD,MAAM,CAAC,qBAAqB,EAAE,oDAAoD,CAAC;KACnF,MAAM,CAAC,2BAA2B,EAAE,2CAA2C,CAAC;KAChF,MAAM,CAAC,2BAA2B,EAAE,2CAA2C,CAAC;KAChF,cAAc,CAAC,wBAAwB,EAAE,gBAAgB,CAAC;KAC1D,cAAc,CAAC,wBAAwB,EAAE,oBAAoB,CAAC;KAC9D,MAAM,CAAC,eAAe,EAAE,wCAAwC,EAAE,KAAK,CAAC;KACxE,MAAM,CAAC,yBAAyB,EAAE,sCAAsC,EAAE,uCAAuC,CAAC;KAClH,MAAM,CAAC,sBAAsB,EAAE,0BAA0B,EAAE,IAAI,CAAC;KAChE,KAAK,EAAE,CAAC;AAEX,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAa,CAAC;AAE1C,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,oBAAoB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACrH,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAE9C,0BAA0B;QAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChE,OAAO,CAAC,KAAK,CAAC,+FAA+F,CAAC,CAAC;YAC/G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,gBAAgB;QAChB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAEhF,mBAAmB;QACnB,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAE1E,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,sBAAsB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAA,uBAAY,EAAC,CAAC,CAAC,CAAC;QAEpC,4BAA4B;QAC5B,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,MAAM,IAAA,4BAAkB,EAC1C,OAAO,CAAC,GAAG,EACX,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,QAAQ,EAChB,OAAO,CAAC,QAAQ,EAChB,OAAO,EACP,WAAW,CACZ,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,4BAA4B,CAAC,CAAC;QAExF,2BAA2B;QAC3B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;YACjD,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE;gBACzD,OAAO,CAAC,GAAG,CAAC,MAAM,UAAU,KAAK,IAAI,CAAC,MAAM,UAAU,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAC9C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC5F,OAAO,CAAC,GAAG,CAAC,aAAa,YAAY,UAAU,CAAC,CAAC;YAEjD,WAAW,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;YAChF,OAAO;QACT,CAAC;QAED,iBAAiB;QACjB,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,MAAM,eAAe,GAAG,MAAM,IAAA,yBAAa,EAAC,WAAW,CAAC,CAAC;QAEzD,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,eAAe,CAAC,CAAC;QAEjF,0BAA0B;QAC1B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAY,EAAC,eAAe,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QAEjH,WAAW,CAAC,IAAI,EAAE,CAAC;QAEnB,kBAAkB;QAClB,MAAM,IAAA,kCAAuB,EAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAEvD,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAE1C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAChE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBAC9B,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACL,CAAC;IAEH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { SingleBar } from 'cli-progress';
2
+ export interface EspoCRMContact {
3
+ id: string;
4
+ firstName?: string;
5
+ lastName?: string;
6
+ email?: string;
7
+ phone?: string;
8
+ accountId?: string;
9
+ title?: string;
10
+ createdAt?: string;
11
+ modifiedAt?: string;
12
+ }
13
+ export interface EspoCRMAccount {
14
+ id: string;
15
+ name?: string;
16
+ website?: string;
17
+ industry?: string;
18
+ phone?: string;
19
+ description?: string;
20
+ createdAt?: string;
21
+ modifiedAt?: string;
22
+ }
23
+ export interface EspoCRMOpportunity {
24
+ id: string;
25
+ name?: string;
26
+ amount?: number;
27
+ currency?: string;
28
+ stage?: string;
29
+ accountId?: string;
30
+ contactId?: string;
31
+ closeDate?: string;
32
+ createdAt?: string;
33
+ modifiedAt?: string;
34
+ }
35
+ export interface EspoCRMNote {
36
+ id: string;
37
+ note?: string;
38
+ parentId?: string;
39
+ parentType?: string;
40
+ createdAt?: string;
41
+ modifiedAt?: string;
42
+ }
43
+ export interface EspoCRMData {
44
+ contacts: EspoCRMContact[];
45
+ accounts: EspoCRMAccount[];
46
+ opportunities: EspoCRMOpportunity[];
47
+ notes: EspoCRMNote[];
48
+ }
49
+ export declare function extractFromEspoCRM(url: string, apiKey: string | undefined, username: string | undefined, password: string | undefined, objects: string[], progressBar: SingleBar): Promise<Partial<EspoCRMData>>;
50
+ //# sourceMappingURL=extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAID,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,EAAE,MAAM,EAAE,EACjB,WAAW,EAAE,SAAS,GACrB,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CA0C/B"}
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractFromEspoCRM = extractFromEspoCRM;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const RATE_LIMIT_DELAY = 600; // 600ms between requests (100 req/min)
9
+ async function extractFromEspoCRM(url, apiKey, username, password, objects, progressBar) {
10
+ const client = await createEspoCRMClient(url, apiKey, username, password);
11
+ const data = {};
12
+ console.log('๐Ÿ”— Testing EspoCRM API connection...');
13
+ try {
14
+ // Test connection
15
+ await testEspoCRMConnection(client);
16
+ console.log('โœ… EspoCRM API connection successful');
17
+ }
18
+ catch (error) {
19
+ console.error('โŒ EspoCRM API connection failed:', error.message);
20
+ throw new Error('Failed to connect to EspoCRM API. Check credentials and permissions.');
21
+ }
22
+ for (const objectType of objects) {
23
+ console.log(`\n๐Ÿ“ฅ Extracting ${objectType}...`);
24
+ try {
25
+ switch (objectType) {
26
+ case 'contacts':
27
+ data.contacts = await extractContacts(client, progressBar);
28
+ break;
29
+ case 'accounts':
30
+ data.accounts = await extractAccounts(client, progressBar);
31
+ break;
32
+ case 'opportunities':
33
+ data.opportunities = await extractOpportunities(client, progressBar);
34
+ break;
35
+ case 'notes':
36
+ data.notes = await extractNotes(client, progressBar);
37
+ break;
38
+ default:
39
+ console.warn(`โš ๏ธ Unknown object type: ${objectType}`);
40
+ }
41
+ }
42
+ catch (error) {
43
+ console.error(`โŒ Failed to extract ${objectType}:`, error.message);
44
+ data[objectType] = [];
45
+ }
46
+ }
47
+ return data;
48
+ }
49
+ async function createEspoCRMClient(url, apiKey, username, password) {
50
+ const client = axios_1.default.create({
51
+ baseURL: `${url}/api/v1`,
52
+ timeout: 30000
53
+ });
54
+ // Set up authentication
55
+ if (apiKey) {
56
+ // API Key authentication
57
+ client.defaults.headers.common['Api-Key'] = apiKey;
58
+ }
59
+ else if (username && password) {
60
+ // Basic authentication
61
+ const authString = Buffer.from(`${username}:${password}`).toString('base64');
62
+ client.defaults.headers.common['Authorization'] = `Basic ${authString}`;
63
+ }
64
+ else {
65
+ throw new Error('Either API key or username/password must be provided');
66
+ }
67
+ return client;
68
+ }
69
+ async function testEspoCRMConnection(client) {
70
+ try {
71
+ await client.get('/App/user');
72
+ }
73
+ catch (error) {
74
+ throw new Error(`EspoCRM API test failed: ${error.message}`);
75
+ }
76
+ }
77
+ async function extractContacts(client, progressBar) {
78
+ const contacts = [];
79
+ let offset = 0;
80
+ const maxSize = 200;
81
+ while (true) {
82
+ try {
83
+ const response = await client.get('/Contact', {
84
+ params: {
85
+ offset,
86
+ maxSize,
87
+ select: 'id,firstName,lastName,email,phone,accountId,title,createdAt,modifiedAt'
88
+ }
89
+ });
90
+ if (response.data && response.data.list && response.data.list.length > 0) {
91
+ contacts.push(...response.data.list);
92
+ progressBar.update(contacts.length, { contacts: contacts.length });
93
+ // Check if there are more records
94
+ if (response.data.list.length < maxSize) {
95
+ break;
96
+ }
97
+ offset += maxSize;
98
+ }
99
+ else {
100
+ break;
101
+ }
102
+ // Rate limiting
103
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
104
+ }
105
+ catch (error) {
106
+ console.error(`โŒ Error fetching contacts:`, error.message);
107
+ break;
108
+ }
109
+ }
110
+ console.log(`โœ… Extracted ${contacts.length} contacts`);
111
+ return contacts;
112
+ }
113
+ async function extractAccounts(client, progressBar) {
114
+ const accounts = [];
115
+ let offset = 0;
116
+ const maxSize = 200;
117
+ while (true) {
118
+ try {
119
+ const response = await client.get('/Account', {
120
+ params: {
121
+ offset,
122
+ maxSize,
123
+ select: 'id,name,website,industry,phone,description,createdAt,modifiedAt'
124
+ }
125
+ });
126
+ if (response.data && response.data.list && response.data.list.length > 0) {
127
+ accounts.push(...response.data.list);
128
+ progressBar.update(accounts.length, { accounts: accounts.length });
129
+ // Check if there are more records
130
+ if (response.data.list.length < maxSize) {
131
+ break;
132
+ }
133
+ offset += maxSize;
134
+ }
135
+ else {
136
+ break;
137
+ }
138
+ // Rate limiting
139
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
140
+ }
141
+ catch (error) {
142
+ console.error(`โŒ Error fetching accounts:`, error.message);
143
+ break;
144
+ }
145
+ }
146
+ console.log(`โœ… Extracted ${accounts.length} accounts`);
147
+ return accounts;
148
+ }
149
+ async function extractOpportunities(client, progressBar) {
150
+ const opportunities = [];
151
+ let offset = 0;
152
+ const maxSize = 200;
153
+ while (true) {
154
+ try {
155
+ const response = await client.get('/Opportunity', {
156
+ params: {
157
+ offset,
158
+ maxSize,
159
+ select: 'id,name,amount,currency,stage,accountId,contactId,closeDate,createdAt,modifiedAt'
160
+ }
161
+ });
162
+ if (response.data && response.data.list && response.data.list.length > 0) {
163
+ opportunities.push(...response.data.list);
164
+ progressBar.update(opportunities.length, { opportunities: opportunities.length });
165
+ // Check if there are more records
166
+ if (response.data.list.length < maxSize) {
167
+ break;
168
+ }
169
+ offset += maxSize;
170
+ }
171
+ else {
172
+ break;
173
+ }
174
+ // Rate limiting
175
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
176
+ }
177
+ catch (error) {
178
+ console.error(`โŒ Error fetching opportunities:`, error.message);
179
+ break;
180
+ }
181
+ }
182
+ console.log(`โœ… Extracted ${opportunities.length} opportunities`);
183
+ return opportunities;
184
+ }
185
+ async function extractNotes(client, progressBar) {
186
+ const notes = [];
187
+ let offset = 0;
188
+ const maxSize = 200;
189
+ while (true) {
190
+ try {
191
+ const response = await client.get('/Note', {
192
+ params: {
193
+ offset,
194
+ maxSize,
195
+ select: 'id,note,parentId,parentType,createdAt,modifiedAt'
196
+ }
197
+ });
198
+ if (response.data && response.data.list && response.data.list.length > 0) {
199
+ notes.push(...response.data.list);
200
+ progressBar.update(notes.length, { notes: notes.length });
201
+ // Check if there are more records
202
+ if (response.data.list.length < maxSize) {
203
+ break;
204
+ }
205
+ offset += maxSize;
206
+ }
207
+ else {
208
+ break;
209
+ }
210
+ // Rate limiting
211
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
212
+ }
213
+ catch (error) {
214
+ console.error(`โŒ Error fetching notes:`, error.message);
215
+ break;
216
+ }
217
+ }
218
+ console.log(`โœ… Extracted ${notes.length} notes`);
219
+ return notes;
220
+ }
221
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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"}
package/dist/load.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { TransformedData } from './transform';
2
+ import { SingleBar } from 'cli-progress';
3
+ export interface LoadResult {
4
+ success: number;
5
+ errors: number;
6
+ errorLog: string[];
7
+ objectResults: {
8
+ people: {
9
+ success: number;
10
+ errors: number;
11
+ };
12
+ companies: {
13
+ success: number;
14
+ errors: number;
15
+ };
16
+ opportunities: {
17
+ success: number;
18
+ errors: number;
19
+ };
20
+ notes: {
21
+ success: number;
22
+ errors: number;
23
+ };
24
+ };
25
+ }
26
+ export interface BatchResult {
27
+ success: boolean;
28
+ count: number;
29
+ error?: string;
30
+ }
31
+ export declare class TwentyAPIClient {
32
+ private client;
33
+ private baseUrl;
34
+ private apiKey;
35
+ private existingEmails;
36
+ private existingCompanies;
37
+ constructor(baseUrl: string, apiKey: string);
38
+ testConnection(): Promise<boolean>;
39
+ loadExistingData(): Promise<void>;
40
+ createRecords(objectType: string, records: any[]): Promise<BatchResult>;
41
+ private filterDuplicates;
42
+ private transformRecordForAPI;
43
+ }
44
+ export declare function loadToTwenty(data: TransformedData, twentyUrl: string, twentyKey: string, batchSize: number, progressBar: SingleBar): Promise<LoadResult>;
45
+ export declare function saveMigrationReport(result: LoadResult, filename: string): void;
46
+ //# sourceMappingURL=load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAA8D,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE;QACb,MAAM,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5C,SAAS,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,aAAa,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QACnD,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC5C,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,iBAAiB,CAA0B;gBAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAcrC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAUlC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BjC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;YA2B/D,gBAAgB;IAa9B,OAAO,CAAC,qBAAqB;CAkD9B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,SAAS,GACrB,OAAO,CAAC,UAAU,CAAC,CAgFrB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAe9E"}