nango 0.36.37 → 0.36.38
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/dist/action.ejs +39 -0
- package/dist/github.sync.ejs +58 -0
- package/dist/integration.ejs +5 -0
- package/dist/integration.github.ejs +61 -0
- package/dist/integration.service.d.ts +6 -0
- package/dist/integration.service.js +37 -0
- package/dist/integration.service.js.map +1 -0
- package/dist/local-integration.service.d.ts +6 -0
- package/dist/local-integration.service.js +60 -0
- package/dist/local-integration.service.js.map +1 -0
- package/dist/migration.ejs +35 -0
- package/dist/services/compile copy.service.d.ts +5 -0
- package/dist/services/compile copy.service.js +68 -0
- package/dist/services/compile copy.service.js.map +1 -0
- package/dist/services/yaml.service.d.ts +7 -0
- package/dist/services/yaml.service.js +32 -0
- package/dist/services/yaml.service.js.map +1 -0
- package/dist/sync.d.ts +17 -0
- package/dist/sync.ejs +10 -0
- package/dist/sync.js +346 -0
- package/dist/sync.js.map +1 -0
- package/dist/templates/migration.ejs +35 -0
- package/docker/docker-compose.yaml +2 -2
- package/package.json +2 -2
package/dist/action.ejs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const isArrayInterfaceNames = Array.isArray(interfaceNames);
|
|
3
|
+
const isArrayMappings = Array.isArray(mappings);
|
|
4
|
+
const isArrayInputs = Array.isArray(inputs);
|
|
5
|
+
|
|
6
|
+
const formattedInterfaceNames = isArrayInterfaceNames ? interfaceNames.join(', ') : interfaceNames;
|
|
7
|
+
const javascriptPrimitives = ['string', 'number', 'boolean', 'bigint', 'symbol', 'undefined', 'object', 'null'];
|
|
8
|
+
const filteredInputs = isArrayInputs ? inputs.filter(input => !javascriptPrimitives.includes(input)) : inputs;
|
|
9
|
+
|
|
10
|
+
const formattedInputs = isArrayInputs ? filteredInputs.join(', ') : (javascriptPrimitives.includes(inputs) ? '' : inputs);
|
|
11
|
+
|
|
12
|
+
let returnTypes = 'void';
|
|
13
|
+
if (isArrayMappings && mappings.length > 0) {
|
|
14
|
+
if (mappings.length === 1) {
|
|
15
|
+
returnTypes = `${mappings[0].name}[]`;
|
|
16
|
+
} else {
|
|
17
|
+
returnTypes = '{' + mappings.map(mapping => `${mapping.name}: ${mapping.type}[]`).join(', ') + '}';
|
|
18
|
+
}
|
|
19
|
+
} else if (typeof mappings === 'object') {
|
|
20
|
+
returnTypes = `${mappings.name}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let paramInputs = 'object';
|
|
24
|
+
let optionalInput = '?';
|
|
25
|
+
if (inputs) {
|
|
26
|
+
optionalInput = '';
|
|
27
|
+
|
|
28
|
+
if (isArrayInputs) {
|
|
29
|
+
paramInputs = `${inputs}[];`
|
|
30
|
+
} else {
|
|
31
|
+
paramInputs = inputs;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
%>
|
|
35
|
+
import type { NangoAction<%= formattedInterfaceNames ? ', ' + formattedInterfaceNames : '' %><%= formattedInputs ? ', ' + formattedInputs : '' %> } from './<%= interfaceFileName %>';
|
|
36
|
+
|
|
37
|
+
export default async function runAction(nango: NangoAction, input<%= optionalInput %>: <%= paramInputs %>): Promise<<%= returnTypes %>> {
|
|
38
|
+
// Integration code goes here
|
|
39
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { NangoSync, <%= interfaceNames.join(', ') %> } from './<%= interfaceFileName %>';
|
|
2
|
+
|
|
3
|
+
export default async function fetchData(nango: NangoSync): Promise<void> {
|
|
4
|
+
|
|
5
|
+
const repos = await paginate(nango, '/user/repos');
|
|
6
|
+
|
|
7
|
+
for (let repo of repos) {
|
|
8
|
+
let issues = await paginate(nango, `/repos/${repo.owner.login}/${repo.name}/issues`);
|
|
9
|
+
|
|
10
|
+
// Filter out pull requests
|
|
11
|
+
issues = issues.filter(issue => !('pull_request' in issue));
|
|
12
|
+
|
|
13
|
+
const mappedIssues: GithubIssue[] = issues.map(issue => ({
|
|
14
|
+
id: issue.id,
|
|
15
|
+
owner: repo.owner.login,
|
|
16
|
+
repo: repo.name,
|
|
17
|
+
issue_number: issue.number,
|
|
18
|
+
title: issue.title,
|
|
19
|
+
state: issue.state,
|
|
20
|
+
author: issue.user.login,
|
|
21
|
+
author_id: issue.user.id,
|
|
22
|
+
body: issue.body,
|
|
23
|
+
date_created: issue.created_at,
|
|
24
|
+
date_last_modified: issue.updated_at
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
if (mappedIssues.length > 0) {
|
|
28
|
+
await nango.batchSave<GithubIssue>(mappedIssues, 'GithubIssue');
|
|
29
|
+
await nango.log(`Sent ${mappedIssues.length} issues from ${repo.owner.login}/${repo.name}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function paginate(nango: NangoSync, endpoint: string) {
|
|
35
|
+
const MAX_PAGE = 100;
|
|
36
|
+
|
|
37
|
+
let results: any[] = [];
|
|
38
|
+
let page = 1;
|
|
39
|
+
while (true) {
|
|
40
|
+
const resp = await nango.get({
|
|
41
|
+
endpoint: endpoint,
|
|
42
|
+
params: {
|
|
43
|
+
limit: `${MAX_PAGE}`,
|
|
44
|
+
page: `${page}`
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
results = results.concat(resp.data);
|
|
49
|
+
|
|
50
|
+
if (resp.data.length == MAX_PAGE) {
|
|
51
|
+
page += 1;
|
|
52
|
+
} else {
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NangoSync, <%= interfaceNames.join(', ') %> } from './<%= interfaceFileName %>';
|
|
2
|
+
|
|
3
|
+
export default async function fetchData(nango: NangoSync): Promise<{<% for (let i = 0; i < mappings.length; i++) { %><%= mappings[i].name %>: <%= mappings[i].type %>[]<% if (i !== mappings.length - 1) { %>, <% } %><% } %>}> {
|
|
4
|
+
// Integration code goes here, be sure to follow the return signature type
|
|
5
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { NangoSync, <%= interfaceNames.join(', ') %> } from './<%= interfaceFileName %>';
|
|
2
|
+
|
|
3
|
+
export default async function fetchData(nango: NangoSync): Promise<{<% for (let i = 0; i < mappings.length; i++) { %><%= mappings[i].name %>: <%= mappings[i].type %>[]<% if (i !== mappings.length - 1) { %>, <% } %><% } %>}> {
|
|
4
|
+
|
|
5
|
+
const repos = await paginate(nango, '/user/repos');
|
|
6
|
+
|
|
7
|
+
for (let repo of repos) {
|
|
8
|
+
let issues = await paginate(nango, `/repos/${repo.owner.login}/${repo.name}/issues`);
|
|
9
|
+
|
|
10
|
+
// Filter out pull requests
|
|
11
|
+
issues = issues.filter(issue => !('pull_request' in issue));
|
|
12
|
+
|
|
13
|
+
const mappedIssues: GithubIssue[] = issues.map(issue => ({
|
|
14
|
+
id: issue.id,
|
|
15
|
+
owner: repo.owner.login,
|
|
16
|
+
repo: repo.name,
|
|
17
|
+
issue_number: issue.number,
|
|
18
|
+
title: issue.title,
|
|
19
|
+
state: issue.state,
|
|
20
|
+
author: issue.user.login,
|
|
21
|
+
author_id: issue.user.id,
|
|
22
|
+
body: issue.body,
|
|
23
|
+
date_created: issue.created_at,
|
|
24
|
+
date_last_modified: issue.updated_at
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
if (mappedIssues.length > 0) {
|
|
28
|
+
await nango.batchSave<GithubIssue>(mappedIssues, 'GithubIssue');
|
|
29
|
+
await nango.log(`Sent ${mappedIssues.length} issues from ${repo.owner.login}/${repo.name}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Return empty array with the model key to indicate success
|
|
34
|
+
return { GithubIssue: [] };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function paginate(nango: NangoSync, endpoint: string) {
|
|
38
|
+
const MAX_PAGE = 100;
|
|
39
|
+
|
|
40
|
+
let results: any[] = [];
|
|
41
|
+
let page = 1;
|
|
42
|
+
while (true) {
|
|
43
|
+
const resp = await nango.get({
|
|
44
|
+
endpoint: endpoint,
|
|
45
|
+
params: {
|
|
46
|
+
limit: `${MAX_PAGE}`,
|
|
47
|
+
page: `${page}`
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
results = results.concat(resp.data);
|
|
52
|
+
|
|
53
|
+
if (resp.data.length == MAX_PAGE) {
|
|
54
|
+
page += 1;
|
|
55
|
+
} else {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IntegrationServiceInterface, NangoIntegrationData, NangoSync } from '@nangohq/shared';
|
|
2
|
+
declare class IntegrationService implements IntegrationServiceInterface {
|
|
3
|
+
runScript(syncName: string, _activityLogId: number | undefined, nango: NangoSync, _integrationData: NangoIntegrationData, _environmentId: number, _writeToDb: boolean, isAction: boolean, optionalLoadLocation?: string, input?: object): Promise<any>;
|
|
4
|
+
}
|
|
5
|
+
declare const _default: IntegrationService;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { localFileService } from '@nangohq/shared';
|
|
2
|
+
class IntegrationService {
|
|
3
|
+
async runScript(syncName, _activityLogId, nango, _integrationData, _environmentId, _writeToDb, isAction, optionalLoadLocation, input) {
|
|
4
|
+
try {
|
|
5
|
+
const script = localFileService.getIntegrationFile(syncName, optionalLoadLocation);
|
|
6
|
+
if (!script) {
|
|
7
|
+
const content = `Unable to find integration file for ${syncName}`;
|
|
8
|
+
console.error(content);
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
let scriptExports;
|
|
12
|
+
eval(`scriptExports = ${script}`);
|
|
13
|
+
if (scriptExports && typeof scriptExports.default === 'function') {
|
|
14
|
+
const results = isAction ? await scriptExports.default(nango, input) : await scriptExports.default(nango);
|
|
15
|
+
return results;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const content = `There is no default export that is a function for ${syncName}`;
|
|
19
|
+
console.error(content);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
console.error(err);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const errorMessage = JSON.stringify(err, ['message', 'name', 'stack'], 2);
|
|
30
|
+
const content = `The script failed to load for ${syncName} with the following error: ${errorMessage}`;
|
|
31
|
+
console.error(content);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export default new IntegrationService();
|
|
37
|
+
//# sourceMappingURL=integration.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.service.js","sourceRoot":"","sources":["../lib/integration.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEjH,MAAM,kBAAkB;IACpB,KAAK,CAAC,SAAS,CACX,QAAgB,EAChB,cAAkC,EAClC,KAAgB,EAChB,gBAAsC,EACtC,cAAsB,EACtB,UAAmB,EACnB,QAAiB,EACjB,oBAA6B,EAC7B,KAAc;QAEd,IAAI;YACA,MAAM,MAAM,GAAkB,gBAAgB,CAAC,kBAAkB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;YAElG,IAAI,CAAC,MAAM,EAAE;gBACT,MAAM,OAAO,GAAG,uCAAuC,QAAQ,EAAE,CAAC;gBAElE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;aAC1B;YAED,IAAI;gBACA,IAAI,aAAkB,CAAC;gBAEvB,IAAI,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;gBAClC,IAAI,aAAa,IAAI,OAAO,aAAa,CAAC,OAAO,KAAK,UAAU,EAAE;oBAC9D,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBAC1G,OAAO,OAAO,CAAC;iBAClB;qBAAM;oBACH,MAAM,OAAO,GAAG,qDAAqD,QAAQ,EAAE,CAAC;oBAChF,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;oBAEvB,OAAO,IAAI,CAAC;iBACf;aACJ;YAAC,OAAO,GAAQ,EAAE;gBACf,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAEnB,OAAO,IAAI,CAAC;aACf;SACJ;QAAC,OAAO,GAAG,EAAE;YACV,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1E,MAAM,OAAO,GAAG,iCAAiC,QAAQ,8BAA8B,YAAY,EAAE,CAAC;YAEtG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAEvB,OAAO,IAAI,CAAC;SACf;IACL,CAAC;CACJ;AAED,eAAe,IAAI,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IntegrationServiceInterface, NangoIntegrationData, NangoSync } from '@nangohq/shared';
|
|
2
|
+
declare class IntegrationService implements IntegrationServiceInterface {
|
|
3
|
+
runScript(syncName: string, _activityLogId: number | undefined, nango: NangoSync, _integrationData: NangoIntegrationData, _environmentId: number, _writeToDb: boolean, isAction: boolean, optionalLoadLocation?: string, input?: object): Promise<any>;
|
|
4
|
+
}
|
|
5
|
+
declare const _default: IntegrationService;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { NangoError, formatScriptError, localFileService } from '@nangohq/shared';
|
|
2
|
+
import * as vm from 'vm';
|
|
3
|
+
import * as url from 'url';
|
|
4
|
+
import * as crypto from 'crypto';
|
|
5
|
+
class IntegrationService {
|
|
6
|
+
async runScript(syncName, _activityLogId, nango, _integrationData, _environmentId, _writeToDb, isAction, optionalLoadLocation, input) {
|
|
7
|
+
try {
|
|
8
|
+
const script = localFileService.getIntegrationFile(syncName, optionalLoadLocation);
|
|
9
|
+
if (!script) {
|
|
10
|
+
const content = `Unable to find integration file for ${syncName}`;
|
|
11
|
+
return { success: false, error: new NangoError(content, 500), response: null };
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const wrappedScript = `
|
|
15
|
+
(function() {
|
|
16
|
+
var module = { exports: {} };
|
|
17
|
+
var exports = module.exports;
|
|
18
|
+
${script}
|
|
19
|
+
return module.exports.default || module.exports;
|
|
20
|
+
})();
|
|
21
|
+
`;
|
|
22
|
+
const scriptObj = new vm.Script(wrappedScript);
|
|
23
|
+
const sandbox = {
|
|
24
|
+
console: console,
|
|
25
|
+
require: (moduleName) => {
|
|
26
|
+
switch (moduleName) {
|
|
27
|
+
case 'url':
|
|
28
|
+
return url;
|
|
29
|
+
case 'crypto':
|
|
30
|
+
return crypto;
|
|
31
|
+
default:
|
|
32
|
+
throw new Error(`Module '${moduleName}' is not allowed`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const context = vm.createContext(sandbox);
|
|
37
|
+
const scriptExports = scriptObj.runInContext(context);
|
|
38
|
+
if (scriptExports && typeof scriptExports === 'function') {
|
|
39
|
+
const results = isAction ? await scriptExports(nango, input) : await scriptExports(nango);
|
|
40
|
+
return { success: true, error: null, response: results };
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const content = `There is no default export that is a function for ${syncName}`;
|
|
44
|
+
return { success: false, error: new NangoError(content, 500), response: null };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
const errorType = isAction ? 'action_script_failure' : 'sync_script_failre';
|
|
49
|
+
return formatScriptError(err, errorType, syncName);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const errorMessage = JSON.stringify(err, ['message', 'name', 'stack'], 2);
|
|
54
|
+
const content = `The script failed to load for ${syncName} with the following error: ${errorMessage}`;
|
|
55
|
+
return { success: false, error: new NangoError(content, 500), response: null };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export default new IntegrationService();
|
|
60
|
+
//# sourceMappingURL=local-integration.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-integration.service.js","sourceRoot":"","sources":["../lib/local-integration.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const tableName = '<%= tableName %>'';
|
|
2
|
+
|
|
3
|
+
exports.up = function (knex, _) {
|
|
4
|
+
return knex.schema.withSchema('nango').createTable(tableName, function (table) {
|
|
5
|
+
return knex.schema.withSchema('nango').createTable(tableName, function (table) {
|
|
6
|
+
table.increments('id').primary();
|
|
7
|
+
<% data.forEach(function(model) { %>
|
|
8
|
+
<% Object.keys(model).forEach(function(prop) { %>
|
|
9
|
+
<% if (prop === 'id') { return; } %>
|
|
10
|
+
<% const type = model[prop]; %>
|
|
11
|
+
<% switch (type) { %>
|
|
12
|
+
<% case 'integer': %>
|
|
13
|
+
table.integer('<%= prop %>');
|
|
14
|
+
<% break; %>
|
|
15
|
+
<% case 'char': %>
|
|
16
|
+
table.string('<%= prop %>', 255);
|
|
17
|
+
<% break; %>
|
|
18
|
+
<% case 'text': %>
|
|
19
|
+
table.text('<%= prop %>');
|
|
20
|
+
<% break; %>
|
|
21
|
+
<% case 'timestamp': %>
|
|
22
|
+
table.timestamp('<%= prop %>');
|
|
23
|
+
<% break; %>
|
|
24
|
+
<% default: %>
|
|
25
|
+
throw new Error(`Unknown type <%= type %> for column <%= prop %>`);
|
|
26
|
+
<% } %>
|
|
27
|
+
<% }); %>
|
|
28
|
+
<% }); %>
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.down = function (knex, _) {
|
|
33
|
+
return knex.schema.withSchema('nango').dropTable(tableName);
|
|
34
|
+
};
|
|
35
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import * as tsNode from 'ts-node';
|
|
3
|
+
import glob from 'glob';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { SyncConfigType } from '@nangohq/shared';
|
|
7
|
+
import yamlService from './yaml.service.js';
|
|
8
|
+
import { getNangoRootPath, printDebug } from '../utils.js';
|
|
9
|
+
import { TYPES_FILE_NAME } from '../constants.js';
|
|
10
|
+
import modelService from './model.service.js';
|
|
11
|
+
import parserService from './parser.service.js';
|
|
12
|
+
class CompileService {
|
|
13
|
+
async run(debug = false, syncName) {
|
|
14
|
+
const tsconfig = fs.readFileSync(`${getNangoRootPath()}/tsconfig.dev.json`, 'utf8');
|
|
15
|
+
const distDir = './dist';
|
|
16
|
+
if (!fs.existsSync(distDir)) {
|
|
17
|
+
if (debug) {
|
|
18
|
+
printDebug(`Creating ${distDir} directory`);
|
|
19
|
+
}
|
|
20
|
+
fs.mkdirSync(distDir);
|
|
21
|
+
}
|
|
22
|
+
if (!fs.existsSync(`./${TYPES_FILE_NAME}`)) {
|
|
23
|
+
if (debug) {
|
|
24
|
+
printDebug(`Creating ${TYPES_FILE_NAME} file`);
|
|
25
|
+
}
|
|
26
|
+
await modelService.createModelFile();
|
|
27
|
+
}
|
|
28
|
+
const compiler = tsNode.create({
|
|
29
|
+
compilerOptions: JSON.parse(tsconfig).compilerOptions
|
|
30
|
+
});
|
|
31
|
+
if (debug) {
|
|
32
|
+
printDebug(`Compiler options: ${JSON.stringify(JSON.parse(tsconfig).compilerOptions, null, 2)}`);
|
|
33
|
+
}
|
|
34
|
+
const integrationFiles = syncName ? [`./${syncName}.ts`] : glob.sync(`./*.ts`);
|
|
35
|
+
let success = true;
|
|
36
|
+
const config = await yamlService.getConfig();
|
|
37
|
+
const modelNames = yamlService.getModelNames(config);
|
|
38
|
+
for (const filePath of integrationFiles) {
|
|
39
|
+
try {
|
|
40
|
+
const providerConfiguration = config.find((config) => [...config.syncs, ...config.actions].find((sync) => sync.name === path.basename(filePath, '.ts')));
|
|
41
|
+
if (!providerConfiguration) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const syncConfig = [...providerConfiguration.syncs, ...providerConfiguration.actions].find((sync) => sync.name === path.basename(filePath, '.ts'));
|
|
45
|
+
const type = syncConfig?.type || SyncConfigType.SYNC;
|
|
46
|
+
if (!parserService.callsAreUsedCorrectly(filePath, type, modelNames)) {
|
|
47
|
+
if (syncName && filePath.includes(syncName)) {
|
|
48
|
+
success = false;
|
|
49
|
+
}
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const result = compiler.compile(fs.readFileSync(filePath, 'utf8'), filePath);
|
|
53
|
+
const jsFilePath = filePath.replace(/\/[^\/]*$/, `/dist/${path.basename(filePath.replace('.ts', '.js'))}`);
|
|
54
|
+
fs.writeFileSync(jsFilePath, result);
|
|
55
|
+
console.log(chalk.green(`Compiled "${filePath}" successfully`));
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error(`Error compiling "${filePath}":`);
|
|
59
|
+
console.error(error);
|
|
60
|
+
success = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return success;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const compileService = new CompileService();
|
|
67
|
+
export default compileService;
|
|
68
|
+
//# sourceMappingURL=compile%20copy.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile copy.service.js","sourceRoot":"","sources":["../../lib/services/compile copy.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { StandardNangoConfig } from '@nangohq/shared';
|
|
2
|
+
declare class YamlService {
|
|
3
|
+
getConfig(optionalLoadLocation?: string, debug?: boolean): Promise<StandardNangoConfig[]>;
|
|
4
|
+
getModelNames(config: StandardNangoConfig[]): string[];
|
|
5
|
+
}
|
|
6
|
+
declare const yamlService: YamlService;
|
|
7
|
+
export default yamlService;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { loadStandardConfig, nangoConfigFile } from '@nangohq/shared';
|
|
2
|
+
import { printDebug } from '../utils.js';
|
|
3
|
+
class YamlService {
|
|
4
|
+
async getConfig(optionalLoadLocation = '', debug = false) {
|
|
5
|
+
const loadLocation = optionalLoadLocation || './';
|
|
6
|
+
const config = await loadStandardConfig(loadLocation);
|
|
7
|
+
if (!config) {
|
|
8
|
+
throw new Error(`Error loading the ${nangoConfigFile} file`);
|
|
9
|
+
}
|
|
10
|
+
if (debug) {
|
|
11
|
+
printDebug(`Config file file found`);
|
|
12
|
+
}
|
|
13
|
+
return config;
|
|
14
|
+
}
|
|
15
|
+
getModelNames(config) {
|
|
16
|
+
const modelNames = config.reduce((acc, config) => {
|
|
17
|
+
const syncs = config.syncs || [];
|
|
18
|
+
const actions = config.actions || [];
|
|
19
|
+
const allSyncs = [...syncs, ...actions];
|
|
20
|
+
const models = allSyncs.reduce((acc, sync) => {
|
|
21
|
+
const models = sync.models || [];
|
|
22
|
+
const names = models.map((model) => model.name);
|
|
23
|
+
return [...acc, ...names];
|
|
24
|
+
}, []);
|
|
25
|
+
return [...acc, ...models];
|
|
26
|
+
}, []);
|
|
27
|
+
return modelNames;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const yamlService = new YamlService();
|
|
31
|
+
export default yamlService;
|
|
32
|
+
//# sourceMappingURL=yaml.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.service.js","sourceRoot":"","sources":["../../lib/services/yaml.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW;IACN,KAAK,CAAC,SAAS,CAAC,oBAAoB,GAAG,EAAE,EAAE,KAAK,GAAG,KAAK;QAC3D,MAAM,YAAY,GAAG,oBAAoB,IAAI,IAAI,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAEtD,IAAI,CAAC,MAAM,EAAE;YACT,MAAM,IAAI,KAAK,CAAC,qBAAqB,eAAe,OAAO,CAAC,CAAC;SAChE;QAED,IAAI,KAAK,EAAE;YACP,UAAU,CAAC,wBAAwB,CAAC,CAAC;SACxC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAEM,aAAa,CAAC,MAA6B;QAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAa,EAAE,MAAM,EAAE,EAAE;YACvD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC,CAAC;YACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAa,EAAE,IAAI,EAAE,EAAE;gBACnD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;gBACjC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAChD,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;YAC9B,CAAC,EAAE,EAAE,CAAC,CAAC;YACP,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC;QAC/B,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AAED,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AACtC,eAAe,WAAW,CAAC"}
|
package/dist/sync.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const exampleSyncName = "github-issue-example";
|
|
2
|
+
export declare const version: (debug: boolean) => void;
|
|
3
|
+
export declare const generate: (debug?: boolean, inParentDirectory?: boolean) => Promise<void>;
|
|
4
|
+
/**
|
|
5
|
+
* Init
|
|
6
|
+
* If we're not currently in the nango-integrations directory create one
|
|
7
|
+
* and create an example nango.yaml file
|
|
8
|
+
*/
|
|
9
|
+
export declare const init: (debug?: boolean) => Promise<void>;
|
|
10
|
+
export declare const tscWatch: (debug?: boolean) => Promise<void>;
|
|
11
|
+
export declare const configWatch: (debug?: boolean) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Docker Run
|
|
14
|
+
* @desc spawn a child process to run the docker compose located in the cli
|
|
15
|
+
* Look into https://www.npmjs.com/package/docker-compose to avoid dependency maybe?
|
|
16
|
+
*/
|
|
17
|
+
export declare const dockerRun: (debug?: boolean) => Promise<void>;
|
package/dist/sync.ejs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const formattedInterfaceNames = Array.isArray(interfaceNames) ? interfaceNames.join(', ') : interfaceNames;
|
|
3
|
+
%>
|
|
4
|
+
import type { NangoSync<%= formattedInterfaceNames ? ', ' + formattedInterfaceNames : '' %> } from './<%= interfaceFileName %>';
|
|
5
|
+
|
|
6
|
+
export default async function fetchData(nango: NangoSync): Promise<void> {
|
|
7
|
+
// Integration code goes here
|
|
8
|
+
// to save data use await nango.batchSave
|
|
9
|
+
// to delete data use await nango.batchDelete
|
|
10
|
+
}
|
package/dist/sync.js
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path, { dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import yaml from 'js-yaml';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import chokidar from 'chokidar';
|
|
7
|
+
import * as tsNode from 'ts-node';
|
|
8
|
+
import glob from 'glob';
|
|
9
|
+
import ejs from 'ejs';
|
|
10
|
+
import * as dotenv from 'dotenv';
|
|
11
|
+
import { spawn } from 'child_process';
|
|
12
|
+
import 'promptly';
|
|
13
|
+
import { nangoConfigFile, SyncConfigType, JAVASCRIPT_PRIMITIVES } from '@nangohq/shared';
|
|
14
|
+
import { NANGO_INTEGRATIONS_NAME, getNangoRootPath, printDebug } from './utils.js';
|
|
15
|
+
import yamlService from './services/yaml.service.js';
|
|
16
|
+
import modelService from './services/model.service.js';
|
|
17
|
+
import parserService from './services/parser.service.js';
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = dirname(__filename);
|
|
20
|
+
dotenv.config();
|
|
21
|
+
const TYPES_FILE_NAME = 'models.ts';
|
|
22
|
+
const NangoSyncTypesFileLocation = 'dist/nango-sync.d.ts';
|
|
23
|
+
export const exampleSyncName = 'github-issue-example';
|
|
24
|
+
export const version = (debug) => {
|
|
25
|
+
if (debug) {
|
|
26
|
+
printDebug('Looking up the version first for a local path first then globally');
|
|
27
|
+
}
|
|
28
|
+
const packageJson = JSON.parse(fs.readFileSync(path.resolve(getNangoRootPath(debug), 'package.json'), 'utf8'));
|
|
29
|
+
const dockerComposeYaml = fs.readFileSync(path.resolve(getNangoRootPath(), 'docker/docker-compose.yaml'), 'utf8');
|
|
30
|
+
const dockerCompose = yaml.load(dockerComposeYaml);
|
|
31
|
+
const nangoServerImage = dockerCompose.services['nango-server'].image;
|
|
32
|
+
const nangoWorkerImage = dockerCompose.services['nango-worker'].image;
|
|
33
|
+
const nangoServerVersion = nangoServerImage.split(':').pop();
|
|
34
|
+
const nangoWorkerVersion = nangoWorkerImage.split(':').pop();
|
|
35
|
+
console.log(chalk.green('Nango Server version:'), nangoServerVersion);
|
|
36
|
+
console.log(chalk.green('Nango Worker version:'), nangoWorkerVersion);
|
|
37
|
+
console.log(chalk.green('Nango CLI version:'), packageJson.version);
|
|
38
|
+
};
|
|
39
|
+
export const generate = async (debug = false, inParentDirectory = false) => {
|
|
40
|
+
const dirPrefix = inParentDirectory ? `./${NANGO_INTEGRATIONS_NAME}` : '.';
|
|
41
|
+
const syncTemplateContents = fs.readFileSync(path.resolve(__dirname, './templates/sync.ejs'), 'utf8');
|
|
42
|
+
const actionTemplateContents = fs.readFileSync(path.resolve(__dirname, './templates/action.ejs'), 'utf8');
|
|
43
|
+
const githubExampleTemplateContents = fs.readFileSync(path.resolve(__dirname, './templates/github.sync.ejs'), 'utf8');
|
|
44
|
+
const configContents = fs.readFileSync(`${dirPrefix}/${nangoConfigFile}`, 'utf8');
|
|
45
|
+
const configData = yaml.load(configContents);
|
|
46
|
+
const { integrations } = configData;
|
|
47
|
+
const { models } = configData;
|
|
48
|
+
const interfaceDefinitions = modelService.build(models, integrations, debug);
|
|
49
|
+
if (interfaceDefinitions) {
|
|
50
|
+
fs.writeFileSync(`${dirPrefix}/${TYPES_FILE_NAME}`, interfaceDefinitions.join('\n'));
|
|
51
|
+
}
|
|
52
|
+
if (debug) {
|
|
53
|
+
printDebug(`Interfaces from the ${nangoConfigFile} file written to ${TYPES_FILE_NAME}`);
|
|
54
|
+
}
|
|
55
|
+
// insert NangoSync types to the bottom of the file
|
|
56
|
+
const typesContent = fs.readFileSync(`${getNangoRootPath()}/${NangoSyncTypesFileLocation}`, 'utf8');
|
|
57
|
+
fs.writeFileSync(`${dirPrefix}/${TYPES_FILE_NAME}`, typesContent, { flag: 'a' });
|
|
58
|
+
const config = await yamlService.getConfig(dirPrefix, debug);
|
|
59
|
+
const flowConfig = `export const NangoFlows = ${JSON.stringify(config, null, 2)} as const; \n`;
|
|
60
|
+
fs.writeFileSync(`${dirPrefix}/${TYPES_FILE_NAME}`, flowConfig, { flag: 'a' });
|
|
61
|
+
if (debug) {
|
|
62
|
+
printDebug(`NangoSync types written to ${TYPES_FILE_NAME}`);
|
|
63
|
+
}
|
|
64
|
+
const allSyncNames = {};
|
|
65
|
+
for (let i = 0; i < Object.keys(integrations).length; i++) {
|
|
66
|
+
const providerConfigKey = Object.keys(integrations)[i];
|
|
67
|
+
if (debug) {
|
|
68
|
+
printDebug(`Generating ${providerConfigKey} integrations`);
|
|
69
|
+
}
|
|
70
|
+
const syncObject = integrations[providerConfigKey];
|
|
71
|
+
const syncNames = Object.keys(syncObject);
|
|
72
|
+
for (let k = 0; k < syncNames.length; k++) {
|
|
73
|
+
const syncName = syncNames[k];
|
|
74
|
+
if (allSyncNames[syncName] === undefined) {
|
|
75
|
+
allSyncNames[syncName] = true;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
console.log(chalk.red(`The sync name ${syncName} is duplicated in the ${nangoConfigFile} file. All sync names must be unique.`));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
if (debug) {
|
|
82
|
+
printDebug(`Generating ${syncName} integration`);
|
|
83
|
+
}
|
|
84
|
+
const syncData = syncObject[syncName];
|
|
85
|
+
if (syncData.type !== SyncConfigType.ACTION && !syncData.returns) {
|
|
86
|
+
console.log(chalk.red(`The ${syncName} integration is missing a returns property for what models the sync returns. Make sure you have "returns" instead of "return"`));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
const { returns: modelOrModels, input, type = SyncConfigType.SYNC } = syncData;
|
|
90
|
+
const syncNameCamel = syncName
|
|
91
|
+
.split('-')
|
|
92
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
93
|
+
.join('');
|
|
94
|
+
let ejsTemplateContents = '';
|
|
95
|
+
if (syncName === exampleSyncName && type === SyncConfigType.SYNC) {
|
|
96
|
+
ejsTemplateContents = githubExampleTemplateContents;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
ejsTemplateContents = type === SyncConfigType.SYNC ? syncTemplateContents : actionTemplateContents;
|
|
100
|
+
}
|
|
101
|
+
const formatModelName = (model) => {
|
|
102
|
+
if (JAVASCRIPT_PRIMITIVES.includes(model)) {
|
|
103
|
+
return '';
|
|
104
|
+
}
|
|
105
|
+
const singularModel = model.charAt(model.length - 1) === 's' ? model.slice(0, -1) : model;
|
|
106
|
+
return `${singularModel.charAt(0).toUpperCase()}${singularModel.slice(1)}`;
|
|
107
|
+
};
|
|
108
|
+
let interfaceNames;
|
|
109
|
+
let mappings;
|
|
110
|
+
if (typeof modelOrModels === 'string') {
|
|
111
|
+
const formattedName = formatModelName(modelOrModels);
|
|
112
|
+
interfaceNames = formattedName;
|
|
113
|
+
mappings = {
|
|
114
|
+
name: modelOrModels,
|
|
115
|
+
type: formattedName
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
interfaceNames = modelOrModels.map(formatModelName);
|
|
120
|
+
mappings = modelOrModels.map((model) => ({
|
|
121
|
+
name: model,
|
|
122
|
+
type: formatModelName(model)
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
const rendered = ejs.render(ejsTemplateContents, {
|
|
126
|
+
syncName: syncNameCamel,
|
|
127
|
+
interfaceFileName: TYPES_FILE_NAME.replace('.ts', ''),
|
|
128
|
+
interfaceNames,
|
|
129
|
+
mappings,
|
|
130
|
+
inputs: input || ''
|
|
131
|
+
});
|
|
132
|
+
const stripped = rendered.replace(/^\s+/, '');
|
|
133
|
+
if (!fs.existsSync(`${dirPrefix}/${syncName}.ts`)) {
|
|
134
|
+
fs.writeFileSync(`${dirPrefix}/${syncName}.ts`, stripped);
|
|
135
|
+
if (debug) {
|
|
136
|
+
printDebug(`Created ${syncName}.ts file`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
if (debug) {
|
|
141
|
+
printDebug(`${syncName}.ts file already exists, so will not overwrite it.`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log(chalk.green(`Integration files have been created`));
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Init
|
|
150
|
+
* If we're not currently in the nango-integrations directory create one
|
|
151
|
+
* and create an example nango.yaml file
|
|
152
|
+
*/
|
|
153
|
+
export const init = async (debug = false) => {
|
|
154
|
+
const yamlData = fs.readFileSync(path.resolve(__dirname, `./templates/${nangoConfigFile}`), 'utf8');
|
|
155
|
+
// if currently in the nango-integrations directory then don't create another one
|
|
156
|
+
const cwd = process.cwd();
|
|
157
|
+
const currentDirectorySplit = cwd.split('/');
|
|
158
|
+
const currentDirectory = currentDirectorySplit[currentDirectorySplit.length - 1];
|
|
159
|
+
let dirExists = false;
|
|
160
|
+
let inParentDirectory = true;
|
|
161
|
+
if (currentDirectory === NANGO_INTEGRATIONS_NAME) {
|
|
162
|
+
dirExists = true;
|
|
163
|
+
inParentDirectory = false;
|
|
164
|
+
if (debug) {
|
|
165
|
+
printDebug(`Currently in the ${NANGO_INTEGRATIONS_NAME} directory so the directory will not be created`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (fs.existsSync(`./${NANGO_INTEGRATIONS_NAME}`)) {
|
|
169
|
+
dirExists = true;
|
|
170
|
+
console.log(chalk.red(`The ${NANGO_INTEGRATIONS_NAME} directory already exists. You should run commands from within this directory`));
|
|
171
|
+
}
|
|
172
|
+
if (!dirExists) {
|
|
173
|
+
if (debug) {
|
|
174
|
+
printDebug(`Creating the nango integrations directory at ./${NANGO_INTEGRATIONS_NAME}`);
|
|
175
|
+
}
|
|
176
|
+
fs.mkdirSync(`./${NANGO_INTEGRATIONS_NAME}`);
|
|
177
|
+
}
|
|
178
|
+
const configFileLocation = inParentDirectory ? `./${NANGO_INTEGRATIONS_NAME}/${nangoConfigFile}` : `./${nangoConfigFile}`;
|
|
179
|
+
if (!fs.existsSync(configFileLocation)) {
|
|
180
|
+
if (debug) {
|
|
181
|
+
printDebug(`Creating the ${nangoConfigFile} file at ${configFileLocation}`);
|
|
182
|
+
}
|
|
183
|
+
fs.writeFileSync(configFileLocation, yamlData);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
if (debug) {
|
|
187
|
+
printDebug(`Nango config file already exists at ${configFileLocation} so not creating a new one`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const envFileLocation = inParentDirectory ? `./${NANGO_INTEGRATIONS_NAME}/.env` : './.env';
|
|
191
|
+
if (!fs.existsSync(envFileLocation)) {
|
|
192
|
+
if (debug) {
|
|
193
|
+
printDebug(`Creating the .env file at ${envFileLocation}`);
|
|
194
|
+
}
|
|
195
|
+
fs.writeFileSync(envFileLocation, `# Authenticates the CLI (get the keys in the dashboard's Projects Settings).
|
|
196
|
+
#NANGO_SECRET_KEY_DEV=xxxx-xxx-xxxx
|
|
197
|
+
#NANGO_SECRET_KEY_PROD=xxxx-xxx-xxxx
|
|
198
|
+
|
|
199
|
+
# Nango's instance URL (OSS: change to http://localhost:3003 or your instance URL).
|
|
200
|
+
NANGO_HOSTPORT=https://api.nango.dev # Default value
|
|
201
|
+
|
|
202
|
+
# How to handle CLI upgrades ("prompt", "auto" or "ignore").
|
|
203
|
+
NANGO_CLI_UPGRADE_MODE=prompt # Default value
|
|
204
|
+
|
|
205
|
+
# Whether to prompt before deployments.
|
|
206
|
+
NANGO_DEPLOY_AUTO_CONFIRM=false # Default value`);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
if (debug) {
|
|
210
|
+
printDebug(`.env file already exists at ${envFileLocation} so not creating a new one`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
await generate(debug, inParentDirectory);
|
|
214
|
+
console.log(chalk.green(`Nango integrations initialized!`));
|
|
215
|
+
};
|
|
216
|
+
export const tscWatch = async (debug = false) => {
|
|
217
|
+
const tsconfig = fs.readFileSync(`${getNangoRootPath()}/tsconfig.dev.json`, 'utf8');
|
|
218
|
+
const config = await yamlService.getConfig();
|
|
219
|
+
const modelNames = yamlService.getModelNames(config);
|
|
220
|
+
const watchPath = [`./*.ts`, `./${nangoConfigFile}`];
|
|
221
|
+
if (debug) {
|
|
222
|
+
printDebug(`Watching ${watchPath.join(', ')}`);
|
|
223
|
+
}
|
|
224
|
+
const watcher = chokidar.watch(watchPath, {
|
|
225
|
+
ignoreInitial: false,
|
|
226
|
+
ignored: (filePath) => {
|
|
227
|
+
return filePath === TYPES_FILE_NAME;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
const distDir = './dist';
|
|
231
|
+
if (!fs.existsSync(distDir)) {
|
|
232
|
+
if (debug) {
|
|
233
|
+
printDebug(`Creating ${distDir} directory`);
|
|
234
|
+
}
|
|
235
|
+
fs.mkdirSync(distDir);
|
|
236
|
+
}
|
|
237
|
+
if (!fs.existsSync(`./${TYPES_FILE_NAME}`)) {
|
|
238
|
+
if (debug) {
|
|
239
|
+
printDebug(`Creating ${TYPES_FILE_NAME} file`);
|
|
240
|
+
}
|
|
241
|
+
await modelService.createModelFile();
|
|
242
|
+
}
|
|
243
|
+
watcher.on('add', (filePath) => {
|
|
244
|
+
if (filePath === nangoConfigFile) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
compileFile(filePath);
|
|
248
|
+
});
|
|
249
|
+
watcher.on('unlink', (filePath) => {
|
|
250
|
+
if (filePath === nangoConfigFile) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const jsFilePath = `./dist/${path.basename(filePath.replace('.ts', '.js'))}`;
|
|
254
|
+
fs.unlinkSync(jsFilePath);
|
|
255
|
+
});
|
|
256
|
+
watcher.on('change', (filePath) => {
|
|
257
|
+
if (filePath === nangoConfigFile) {
|
|
258
|
+
// config file changed, re-compile each ts file
|
|
259
|
+
const integrationFiles = glob.sync(`./*.ts`);
|
|
260
|
+
for (const file of integrationFiles) {
|
|
261
|
+
// strip the file to just the last part
|
|
262
|
+
const strippedFile = file.replace(/^.*[\\\/]/, '');
|
|
263
|
+
compileFile(strippedFile);
|
|
264
|
+
}
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
compileFile(filePath);
|
|
268
|
+
});
|
|
269
|
+
function compileFile(filePath) {
|
|
270
|
+
const compiler = tsNode.create({
|
|
271
|
+
compilerOptions: JSON.parse(tsconfig).compilerOptions
|
|
272
|
+
});
|
|
273
|
+
try {
|
|
274
|
+
const providerConfiguration = config.find((config) => [...config.syncs, ...config.actions].find((sync) => sync.name === path.basename(filePath, '.ts')));
|
|
275
|
+
if (!providerConfiguration) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const syncConfig = [...providerConfiguration.syncs, ...providerConfiguration.actions].find((sync) => sync.name === path.basename(filePath, '.ts'));
|
|
279
|
+
const type = syncConfig?.type || SyncConfigType.SYNC;
|
|
280
|
+
if (!parserService.callsAreUsedCorrectly(filePath, type, modelNames)) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const result = compiler.compile(fs.readFileSync(filePath, 'utf8'), filePath);
|
|
284
|
+
const jsFilePath = `./dist/${path.basename(filePath.replace('.ts', '.js'))}`;
|
|
285
|
+
fs.writeFileSync(jsFilePath, result);
|
|
286
|
+
console.log(chalk.green(`Compiled ${filePath} successfully`));
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
console.error(`Error compiling ${filePath}:`);
|
|
290
|
+
console.error(error);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
export const configWatch = (debug = false) => {
|
|
296
|
+
const watchPath = `./${nangoConfigFile}`;
|
|
297
|
+
if (debug) {
|
|
298
|
+
printDebug(`Watching ${watchPath}`);
|
|
299
|
+
}
|
|
300
|
+
const watcher = chokidar.watch(watchPath, { ignoreInitial: true });
|
|
301
|
+
watcher.on('change', async () => {
|
|
302
|
+
await modelService.createModelFile(true);
|
|
303
|
+
});
|
|
304
|
+
};
|
|
305
|
+
let child;
|
|
306
|
+
process.on('SIGINT', () => {
|
|
307
|
+
if (child) {
|
|
308
|
+
const dockerDown = spawn('docker', ['compose', '-f', `${getNangoRootPath()}/docker/docker-compose.yaml`, '--project-directory', '.', 'down'], {
|
|
309
|
+
stdio: 'inherit'
|
|
310
|
+
});
|
|
311
|
+
dockerDown.on('exit', () => {
|
|
312
|
+
process.exit();
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
process.exit();
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
/**
|
|
320
|
+
* Docker Run
|
|
321
|
+
* @desc spawn a child process to run the docker compose located in the cli
|
|
322
|
+
* Look into https://www.npmjs.com/package/docker-compose to avoid dependency maybe?
|
|
323
|
+
*/
|
|
324
|
+
export const dockerRun = async (debug = false) => {
|
|
325
|
+
const cwd = process.cwd();
|
|
326
|
+
const args = ['compose', '-f', `${getNangoRootPath()}/docker/docker-compose.yaml`, '--project-directory', '.', 'up', '--build'];
|
|
327
|
+
if (debug) {
|
|
328
|
+
printDebug(`Running docker with args: ${args.join(' ')}`);
|
|
329
|
+
}
|
|
330
|
+
child = spawn('docker', args, {
|
|
331
|
+
cwd,
|
|
332
|
+
detached: false,
|
|
333
|
+
stdio: 'inherit'
|
|
334
|
+
});
|
|
335
|
+
await new Promise((resolve, reject) => {
|
|
336
|
+
child?.on('exit', (code) => {
|
|
337
|
+
if (code !== 0) {
|
|
338
|
+
reject(new Error(`Error with the nango docker containers, please check your containers using 'docker ps''`));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
resolve(true);
|
|
342
|
+
});
|
|
343
|
+
child?.on('error', reject);
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
//# sourceMappingURL=sync.js.map
|
package/dist/sync.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../lib/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const tableName = '<%= tableName %>'';
|
|
2
|
+
|
|
3
|
+
exports.up = function (knex, _) {
|
|
4
|
+
return knex.schema.withSchema('nango').createTable(tableName, function (table) {
|
|
5
|
+
return knex.schema.withSchema('nango').createTable(tableName, function (table) {
|
|
6
|
+
table.increments('id').primary();
|
|
7
|
+
<% data.forEach(function(model) { %>
|
|
8
|
+
<% Object.keys(model).forEach(function(prop) { %>
|
|
9
|
+
<% if (prop === 'id') { return; } %>
|
|
10
|
+
<% const type = model[prop]; %>
|
|
11
|
+
<% switch (type) { %>
|
|
12
|
+
<% case 'integer': %>
|
|
13
|
+
table.integer('<%= prop %>');
|
|
14
|
+
<% break; %>
|
|
15
|
+
<% case 'char': %>
|
|
16
|
+
table.string('<%= prop %>', 255);
|
|
17
|
+
<% break; %>
|
|
18
|
+
<% case 'text': %>
|
|
19
|
+
table.text('<%= prop %>');
|
|
20
|
+
<% break; %>
|
|
21
|
+
<% case 'timestamp': %>
|
|
22
|
+
table.timestamp('<%= prop %>');
|
|
23
|
+
<% break; %>
|
|
24
|
+
<% default: %>
|
|
25
|
+
throw new Error(`Unknown type <%= type %> for column <%= prop %>`);
|
|
26
|
+
<% } %>
|
|
27
|
+
<% }); %>
|
|
28
|
+
<% }); %>
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.down = function (knex, _) {
|
|
33
|
+
return knex.schema.withSchema('nango').dropTable(tableName);
|
|
34
|
+
};
|
|
35
|
+
|
|
@@ -15,7 +15,7 @@ services:
|
|
|
15
15
|
- nango
|
|
16
16
|
|
|
17
17
|
nango-server:
|
|
18
|
-
image: nangohq/nango-server:0.36.
|
|
18
|
+
image: nangohq/nango-server:0.36.38
|
|
19
19
|
container_name: nango-server
|
|
20
20
|
environment:
|
|
21
21
|
- TEMPORAL_ADDRESS=temporal:7233
|
|
@@ -47,7 +47,7 @@ services:
|
|
|
47
47
|
- nango
|
|
48
48
|
|
|
49
49
|
nango-worker:
|
|
50
|
-
image: nangohq/nango-worker:0.36.
|
|
50
|
+
image: nangohq/nango-worker:0.36.38
|
|
51
51
|
container_name: nango-worker
|
|
52
52
|
restart: always
|
|
53
53
|
ports:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nango",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.38",
|
|
4
4
|
"description": "Nango's CLI tool.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@babel/traverse": "^7.22.5",
|
|
25
25
|
"@inquirer/prompts": "^2.3.0",
|
|
26
|
-
"@nangohq/shared": "0.36.
|
|
26
|
+
"@nangohq/shared": "0.36.38",
|
|
27
27
|
"@vercel/ncc": "^0.36.1",
|
|
28
28
|
"ajv": "^8.12.0",
|
|
29
29
|
"ajv-errors": "^3.0.0",
|