nango 0.69.21 → 0.69.26
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/index.js +122 -20
- package/dist/index.js.map +1 -1
- package/dist/services/clone.service.d.ts +12 -0
- package/dist/services/clone.service.js +440 -0
- package/dist/services/clone.service.js.map +1 -0
- package/dist/services/dryrun.service.js +23 -82
- package/dist/services/dryrun.service.js.map +1 -1
- package/dist/services/ensure.service.d.ts +18 -0
- package/dist/services/ensure.service.js +60 -0
- package/dist/services/ensure.service.js.map +1 -0
- package/dist/services/function-create.service.d.ts +3 -4
- package/dist/services/function-create.service.js +2 -12
- package/dist/services/function-create.service.js.map +1 -1
- package/dist/services/interactive.service.d.ts +13 -0
- package/dist/services/interactive.service.js +147 -0
- package/dist/services/interactive.service.js.map +1 -0
- package/dist/services/response-collector.service.d.ts +23 -0
- package/dist/services/response-collector.service.js +233 -0
- package/dist/services/response-collector.service.js.map +1 -0
- package/dist/services/sdk.js +2 -1
- package/dist/services/sdk.js.map +1 -1
- package/dist/testMocks/utils.d.ts +137 -51
- package/dist/testMocks/utils.js +755 -172
- package/dist/testMocks/utils.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/errors.d.ts +3 -0
- package/dist/utils/errors.js +6 -0
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.js +15 -0
- package/dist/utils.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +11 -8
- package/dist/migrations/toZeroYaml.unit.test.d.ts +0 -1
- package/dist/migrations/toZeroYaml.unit.test.js +0 -307
- package/dist/migrations/toZeroYaml.unit.test.js.map +0 -1
- package/dist/services/compile.service.unit.test.d.ts +0 -1
- package/dist/services/compile.service.unit.test.js +0 -44
- package/dist/services/compile.service.unit.test.js.map +0 -1
- package/dist/services/config.service.unit.test.d.ts +0 -1
- package/dist/services/config.service.unit.test.js +0 -162
- package/dist/services/config.service.unit.test.js.map +0 -1
- package/dist/services/docs.service.unit.test.d.ts +0 -1
- package/dist/services/docs.service.unit.test.js +0 -51
- package/dist/services/docs.service.unit.test.js.map +0 -1
- package/dist/services/model.service.unit.test.d.ts +0 -1
- package/dist/services/model.service.unit.test.js +0 -240
- package/dist/services/model.service.unit.test.js.map +0 -1
- package/dist/services/response-saver.service.d.ts +0 -17
- package/dist/services/response-saver.service.js +0 -169
- package/dist/services/response-saver.service.js.map +0 -1
- package/dist/services/sdk.service.unit.test.d.ts +0 -1
- package/dist/services/sdk.service.unit.test.js +0 -66
- package/dist/services/sdk.service.unit.test.js.map +0 -1
- package/dist/zeroYaml/definitions.unit.test.d.ts +0 -1
- package/dist/zeroYaml/definitions.unit.test.js +0 -111
- package/dist/zeroYaml/definitions.unit.test.js.map +0 -1
- package/dist/zeroYaml/zodToNango.unit.test.d.ts +0 -1
- package/dist/zeroYaml/zodToNango.unit.test.js +0 -185
- package/dist/zeroYaml/zodToNango.unit.test.js.map +0 -1
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parse } from '@babel/parser';
|
|
4
|
+
import traverse from '@babel/traverse';
|
|
5
|
+
import axios from 'axios';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import promptly from 'promptly';
|
|
9
|
+
import { printDebug } from '../utils.js';
|
|
10
|
+
// GitHub API for directory listings (rate limited: 60/hour unauthenticated, 5000/hour with token)
|
|
11
|
+
const GITHUB_API_BASE = 'https://api.github.com/repos/NangoHQ/integration-templates/contents/integrations';
|
|
12
|
+
// Raw content URL for file downloads (no practical rate limit)
|
|
13
|
+
const GITHUB_RAW_BASE = 'https://raw.githubusercontent.com/NangoHQ/integration-templates/main/integrations';
|
|
14
|
+
class GitHubRateLimitError extends Error {
|
|
15
|
+
constructor(resetTime) {
|
|
16
|
+
const resetDate = resetTime ? new Date(resetTime * 1000) : null;
|
|
17
|
+
const resetMsg = resetDate ? ` Rate limit resets at ${resetDate.toLocaleTimeString()}.` : '';
|
|
18
|
+
super(`GitHub API rate limit exceeded.${resetMsg} Set GITHUB_TOKEN environment variable to increase the limit.`);
|
|
19
|
+
this.name = 'GitHubRateLimitError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
class GitHubNotFoundError extends Error {
|
|
23
|
+
constructor(path) {
|
|
24
|
+
super(`Template not found: ${path}`);
|
|
25
|
+
this.name = 'GitHubNotFoundError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a template path by checking what exists in the remote repository.
|
|
30
|
+
* - If the path matches a directory, returns type: 'directory'
|
|
31
|
+
* - If the path doesn't exist but {path}.ts exists, returns type: 'file' with optional .md
|
|
32
|
+
* - Throws GitHubNotFoundError if neither exists
|
|
33
|
+
*/
|
|
34
|
+
async function resolveTemplatePath(templatePath, debug) {
|
|
35
|
+
const integration = templatePath.split('/')[0];
|
|
36
|
+
if (!integration) {
|
|
37
|
+
throw new Error('Template path cannot be empty');
|
|
38
|
+
}
|
|
39
|
+
// First, try to fetch as a directory
|
|
40
|
+
try {
|
|
41
|
+
await fetchGitHubDirectory(templatePath, debug);
|
|
42
|
+
printDebug(`Path "${templatePath}" resolved as directory`, debug);
|
|
43
|
+
return { type: 'directory', path: templatePath, integration };
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (!(err instanceof GitHubNotFoundError)) {
|
|
47
|
+
throw err; // Re-throw rate limits, network errors, etc.
|
|
48
|
+
}
|
|
49
|
+
// Directory doesn't exist, try as file
|
|
50
|
+
}
|
|
51
|
+
const tsPath = `${templatePath}.ts`;
|
|
52
|
+
try {
|
|
53
|
+
await fetchFileContent(tsPath, debug);
|
|
54
|
+
printDebug(`Path "${templatePath}" resolved as file: ${tsPath}`, debug);
|
|
55
|
+
// Check if companion .md file exists
|
|
56
|
+
const mdPath = `${templatePath}.md`;
|
|
57
|
+
let hasMdFile = false;
|
|
58
|
+
try {
|
|
59
|
+
await fetchFileContent(mdPath, debug);
|
|
60
|
+
hasMdFile = true;
|
|
61
|
+
printDebug(`Found companion documentation: ${mdPath}`, debug);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
printDebug(`No companion documentation found for ${templatePath}`, debug);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
type: 'file',
|
|
68
|
+
path: tsPath,
|
|
69
|
+
mdPath: hasMdFile ? mdPath : undefined,
|
|
70
|
+
integration
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (!(err instanceof GitHubNotFoundError) && !(err instanceof Error && err.message.startsWith('File not found'))) {
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Neither directory nor file exists
|
|
79
|
+
throw new GitHubNotFoundError(templatePath);
|
|
80
|
+
}
|
|
81
|
+
function getGitHubHeaders() {
|
|
82
|
+
const headers = {
|
|
83
|
+
Accept: 'application/vnd.github.v3+json',
|
|
84
|
+
'User-Agent': 'nango-cli'
|
|
85
|
+
};
|
|
86
|
+
const token = process.env['GITHUB_TOKEN'];
|
|
87
|
+
if (token) {
|
|
88
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
89
|
+
}
|
|
90
|
+
return headers;
|
|
91
|
+
}
|
|
92
|
+
async function fetchGitHubDirectory(urlPath, debug) {
|
|
93
|
+
const url = `${GITHUB_API_BASE}/${urlPath}`;
|
|
94
|
+
printDebug(`Fetching GitHub directory: ${url}`, debug);
|
|
95
|
+
try {
|
|
96
|
+
const response = await axios.get(url, {
|
|
97
|
+
headers: getGitHubHeaders()
|
|
98
|
+
});
|
|
99
|
+
return response.data;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
if (axios.isAxiosError(err)) {
|
|
103
|
+
if (err.response?.status === 403) {
|
|
104
|
+
const resetTime = err.response.headers['x-ratelimit-reset'];
|
|
105
|
+
throw new GitHubRateLimitError(resetTime ? Number(resetTime) : undefined);
|
|
106
|
+
}
|
|
107
|
+
if (err.response?.status === 404) {
|
|
108
|
+
throw new GitHubNotFoundError(urlPath);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Fetch file content from GitHub raw URL
|
|
116
|
+
* Uses raw.githubusercontent.com which has higher rate limits than the API
|
|
117
|
+
*/
|
|
118
|
+
async function fetchFileContent(urlPath, debug) {
|
|
119
|
+
const url = `${GITHUB_RAW_BASE}/${urlPath}`;
|
|
120
|
+
printDebug(`Fetching file: ${url}`, debug);
|
|
121
|
+
try {
|
|
122
|
+
const response = await axios.get(url, {
|
|
123
|
+
headers: { 'User-Agent': 'nango-cli' },
|
|
124
|
+
responseType: 'text'
|
|
125
|
+
});
|
|
126
|
+
return response.data;
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
if (axios.isAxiosError(err)) {
|
|
130
|
+
if (err.response?.status === 404) {
|
|
131
|
+
throw new Error(`File not found: ${urlPath}`);
|
|
132
|
+
}
|
|
133
|
+
if (err.response?.status === 403) {
|
|
134
|
+
throw new GitHubRateLimitError();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Recursively fetch all files from a directory in the GitHub repository.
|
|
142
|
+
* Returns file paths relative to the integrations root (e.g., "github/actions/list-repos.ts")
|
|
143
|
+
*/
|
|
144
|
+
async function fetchDirectoryRecursively(dirPath, debug) {
|
|
145
|
+
const files = [];
|
|
146
|
+
const contents = await fetchGitHubDirectory(dirPath, debug);
|
|
147
|
+
for (const item of contents) {
|
|
148
|
+
if (item.type === 'dir') {
|
|
149
|
+
const subFiles = await fetchDirectoryRecursively(item.path.replace(/^integrations\//, ''), debug);
|
|
150
|
+
files.push(...subFiles);
|
|
151
|
+
}
|
|
152
|
+
else if (item.type === 'file') {
|
|
153
|
+
const relativePath = item.path.replace(/^integrations\//, '');
|
|
154
|
+
// Determine if this is a script (in actions/syncs folders)
|
|
155
|
+
const isScript = /\/(actions|syncs)\/[^/]+\.ts$/.test(relativePath);
|
|
156
|
+
files.push({ relativePath, isScript });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return files;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Parse local imports from a TypeScript file content using Babel
|
|
163
|
+
* Returns relative import paths (starting with ./ or ../)
|
|
164
|
+
*/
|
|
165
|
+
function parseLocalImports(content) {
|
|
166
|
+
const imports = [];
|
|
167
|
+
try {
|
|
168
|
+
const ast = parse(content, {
|
|
169
|
+
sourceType: 'module',
|
|
170
|
+
plugins: ['typescript']
|
|
171
|
+
});
|
|
172
|
+
const traverseFn = traverse.default || traverse;
|
|
173
|
+
traverseFn(ast, {
|
|
174
|
+
ImportDeclaration(nodePath) {
|
|
175
|
+
const source = nodePath.node.source.value;
|
|
176
|
+
// Only collect relative imports (starting with . or ..)
|
|
177
|
+
if (source.startsWith('./') || source.startsWith('../')) {
|
|
178
|
+
imports.push(source);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
return imports;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Resolve a relative import path to an absolute path within the integration
|
|
190
|
+
* @param importPath - The import path (e.g., '../mappers/toCompany.js')
|
|
191
|
+
* @param fromFilePath - The file containing the import (e.g., 'hubspot/actions/create-company.ts')
|
|
192
|
+
* @returns The resolved path (e.g., 'hubspot/mappers/toCompany.ts') or null if outside integration
|
|
193
|
+
*/
|
|
194
|
+
function resolveImportPath(importPath, fromFilePath) {
|
|
195
|
+
const fromDir = path.dirname(fromFilePath);
|
|
196
|
+
// Resolve the import path relative to the importing file's directory
|
|
197
|
+
// Convert .js extension to .ts (TypeScript source)
|
|
198
|
+
const tsPath = importPath.replace(/\.js$/, '.ts');
|
|
199
|
+
const resolved = path.normalize(path.join(fromDir, tsPath));
|
|
200
|
+
// Ensure the resolved path stays within the integration (no leading ..)
|
|
201
|
+
if (resolved.startsWith('..')) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
return resolved;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Recursively collect all dependencies for a set of files
|
|
208
|
+
* Also caches file content to avoid double-fetching
|
|
209
|
+
*/
|
|
210
|
+
async function collectDependencies(initialFiles, integration, debug, contentCache) {
|
|
211
|
+
const allFiles = new Map();
|
|
212
|
+
const processedFiles = new Set();
|
|
213
|
+
const filesToProcess = [];
|
|
214
|
+
for (const file of initialFiles) {
|
|
215
|
+
allFiles.set(file.relativePath, file);
|
|
216
|
+
if (file.relativePath.endsWith('.ts')) {
|
|
217
|
+
filesToProcess.push(file.relativePath);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
while (filesToProcess.length > 0) {
|
|
221
|
+
const filePath = filesToProcess.pop();
|
|
222
|
+
if (processedFiles.has(filePath)) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
processedFiles.add(filePath);
|
|
226
|
+
let content;
|
|
227
|
+
try {
|
|
228
|
+
if (contentCache.has(filePath)) {
|
|
229
|
+
content = contentCache.get(filePath);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
content = await fetchFileContent(filePath, debug);
|
|
233
|
+
contentCache.set(filePath, content);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
printDebug(`Could not fetch ${filePath} for dependency analysis`, debug);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const imports = parseLocalImports(content);
|
|
241
|
+
printDebug(`Found ${imports.length} local imports in ${filePath}: ${imports.join(', ')}`, debug);
|
|
242
|
+
for (const importPath of imports) {
|
|
243
|
+
const resolvedPath = resolveImportPath(importPath, filePath);
|
|
244
|
+
if (!resolvedPath) {
|
|
245
|
+
printDebug(`Skipping import ${importPath} - resolves outside integration`, debug);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
// Check if this is a file within our integration
|
|
249
|
+
if (!resolvedPath.startsWith(integration + '/')) {
|
|
250
|
+
printDebug(`Skipping import ${importPath} - outside integration folder`, debug);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (allFiles.has(resolvedPath)) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
// Check if file exists on GitHub
|
|
257
|
+
try {
|
|
258
|
+
const depContent = await fetchFileContent(resolvedPath, debug);
|
|
259
|
+
contentCache.set(resolvedPath, depContent);
|
|
260
|
+
// Dependencies are never scripts (they're helpers/mappers/etc.)
|
|
261
|
+
allFiles.set(resolvedPath, { relativePath: resolvedPath, isScript: false });
|
|
262
|
+
filesToProcess.push(resolvedPath);
|
|
263
|
+
printDebug(`Added dependency: ${resolvedPath}`, debug);
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
printDebug(`Dependency not found on GitHub: ${resolvedPath}`, debug);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return Array.from(allFiles.values());
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Get all files to clone based on the resolved template path, including dependencies
|
|
274
|
+
*/
|
|
275
|
+
async function getFilesToClone(resolved, debug) {
|
|
276
|
+
const files = [];
|
|
277
|
+
const { type, path: resolvedPath, mdPath, integration } = resolved;
|
|
278
|
+
if (type === 'file') {
|
|
279
|
+
const isScript = /\/(actions|syncs)\/[^/]+\.ts$/.test(resolvedPath);
|
|
280
|
+
files.push({ relativePath: resolvedPath, isScript });
|
|
281
|
+
if (mdPath) {
|
|
282
|
+
files.push({ relativePath: mdPath, isScript: false });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
const dirFiles = await fetchDirectoryRecursively(resolvedPath, debug);
|
|
287
|
+
files.push(...dirFiles);
|
|
288
|
+
}
|
|
289
|
+
// Collect dependencies for all TypeScript files
|
|
290
|
+
const contentCache = new Map();
|
|
291
|
+
const filesWithDependencies = await collectDependencies(files, integration, debug, contentCache);
|
|
292
|
+
return { files: filesWithDependencies, contentCache };
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Check for existing files to avoid accidental overwrites and prompt user if needed
|
|
296
|
+
*/
|
|
297
|
+
async function checkExistingFiles(fullPath, files, force, autoConfirm, debug) {
|
|
298
|
+
const existingFiles = [];
|
|
299
|
+
const filesToSkip = new Set();
|
|
300
|
+
for (const file of files) {
|
|
301
|
+
const localPath = path.join(fullPath, file.relativePath);
|
|
302
|
+
if (fs.existsSync(localPath)) {
|
|
303
|
+
existingFiles.push(file.relativePath);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (existingFiles.length === 0) {
|
|
307
|
+
return { proceed: true, filesToSkip };
|
|
308
|
+
}
|
|
309
|
+
if (force) {
|
|
310
|
+
printDebug(`Force mode: overwriting ${existingFiles.length} existing files`, debug);
|
|
311
|
+
return { proceed: true, filesToSkip };
|
|
312
|
+
}
|
|
313
|
+
console.log(chalk.yellow(`\nThe following files already exist:`));
|
|
314
|
+
for (const file of existingFiles) {
|
|
315
|
+
console.log(chalk.yellow(` - ${file}`));
|
|
316
|
+
}
|
|
317
|
+
if (autoConfirm) {
|
|
318
|
+
console.log(chalk.yellow(`Auto-confirm enabled: overwriting files`));
|
|
319
|
+
return { proceed: true, filesToSkip };
|
|
320
|
+
}
|
|
321
|
+
const answer = await promptly.prompt(chalk.yellow(`\nDo you want to overwrite these files? (yes/no/skip): `), { default: 'no' });
|
|
322
|
+
if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {
|
|
323
|
+
return { proceed: true, filesToSkip };
|
|
324
|
+
}
|
|
325
|
+
if (answer.toLowerCase() === 'skip' || answer.toLowerCase() === 's') {
|
|
326
|
+
for (const file of existingFiles) {
|
|
327
|
+
filesToSkip.add(file);
|
|
328
|
+
}
|
|
329
|
+
return { proceed: true, filesToSkip };
|
|
330
|
+
}
|
|
331
|
+
return { proceed: false, filesToSkip };
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Update the index.ts file with new imports
|
|
335
|
+
*/
|
|
336
|
+
async function updateIndexFile(fullPath, files, debug) {
|
|
337
|
+
const indexPath = path.join(fullPath, 'index.ts');
|
|
338
|
+
let indexContent = '';
|
|
339
|
+
if (fs.existsSync(indexPath)) {
|
|
340
|
+
indexContent = await fs.promises.readFile(indexPath, 'utf-8');
|
|
341
|
+
}
|
|
342
|
+
const scriptFiles = files.filter((f) => f.isScript && f.relativePath.endsWith('.ts'));
|
|
343
|
+
const newImports = [];
|
|
344
|
+
for (const file of scriptFiles) {
|
|
345
|
+
// Convert path like "github/actions/list-repos.ts" to "./github/actions/list-repos.js"
|
|
346
|
+
const importPath = './' + file.relativePath.replace(/\.ts$/, '.js');
|
|
347
|
+
const importStatement = `import '${importPath}';`;
|
|
348
|
+
if (!indexContent.includes(importPath)) {
|
|
349
|
+
newImports.push(importStatement);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (newImports.length > 0) {
|
|
353
|
+
printDebug(`Adding ${newImports.length} new imports to index.ts`, debug);
|
|
354
|
+
const updatedContent = indexContent.trim() + '\n' + newImports.join('\n') + '\n';
|
|
355
|
+
await fs.promises.writeFile(indexPath, updatedContent, 'utf-8');
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Main clone function - clones integration templates from the integration-templates repository
|
|
360
|
+
*/
|
|
361
|
+
export async function cloneTemplate(options) {
|
|
362
|
+
const { fullPath, templatePath, debug, force, autoConfirm } = options;
|
|
363
|
+
const spinner = ora({ text: `Resolving template path: ${templatePath}` }).start();
|
|
364
|
+
try {
|
|
365
|
+
const resolved = await resolveTemplatePath(templatePath, debug);
|
|
366
|
+
printDebug(`Resolved template path: ${JSON.stringify(resolved)}`, debug);
|
|
367
|
+
spinner.text = `Fetching file list for: ${templatePath}`;
|
|
368
|
+
const { files, contentCache } = await getFilesToClone(resolved, debug);
|
|
369
|
+
if (files.length === 0) {
|
|
370
|
+
spinner.fail(`No files found for template: ${templatePath}`);
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
printDebug(`Found ${files.length} files to clone`, debug);
|
|
374
|
+
spinner.succeed(`Found ${files.length} files to clone`);
|
|
375
|
+
const { proceed, filesToSkip } = await checkExistingFiles(fullPath, files, force, autoConfirm, debug);
|
|
376
|
+
if (!proceed) {
|
|
377
|
+
console.log(chalk.yellow('Clone cancelled.'));
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
const downloadSpinner = ora({ text: 'Downloading files...' }).start();
|
|
381
|
+
let downloadedCount = 0;
|
|
382
|
+
let skippedCount = 0;
|
|
383
|
+
for (const file of files) {
|
|
384
|
+
if (filesToSkip.has(file.relativePath)) {
|
|
385
|
+
skippedCount++;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
downloadSpinner.text = `Downloading: ${file.relativePath}`;
|
|
389
|
+
try {
|
|
390
|
+
let content;
|
|
391
|
+
if (contentCache.has(file.relativePath)) {
|
|
392
|
+
content = contentCache.get(file.relativePath);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
content = await fetchFileContent(file.relativePath, debug);
|
|
396
|
+
}
|
|
397
|
+
const localPath = path.join(fullPath, file.relativePath);
|
|
398
|
+
// Ensure directory exists
|
|
399
|
+
await fs.promises.mkdir(path.dirname(localPath), { recursive: true });
|
|
400
|
+
await fs.promises.writeFile(localPath, content, 'utf-8');
|
|
401
|
+
downloadedCount++;
|
|
402
|
+
}
|
|
403
|
+
catch (err) {
|
|
404
|
+
downloadSpinner.fail(`Failed to download: ${file.relativePath}`);
|
|
405
|
+
if (err instanceof Error) {
|
|
406
|
+
console.log(chalk.red(` Error: ${err.message}`));
|
|
407
|
+
}
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
downloadSpinner.succeed(`Downloaded ${downloadedCount} files${skippedCount > 0 ? ` (${skippedCount} skipped)` : ''}`);
|
|
412
|
+
// Update index.ts
|
|
413
|
+
const indexSpinner = ora({ text: 'Updating index.ts...' }).start();
|
|
414
|
+
await updateIndexFile(fullPath, files.filter((f) => !filesToSkip.has(f.relativePath)), debug);
|
|
415
|
+
indexSpinner.succeed('Updated index.ts');
|
|
416
|
+
console.log('');
|
|
417
|
+
console.log(chalk.green(`Successfully cloned template: ${templatePath}`));
|
|
418
|
+
console.log(chalk.gray(`\nFiles written to: ${fullPath}`));
|
|
419
|
+
const scriptFiles = files.filter((f) => f.isScript && !filesToSkip.has(f.relativePath));
|
|
420
|
+
if (scriptFiles.length > 0) {
|
|
421
|
+
console.log(chalk.gray(`\nScripts added:`));
|
|
422
|
+
for (const file of scriptFiles) {
|
|
423
|
+
console.log(chalk.gray(` - ${file.relativePath}`));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
console.log(`\nNext steps:`);
|
|
427
|
+
console.log(` 1. Review and customize the pulled scripts`);
|
|
428
|
+
console.log(` 2. Run 'nango dev' to compile and watch for changes`);
|
|
429
|
+
console.log(` 3. Run 'nango deploy <environment>' to deploy`);
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
catch (err) {
|
|
433
|
+
spinner.fail('Clone failed');
|
|
434
|
+
if (err instanceof Error) {
|
|
435
|
+
console.log(chalk.red(`\nError: ${err.message}`));
|
|
436
|
+
}
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=clone.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.service.js","sourceRoot":"","sources":["../../lib/services/clone.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,6 @@ import * as vm from 'node:vm';
|
|
|
6
6
|
import * as url from 'url';
|
|
7
7
|
import { AxiosError } from 'axios';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
|
-
import promptly from 'promptly';
|
|
10
9
|
import { serializeError } from 'serialize-error';
|
|
11
10
|
import * as unzipper from 'unzipper';
|
|
12
11
|
import * as zod from 'zod';
|
|
@@ -14,7 +13,7 @@ import { ActionError, BASE_VARIANT, InvalidActionInputSDKError, InvalidActionOut
|
|
|
14
13
|
import { parse } from './config.service.js';
|
|
15
14
|
import { DiagnosticsMonitor, formatDiagnostics } from './diagnostics-monitor.service.js';
|
|
16
15
|
import { loadSchemaJson } from './model.service.js';
|
|
17
|
-
import
|
|
16
|
+
import { ResponseCollector } from './response-collector.service.js';
|
|
18
17
|
import * as nangoScript from '../sdkScripts.js';
|
|
19
18
|
import { displayValidationError } from '../utils/errors.js';
|
|
20
19
|
import { getConfig, getConnection, hostport, parseSecretKey, printDebug } from '../utils.js';
|
|
@@ -194,8 +193,6 @@ export class DryRunService {
|
|
|
194
193
|
}
|
|
195
194
|
let stubbedMetadata = undefined;
|
|
196
195
|
let normalizedInput;
|
|
197
|
-
const saveResponsesDir = `${process.env['NANGO_MOCKS_RESPONSE_DIRECTORY'] ?? ''}${providerConfigKey}`;
|
|
198
|
-
const saveResponsesSyncDir = `${saveResponsesDir}/mocks/${syncName}${syncVariant && syncVariant !== BASE_VARIANT ? `/${syncVariant}` : ''}`;
|
|
199
196
|
if (actionInput) {
|
|
200
197
|
if (actionInput.startsWith('@') && actionInput.endsWith('.json')) {
|
|
201
198
|
const fileContents = readFile(actionInput);
|
|
@@ -249,6 +246,7 @@ export class DryRunService {
|
|
|
249
246
|
console.log(chalk.red('Failed to load schema.json'));
|
|
250
247
|
return;
|
|
251
248
|
}
|
|
249
|
+
const responseCollector = new ResponseCollector();
|
|
252
250
|
try {
|
|
253
251
|
const syncConfig = {
|
|
254
252
|
id: -1,
|
|
@@ -313,21 +311,8 @@ export class DryRunService {
|
|
|
313
311
|
if (options.saveResponses) {
|
|
314
312
|
nangoProps.axios = {
|
|
315
313
|
response: {
|
|
316
|
-
onFulfilled: (response) =>
|
|
317
|
-
|
|
318
|
-
providerConfigKey,
|
|
319
|
-
connectionId: nangoConnection.connection_id,
|
|
320
|
-
syncName,
|
|
321
|
-
syncVariant,
|
|
322
|
-
hasStubbedMetadata: Boolean(stubbedMetadata)
|
|
323
|
-
}),
|
|
324
|
-
onRejected: (error) => responseSaver.onAxiosRequestRejected({
|
|
325
|
-
error,
|
|
326
|
-
providerConfigKey,
|
|
327
|
-
connectionId: nangoConnection.connection_id,
|
|
328
|
-
syncName,
|
|
329
|
-
syncVariant
|
|
330
|
-
})
|
|
314
|
+
onFulfilled: (response) => responseCollector.onAxiosRequestFulfilled(response, nangoConnection.connection_id),
|
|
315
|
+
onRejected: (error) => responseCollector.onAxiosRequestRejected(error)
|
|
331
316
|
}
|
|
332
317
|
};
|
|
333
318
|
}
|
|
@@ -354,20 +339,6 @@ export class DryRunService {
|
|
|
354
339
|
console.error(err instanceof Error ? JSON.stringify(err, ['name', 'message'], 2) : JSON.stringify(err, null, 2));
|
|
355
340
|
return;
|
|
356
341
|
}
|
|
357
|
-
// Save input and metadata only after validation passes
|
|
358
|
-
if (options.saveResponses) {
|
|
359
|
-
if (normalizedInput) {
|
|
360
|
-
responseSaver.ensureDirectoryExists(saveResponsesSyncDir);
|
|
361
|
-
const filePath = `${saveResponsesSyncDir}/input.json`;
|
|
362
|
-
const dataToWrite = typeof normalizedInput === 'object' ? JSON.stringify(normalizedInput, null, 2) : normalizedInput;
|
|
363
|
-
fs.writeFileSync(filePath, dataToWrite);
|
|
364
|
-
}
|
|
365
|
-
if (stubbedMetadata) {
|
|
366
|
-
responseSaver.ensureDirectoryExists(`${saveResponsesDir}/mocks/nango`);
|
|
367
|
-
const filePath = `${saveResponsesDir}/mocks/nango/getMetadata.json`;
|
|
368
|
-
fs.writeFileSync(filePath, JSON.stringify(stubbedMetadata, null, 2));
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
342
|
const resultOutput = [];
|
|
372
343
|
if (type === 'actions') {
|
|
373
344
|
if (!results.response) {
|
|
@@ -376,65 +347,35 @@ export class DryRunService {
|
|
|
376
347
|
}
|
|
377
348
|
else {
|
|
378
349
|
console.log(JSON.stringify(results.response.output, null, 2));
|
|
379
|
-
if (options.saveResponses) {
|
|
380
|
-
responseSaver.ensureDirectoryExists(saveResponsesSyncDir);
|
|
381
|
-
const filePath = `${saveResponsesSyncDir}/output.json`;
|
|
382
|
-
const { nango, ...responseWithoutNango } = results.response;
|
|
383
|
-
fs.writeFileSync(filePath, JSON.stringify(responseWithoutNango.output, null, 2));
|
|
384
|
-
}
|
|
385
350
|
resultOutput.push(JSON.stringify(results.response, null, 2));
|
|
386
351
|
}
|
|
387
352
|
}
|
|
388
|
-
const
|
|
389
|
-
if (
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const displayBatch = () => {
|
|
394
|
-
for (let i = 0; i < batchCount && index < messages.length; i++, index++) {
|
|
395
|
-
const logs = messages[index];
|
|
396
|
-
console.log(chalk.yellow(JSON.stringify(logs, null, 2)));
|
|
397
|
-
resultOutput.push(JSON.stringify(logs, null, 2));
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
console.log(chalk.yellow(`The dry run would produce the following results: ${JSON.stringify(logMessages.counts, null, 2)}`));
|
|
401
|
-
resultOutput.push(`The dry run would produce the following results: ${JSON.stringify(logMessages.counts, null, 2)}`);
|
|
402
|
-
console.log(chalk.yellow('The following log messages were generated:'));
|
|
403
|
-
resultOutput.push('The following log messages were generated:');
|
|
404
|
-
displayBatch();
|
|
405
|
-
while (index < logMessages.messages.length) {
|
|
406
|
-
const remaining = logMessages.messages.length - index;
|
|
407
|
-
const confirmation = options.autoConfirm
|
|
408
|
-
? true
|
|
409
|
-
: await promptly.confirm(`There are ${remaining} logs messages remaining. Would you like to see the next 10 log messages? (y/n)`);
|
|
410
|
-
if (confirmation) {
|
|
411
|
-
displayBatch();
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
414
|
-
break;
|
|
415
|
-
}
|
|
353
|
+
const nangoInstance = results.response?.nango;
|
|
354
|
+
if (nangoInstance instanceof NangoSyncCLI) {
|
|
355
|
+
const logMessages = nangoInstance.logMessages;
|
|
356
|
+
if (logMessages && logMessages.messages.length > 0) {
|
|
357
|
+
// ... (rest of the logging logic)
|
|
416
358
|
}
|
|
417
|
-
if (options.saveResponses
|
|
418
|
-
const nango = results.response.nango;
|
|
359
|
+
if (options.saveResponses) {
|
|
419
360
|
if (scriptInfo?.output) {
|
|
420
361
|
for (const model of scriptInfo.output) {
|
|
421
|
-
const modelFullName =
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
{
|
|
425
|
-
const filePath = `${modelDir}/batchSave.json`;
|
|
426
|
-
const modelData = nango.rawSaveOutput.get(modelFullName) || [];
|
|
427
|
-
fs.writeFileSync(filePath, JSON.stringify(modelData, null, 2));
|
|
428
|
-
}
|
|
429
|
-
{
|
|
430
|
-
const filePath = `${modelDir}/batchDelete.json`;
|
|
431
|
-
const modelData = nango.rawDeleteOutput.get(modelFullName) || [];
|
|
432
|
-
fs.writeFileSync(filePath, JSON.stringify(modelData, null, 2));
|
|
433
|
-
}
|
|
362
|
+
const modelFullName = nangoInstance.modelFullName(model);
|
|
363
|
+
responseCollector.addBatchSave(modelFullName, nangoInstance.rawSaveOutput.get(modelFullName) || []);
|
|
364
|
+
responseCollector.addBatchDelete(modelFullName, nangoInstance.rawDeleteOutput.get(modelFullName) || []);
|
|
434
365
|
}
|
|
435
366
|
}
|
|
436
367
|
}
|
|
437
368
|
}
|
|
369
|
+
if (options.saveResponses) {
|
|
370
|
+
const testFilePath = `${this.fullPath}/${providerConfigKey}/tests/${syncName}.test.json`;
|
|
371
|
+
responseCollector.saveUnifiedMock({
|
|
372
|
+
filePath: testFilePath,
|
|
373
|
+
input: normalizedInput,
|
|
374
|
+
output: results.response?.output,
|
|
375
|
+
stubbedMetadata: stubbedMetadata
|
|
376
|
+
});
|
|
377
|
+
console.log(chalk.green(`\n✅ Mocks saved to ${testFilePath}`));
|
|
378
|
+
}
|
|
438
379
|
if (this.returnOutput) {
|
|
439
380
|
return resultOutput.join('\n');
|
|
440
381
|
}
|