MCPcopy Create free account
hub / github.com/dyoshikawa/rulesync / fetchFiles

Function fetchFiles

src/lib/fetch.ts:272–410  ·  view source on GitHub ↗
(params: FetchParams)

Source from the content-addressed store, hash-verified

270 * converted to rulesync format, and written to the output directory.
271 */
272export async function fetchFiles(params: FetchParams): Promise<FetchSummary> {
273 const { source, options = {}, outputRoot = process.cwd(), logger } = params;
274
275 // Parse source
276 const parsed = parseSource(source);
277
278 // Check if provider is supported
279 if (parsed.provider === "gitlab") {
280 throw new Error(
281 "GitLab is not yet supported. Currently only GitHub repositories are supported.",
282 );
283 }
284
285 // Resolve options
286 const resolvedRef = options.ref ?? parsed.ref;
287 // Normalize backslashes to forward slashes for GitHub API compatibility.
288 const resolvedPath = toPosixPath(options.path ?? parsed.path ?? ".");
289 const outputDir = options.output ?? RULESYNC_RELATIVE_DIR_PATH;
290 const conflictStrategy: ConflictStrategy = options.conflict ?? "overwrite";
291 const enabledFeatures = resolveFeatures(options.features);
292 const target: FetchTarget = options.target ?? "rulesync";
293
294 // Validate output directory to prevent path traversal attacks
295 checkPathTraversal({
296 relativePath: outputDir,
297 intendedRootDir: outputRoot,
298 });
299
300 // Initialize GitHub client
301 const token = GitHubClient.resolveToken(options.token);
302 const client = new GitHubClient({ token });
303
304 // Validate repository
305 logger.debug(`Validating repository: ${parsed.owner}/${parsed.repo}`);
306 const isValid = await client.validateRepository(parsed.owner, parsed.repo);
307 if (!isValid) {
308 throw new GitHubClientError(
309 `Repository not found: ${parsed.owner}/${parsed.repo}. Check the repository name and your access permissions.`,
310 404,
311 );
312 }
313
314 // Resolve ref to use
315 const ref = resolvedRef ?? (await client.getDefaultBranch(parsed.owner, parsed.repo));
316 logger.debug(`Using ref: ${ref}`);
317
318 // If target is a tool format, use conversion flow
319 if (isToolTarget(target)) {
320 return fetchAndConvertToolFiles({
321 client,
322 parsed,
323 ref,
324 resolvedPath,
325 enabledFeatures,
326 target,
327 outputDir,
328 outputRoot,
329 conflictStrategy,

Callers 2

fetch.test.tsFile · 0.85
fetchCommandFunction · 0.85

Calls 15

validateRepositoryMethod · 0.95
getDefaultBranchMethod · 0.95
getFileContentMethod · 0.95
parseSourceFunction · 0.85
toPosixPathFunction · 0.85
resolveFeaturesFunction · 0.85
checkPathTraversalFunction · 0.85
isToolTargetFunction · 0.85
fetchAndConvertToolFilesFunction · 0.85
collectFeatureFilesFunction · 0.85
validateFileSizeFunction · 0.85
fileExistsFunction · 0.85

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…