twenty-migrate-copper 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,13 @@
1
+ # Copper API Configuration
2
+ COPPER_API_KEY=your_copper_api_key_here
3
+ COPPER_API_URL=https://api.copper.com/v1
4
+
5
+ # Twenty CRM Configuration
6
+ TWENTY_URL=http://localhost:3000
7
+ TWENTY_API_KEY=your_twenty_api_key_here
8
+
9
+ # Migration Settings
10
+ BATCH_SIZE=60
11
+ RATE_LIMIT_DELAY=600
12
+ DRY_RUN=false
13
+ OBJECTS=people,companies,opportunities,activities
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,88 @@
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-copper')
12
+ .description('CLI migration tool for Copper to Twenty CRM')
13
+ .version('1.0.0');
14
+ program
15
+ .requiredOption('-k, --api-key <key>', 'Copper API key')
16
+ .requiredOption('-u, --twenty-url <url>', 'Twenty CRM URL')
17
+ .requiredOption('-t, --twenty-key <key>', 'Twenty CRM API key')
18
+ .option('-d, --dry-run', 'Preview migration without writing data', false)
19
+ .option('-o, --objects <objects>', 'Objects to migrate (comma-separated)', 'people,companies,opportunities,activities')
20
+ .option('-b, --batch <number>', 'Batch size for API calls', '60')
21
+ .parse();
22
+ const options = program.opts();
23
+ async function main() {
24
+ try {
25
+ console.log('๐Ÿ”„ Copper to Twenty CRM Migration Tool');
26
+ console.log(`๐Ÿ”— Copper API Key: ${options.apiKey ? 'โœ… Configured' : 'โŒ Missing'}`);
27
+ console.log(`๐ŸŽฏ Twenty CRM: ${options.twentyUrl}`);
28
+ console.log(`๐Ÿ”‘ Twenty API: ${options.twentyKey ? 'โœ… Configured' : 'โŒ Missing'}`);
29
+ console.log(`๐Ÿงช Dry Run: ${options.dryRun ? 'YES' : 'NO'}`);
30
+ console.log(`๐Ÿ“ฆ Objects: ${options.objects}`);
31
+ // Parse objects
32
+ const objects = options.objects.split(',').map(obj => obj.trim().toLowerCase());
33
+ // Validate objects
34
+ const validObjects = ['people', 'companies', 'opportunities', 'activities'];
35
+ const invalidObjects = objects.filter(obj => !validObjects.includes(obj));
36
+ if (invalidObjects.length > 0) {
37
+ console.error(`โŒ Invalid objects: ${invalidObjects.join(', ')}`);
38
+ console.error(`Valid objects: ${validObjects.join(', ')}`);
39
+ process.exit(1);
40
+ }
41
+ console.log('\n๐Ÿ“Š Starting migration...');
42
+ const progressBar = (0, reporter_1.showProgress)(0);
43
+ // Extract data from Copper
44
+ console.log('\n๐Ÿ“ฅ Extracting data from Copper...');
45
+ const copperData = await (0, extract_1.extractFromCopper)(options.apiKey, objects, progressBar);
46
+ console.log(`โœ… Extracted ${Object.keys(copperData).length} object types from Copper`);
47
+ // Show summary for dry run
48
+ if (options.dryRun) {
49
+ console.log('\n๐Ÿ‘€ DRY RUN - Migration Summary:');
50
+ Object.entries(copperData).forEach(([objectType, data]) => {
51
+ console.log(`๐Ÿ“Š ${objectType}: ${data.length} records`);
52
+ });
53
+ console.log('\n๐Ÿ“‹ Total records to migrate:');
54
+ const totalRecords = Object.values(copperData).reduce((sum, data) => sum + data.length, 0);
55
+ console.log(`๐Ÿ“ˆ Total: ${totalRecords} records`);
56
+ progressBar.stop();
57
+ console.log('\nโœ… Dry run completed. Use --dry-run=false to execute migration.');
58
+ return;
59
+ }
60
+ // Transform data
61
+ console.log('\n๐Ÿ”„ Transforming data for Twenty CRM...');
62
+ const transformedData = await (0, transform_1.transformData)(copperData);
63
+ console.log(`โœ… Transformed ${Object.keys(transformedData).length} object types`);
64
+ // Load data to Twenty CRM
65
+ console.log('\n๐Ÿ“ค Loading data to Twenty CRM...');
66
+ const batchSize = parseInt(options.batch?.toString() || '60');
67
+ const result = await (0, load_1.loadToTwenty)(transformedData, options.twentyUrl, options.twentyKey, batchSize, progressBar);
68
+ progressBar.stop();
69
+ // Generate report
70
+ await (0, reporter_1.generateMigrationReport)(result, options.objects);
71
+ console.log('\nโœ… Migration completed!');
72
+ console.log(`๐Ÿ“Š Success: ${result.success}`);
73
+ console.log(`โŒ Errors: ${result.errors}`);
74
+ if (result.errors > 0) {
75
+ console.log(`๐Ÿ“„ Error log: migration-errors-${Date.now()}.log`);
76
+ console.log('\n๐Ÿ” Error details:');
77
+ result.errorLog.forEach(error => {
78
+ console.log(` โŒ ${error}`);
79
+ });
80
+ }
81
+ }
82
+ catch (error) {
83
+ console.error('โŒ Migration failed:', error.message);
84
+ process.exit(1);
85
+ }
86
+ }
87
+ main();
88
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { SingleBar } from 'cli-progress';
2
+ export interface CopperPerson {
3
+ id: number;
4
+ name?: string;
5
+ first_name?: string;
6
+ last_name?: string;
7
+ email?: string;
8
+ phone?: string;
9
+ company_id?: number;
10
+ title?: string;
11
+ date_created?: string;
12
+ date_modified?: string;
13
+ }
14
+ export interface CopperCompany {
15
+ id: number;
16
+ name?: string;
17
+ website?: string;
18
+ industry?: string;
19
+ phone?: string;
20
+ description?: string;
21
+ date_created?: string;
22
+ date_modified?: string;
23
+ }
24
+ export interface CopperOpportunity {
25
+ id: number;
26
+ name?: string;
27
+ monetary_value?: number;
28
+ currency?: string;
29
+ status?: string;
30
+ pipeline_id?: number;
31
+ pipeline_stage_id?: number;
32
+ company_id?: number;
33
+ primary_contact_id?: number;
34
+ close_date?: string;
35
+ date_created?: string;
36
+ date_modified?: string;
37
+ }
38
+ export interface CopperActivity {
39
+ id: number;
40
+ activity_type?: string;
41
+ details?: string;
42
+ user_id?: number;
43
+ person_id?: number;
44
+ company_id?: number;
45
+ opportunity_id?: number;
46
+ due_date?: string;
47
+ date_created?: string;
48
+ date_modified?: string;
49
+ }
50
+ export interface CopperData {
51
+ people: CopperPerson[];
52
+ companies: CopperCompany[];
53
+ opportunities: CopperOpportunity[];
54
+ activities: CopperActivity[];
55
+ }
56
+ export declare function extractFromCopper(apiKey: string, objects: string[], progressBar: SingleBar): Promise<Partial<CopperData>>;
57
+ //# 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,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,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,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B;AAID,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,WAAW,EAAE,SAAS,GACrB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CA0C9B"}
@@ -0,0 +1,209 @@
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.extractFromCopper = extractFromCopper;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const RATE_LIMIT_DELAY = 600; // 600ms between requests (100 req/min)
9
+ async function extractFromCopper(apiKey, objects, progressBar) {
10
+ const client = createCopperClient(apiKey);
11
+ const data = {};
12
+ console.log('๐Ÿ”— Testing Copper API connection...');
13
+ try {
14
+ // Test connection
15
+ await testCopperConnection(client);
16
+ console.log('โœ… Copper API connection successful');
17
+ }
18
+ catch (error) {
19
+ console.error('โŒ Copper API connection failed:', error.message);
20
+ throw new Error('Failed to connect to Copper API. Check API key and permissions.');
21
+ }
22
+ for (const objectType of objects) {
23
+ console.log(`\n๐Ÿ“ฅ Extracting ${objectType}...`);
24
+ try {
25
+ switch (objectType) {
26
+ case 'people':
27
+ data.people = await extractPeople(client, progressBar);
28
+ break;
29
+ case 'companies':
30
+ data.companies = await extractCompanies(client, progressBar);
31
+ break;
32
+ case 'opportunities':
33
+ data.opportunities = await extractOpportunities(client, progressBar);
34
+ break;
35
+ case 'activities':
36
+ data.activities = await extractActivities(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
+ function createCopperClient(apiKey) {
50
+ return axios_1.default.create({
51
+ baseURL: 'https://api.copper.com/v1',
52
+ headers: {
53
+ 'X-PW-Application': 'developer_api_key',
54
+ 'X-PW-UserEmail': 'api@example.com',
55
+ 'X-PW-AccessToken': apiKey,
56
+ 'Content-Type': 'application/json'
57
+ },
58
+ timeout: 30000
59
+ });
60
+ }
61
+ async function testCopperConnection(client) {
62
+ try {
63
+ await client.get('/users');
64
+ }
65
+ catch (error) {
66
+ throw new Error(`Copper API test failed: ${error.message}`);
67
+ }
68
+ }
69
+ async function extractPeople(client, progressBar) {
70
+ const people = [];
71
+ let page = 1;
72
+ const pageSize = 200;
73
+ while (true) {
74
+ try {
75
+ const response = await client.get('/people', {
76
+ params: {
77
+ page_number: page,
78
+ page_size: pageSize
79
+ }
80
+ });
81
+ if (response.data && response.data.length > 0) {
82
+ people.push(...response.data);
83
+ progressBar.update(people.length, { people: people.length });
84
+ // Check if there are more records
85
+ if (response.data.length < pageSize) {
86
+ break;
87
+ }
88
+ page++;
89
+ }
90
+ else {
91
+ break;
92
+ }
93
+ // Rate limiting
94
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
95
+ }
96
+ catch (error) {
97
+ console.error(`โŒ Error fetching people page:`, error.message);
98
+ break;
99
+ }
100
+ }
101
+ console.log(`โœ… Extracted ${people.length} people`);
102
+ return people;
103
+ }
104
+ async function extractCompanies(client, progressBar) {
105
+ const companies = [];
106
+ let page = 1;
107
+ const pageSize = 200;
108
+ while (true) {
109
+ try {
110
+ const response = await client.get('/companies', {
111
+ params: {
112
+ page_number: page,
113
+ page_size: pageSize
114
+ }
115
+ });
116
+ if (response.data && response.data.length > 0) {
117
+ companies.push(...response.data);
118
+ progressBar.update(companies.length, { companies: companies.length });
119
+ // Check if there are more records
120
+ if (response.data.length < pageSize) {
121
+ break;
122
+ }
123
+ page++;
124
+ }
125
+ else {
126
+ break;
127
+ }
128
+ // Rate limiting
129
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
130
+ }
131
+ catch (error) {
132
+ console.error(`โŒ Error fetching companies page:`, error.message);
133
+ break;
134
+ }
135
+ }
136
+ console.log(`โœ… Extracted ${companies.length} companies`);
137
+ return companies;
138
+ }
139
+ async function extractOpportunities(client, progressBar) {
140
+ const opportunities = [];
141
+ let page = 1;
142
+ const pageSize = 200;
143
+ while (true) {
144
+ try {
145
+ const response = await client.get('/opportunities', {
146
+ params: {
147
+ page_number: page,
148
+ page_size: pageSize
149
+ }
150
+ });
151
+ if (response.data && response.data.length > 0) {
152
+ opportunities.push(...response.data);
153
+ progressBar.update(opportunities.length, { opportunities: opportunities.length });
154
+ // Check if there are more records
155
+ if (response.data.length < pageSize) {
156
+ break;
157
+ }
158
+ page++;
159
+ }
160
+ else {
161
+ break;
162
+ }
163
+ // Rate limiting
164
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
165
+ }
166
+ catch (error) {
167
+ console.error(`โŒ Error fetching opportunities page:`, error.message);
168
+ break;
169
+ }
170
+ }
171
+ console.log(`โœ… Extracted ${opportunities.length} opportunities`);
172
+ return opportunities;
173
+ }
174
+ async function extractActivities(client, progressBar) {
175
+ const activities = [];
176
+ let page = 1;
177
+ const pageSize = 200;
178
+ while (true) {
179
+ try {
180
+ const response = await client.get('/activities', {
181
+ params: {
182
+ page_number: page,
183
+ page_size: pageSize
184
+ }
185
+ });
186
+ if (response.data && response.data.length > 0) {
187
+ activities.push(...response.data);
188
+ progressBar.update(activities.length, { activities: activities.length });
189
+ // Check if there are more records
190
+ if (response.data.length < pageSize) {
191
+ break;
192
+ }
193
+ page++;
194
+ }
195
+ else {
196
+ break;
197
+ }
198
+ // Rate limiting
199
+ await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY));
200
+ }
201
+ catch (error) {
202
+ console.error(`โŒ Error fetching activities page:`, error.message);
203
+ break;
204
+ }
205
+ }
206
+ console.log(`โœ… Extracted ${activities.length} activities`);
207
+ return activities;
208
+ }
209
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":";;;;;AAgEA,8CA8CC;AA9GD,kDAA6C;AA8D7C,MAAM,gBAAgB,GAAG,GAAG,CAAC,CAAC,uCAAuC;AAE9D,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,OAAiB,EACjB,WAAsB;IAEtB,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAwB,EAAE,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAEnD,IAAI,CAAC;QACH,kBAAkB;QAClB,MAAM,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IAED,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,mBAAmB,UAAU,KAAK,CAAC,CAAC;QAEhD,IAAI,CAAC;YACH,QAAQ,UAAU,EAAE,CAAC;gBACnB,KAAK,QAAQ;oBACX,IAAI,CAAC,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;oBACvD,MAAM;gBACR,KAAK,WAAW;oBACd,IAAI,CAAC,SAAS,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;oBAC7D,MAAM;gBACR,KAAK,eAAe;oBAClB,IAAI,CAAC,aAAa,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;oBACrE,MAAM;gBACR,KAAK,YAAY;oBACf,IAAI,CAAC,UAAU,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;oBAC/D,MAAM;gBACR;oBACE,OAAO,CAAC,IAAI,CAAC,2BAA2B,UAAU,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,uBAAuB,UAAU,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACnE,IAAI,CAAC,UAA8B,CAAC,GAAG,EAAE,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,OAAO,eAAK,CAAC,MAAM,CAAC;QAClB,OAAO,EAAE,2BAA2B;QACpC,OAAO,EAAE;YACP,kBAAkB,EAAE,mBAAmB;YACvC,gBAAgB,EAAE,iBAAiB;YACnC,kBAAkB,EAAE,MAAM;YAC1B,cAAc,EAAE,kBAAkB;SACnC;QACD,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,MAAqB;IACvD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,MAAqB,EAAE,WAAsB;IACxE,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,QAAQ,GAAG,GAAG,CAAC;IAErB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE;gBAC3C,MAAM,EAAE;oBACN,WAAW,EAAE,IAAI;oBACjB,SAAS,EAAE,QAAQ;iBACpB;aACF,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9C,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC9B,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;gBAE7D,kCAAkC;gBAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;oBACpC,MAAM;gBACR,CAAC;gBAED,IAAI,EAAE,CAAC;YACT,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;YAED,gBAAgB;YAChB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEtE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC9D,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,MAAqB,EAAE,WAAsB;IAC3E,MAAM,SAAS,GAAoB,EAAE,CAAC;IACtC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,QAAQ,GAAG,GAAG,CAAC;IAErB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE;gBAC9C,MAAM,EAAE;oBACN,WAAW,EAAE,IAAI;oBACjB,SAAS,EAAE,QAAQ;iBACpB;aACF,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9C,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACjC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;gBAEtE,kCAAkC;gBAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;oBACpC,MAAM;gBACR,CAAC;gBAED,IAAI,EAAE,CAAC;YACT,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;YAED,gBAAgB;YAChB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEtE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACjE,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,MAAM,YAAY,CAAC,CAAC;IACzD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,MAAqB,EAAE,WAAsB;IAC/E,MAAM,aAAa,GAAwB,EAAE,CAAC;IAC9C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,QAAQ,GAAG,GAAG,CAAC;IAErB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE;gBAClD,MAAM,EAAE;oBACN,WAAW,EAAE,IAAI;oBACjB,SAAS,EAAE,QAAQ;iBACpB;aACF,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9C,aAAa,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACrC,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;gBAElF,kCAAkC;gBAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;oBACpC,MAAM;gBACR,CAAC;gBAED,IAAI,EAAE,CAAC;YACT,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;YAED,gBAAgB;YAChB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEtE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAe,aAAa,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACjE,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,MAAqB,EAAE,WAAsB;IAC5E,MAAM,UAAU,GAAqB,EAAE,CAAC;IACxC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,QAAQ,GAAG,GAAG,CAAC;IAErB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE;gBAC/C,MAAM,EAAE;oBACN,WAAW,EAAE,IAAI;oBACjB,SAAS,EAAE,QAAQ;iBACpB;aACF,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9C,UAAU,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAClC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;gBAEzE,kCAAkC;gBAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;oBACpC,MAAM;gBACR,CAAC;gBAED,IAAI,EAAE,CAAC;YACT,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;YAED,gBAAgB;YAChB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEtE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAClE,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAe,UAAU,CAAC,MAAM,aAAa,CAAC,CAAC;IAC3D,OAAO,UAAU,CAAC;AACpB,CAAC"}
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
+ activities: {
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,EAAkE,MAAM,aAAa,CAAC;AAC9G,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,UAAU,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KACjD,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;CAoD9B;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"}