 e89f2f4b7b
			
		
	
	e89f2f4b7b
	
	
	
		
			
			Created 10 detailed GitHub issues covering: - Project activation and management UI (#1-2) - Worker node coordination and visualization (#3-4) - Automated GitHub repository scanning (#5) - Intelligent model-to-issue matching (#6) - Multi-model task execution system (#7) - N8N workflow integration (#8) - Hive-Bzzz P2P bridge (#9) - Peer assistance protocol (#10) Each issue includes detailed specifications, acceptance criteria, technical implementation notes, and dependency mapping. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			209 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { shallowIgnoreVisitors } from '../utils/traverse.js';
 | |
| import resolve from 'resolve';
 | |
| import { dirname, extname } from 'path';
 | |
| import fs from 'fs';
 | |
| import { visitors } from '@babel/traverse';
 | |
| import { resolveObjectPatternPropertyToValue } from '../utils/index.js';
 | |
| // These extensions are sorted by priority
 | |
| // resolve() will check for files in the order these extensions are sorted
 | |
| const RESOLVE_EXTENSIONS = [
 | |
|     '.js',
 | |
|     '.ts',
 | |
|     '.tsx',
 | |
|     '.mjs',
 | |
|     '.cjs',
 | |
|     '.mts',
 | |
|     '.cts',
 | |
|     '.jsx',
 | |
| ];
 | |
| function defaultLookupModule(filename, basedir) {
 | |
|     const resolveOptions = {
 | |
|         basedir,
 | |
|         extensions: RESOLVE_EXTENSIONS,
 | |
|         // we do not need to check core modules as we cannot import them anyway
 | |
|         includeCoreModules: false,
 | |
|     };
 | |
|     try {
 | |
|         return resolve.sync(filename, resolveOptions);
 | |
|     }
 | |
|     catch (error) {
 | |
|         const ext = extname(filename);
 | |
|         let newFilename;
 | |
|         // if we try to import a JavaScript file it might be that we are actually pointing to
 | |
|         // a TypeScript file. This can happen in ES modules as TypeScript requires to import other
 | |
|         // TypeScript files with .js extensions
 | |
|         // https://www.typescriptlang.org/docs/handbook/esm-node.html#type-in-packagejson-and-new-extensions
 | |
|         switch (ext) {
 | |
|             case '.js':
 | |
|             case '.mjs':
 | |
|             case '.cjs':
 | |
|                 newFilename = `${filename.slice(0, -2)}ts`;
 | |
|                 break;
 | |
|             case '.jsx':
 | |
|                 newFilename = `${filename.slice(0, -3)}tsx`;
 | |
|                 break;
 | |
|             default:
 | |
|                 throw error;
 | |
|         }
 | |
|         return resolve.sync(newFilename, {
 | |
|             ...resolveOptions,
 | |
|             // we already know that there is an extension at this point, so no need to check other extensions
 | |
|             extensions: [],
 | |
|         });
 | |
|     }
 | |
| }
 | |
| // Factory for the resolveImports importer
 | |
| // If this resolver is used in an environment where the source files change (e.g. watch)
 | |
| // then the cache needs to be cleared on file changes.
 | |
| export default function makeFsImporter(lookupModule = defaultLookupModule, { parseCache, resolveCache } = {
 | |
|     parseCache: new Map(),
 | |
|     resolveCache: new Map(),
 | |
| }) {
 | |
|     function resolveImportedValue(path, name, file, seen = new Set()) {
 | |
|         // Bail if no filename was provided for the current source file.
 | |
|         // Also never traverse into react itself.
 | |
|         const source = path.node.source?.value;
 | |
|         const { filename } = file.opts;
 | |
|         if (!source || !filename || source === 'react') {
 | |
|             return null;
 | |
|         }
 | |
|         // Resolve the imported module using the Node resolver
 | |
|         const basedir = dirname(filename);
 | |
|         const resolveCacheKey = `${basedir}|${source}`;
 | |
|         let resolvedSource = resolveCache.get(resolveCacheKey);
 | |
|         // We haven't found it before, so no need to look again
 | |
|         if (resolvedSource === null) {
 | |
|             return null;
 | |
|         }
 | |
|         // First time we try to resolve this file
 | |
|         if (resolvedSource === undefined) {
 | |
|             try {
 | |
|                 resolvedSource = lookupModule(source, basedir);
 | |
|             }
 | |
|             catch (error) {
 | |
|                 const { code } = error;
 | |
|                 if (code === 'MODULE_NOT_FOUND' || code === 'INVALID_PACKAGE_MAIN') {
 | |
|                     resolveCache.set(resolveCacheKey, null);
 | |
|                     return null;
 | |
|                 }
 | |
|                 throw error;
 | |
|             }
 | |
|             resolveCache.set(resolveCacheKey, resolvedSource);
 | |
|         }
 | |
|         // Prevent recursive imports
 | |
|         if (seen.has(resolvedSource)) {
 | |
|             return null;
 | |
|         }
 | |
|         seen.add(resolvedSource);
 | |
|         let nextFile = parseCache.get(resolvedSource);
 | |
|         if (!nextFile) {
 | |
|             // Read and parse the code
 | |
|             const src = fs.readFileSync(resolvedSource, 'utf8');
 | |
|             nextFile = file.parse(src, resolvedSource);
 | |
|             parseCache.set(resolvedSource, nextFile);
 | |
|         }
 | |
|         return findExportedValue(nextFile, name, seen);
 | |
|     }
 | |
|     const explodedVisitors = visitors.explode({
 | |
|         ...shallowIgnoreVisitors,
 | |
|         ExportNamedDeclaration: {
 | |
|             enter: function (path, state) {
 | |
|                 const { file, name, seen } = state;
 | |
|                 const declaration = path.get('declaration');
 | |
|                 // export const/var ...
 | |
|                 if (declaration.hasNode() && declaration.isVariableDeclaration()) {
 | |
|                     for (const declPath of declaration.get('declarations')) {
 | |
|                         const id = declPath.get('id');
 | |
|                         const init = declPath.get('init');
 | |
|                         if (id.isIdentifier({ name }) && init.hasNode()) {
 | |
|                             // export const/var a = <init>
 | |
|                             state.resultPath = init;
 | |
|                             break;
 | |
|                         }
 | |
|                         else if (id.isObjectPattern()) {
 | |
|                             // export const/var { a } = <init>
 | |
|                             state.resultPath = id.get('properties').find((prop) => {
 | |
|                                 if (prop.isObjectProperty()) {
 | |
|                                     const value = prop.get('value');
 | |
|                                     return value.isIdentifier({ name });
 | |
|                                 }
 | |
|                                 // We don't handle RestElement here yet as complicated
 | |
|                                 return false;
 | |
|                             });
 | |
|                             if (state.resultPath) {
 | |
|                                 state.resultPath = resolveObjectPatternPropertyToValue(state.resultPath);
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                         // ArrayPattern not handled yet
 | |
|                     }
 | |
|                 }
 | |
|                 else if (declaration.hasNode() &&
 | |
|                     declaration.has('id') &&
 | |
|                     declaration.get('id').isIdentifier({ name })) {
 | |
|                     // export function/class/type/interface/enum ...
 | |
|                     state.resultPath = declaration;
 | |
|                 }
 | |
|                 else if (path.has('specifiers')) {
 | |
|                     // export { ... } or export x from ... or export * as x from ...
 | |
|                     for (const specifierPath of path.get('specifiers')) {
 | |
|                         if (specifierPath.isExportNamespaceSpecifier()) {
 | |
|                             continue;
 | |
|                         }
 | |
|                         const exported = specifierPath.get('exported');
 | |
|                         if (exported.isIdentifier({ name })) {
 | |
|                             // export ... from ''
 | |
|                             if (path.has('source')) {
 | |
|                                 const local = specifierPath.isExportSpecifier()
 | |
|                                     ? specifierPath.node.local.name
 | |
|                                     : 'default';
 | |
|                                 state.resultPath = resolveImportedValue(path, local, file, seen);
 | |
|                                 if (state.resultPath) {
 | |
|                                     break;
 | |
|                                 }
 | |
|                             }
 | |
|                             else {
 | |
|                                 state.resultPath = specifierPath.get('local');
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 return state.resultPath ? path.stop() : path.skip();
 | |
|             },
 | |
|         },
 | |
|         ExportDefaultDeclaration: {
 | |
|             enter: function (path, state) {
 | |
|                 const { name } = state;
 | |
|                 if (name === 'default') {
 | |
|                     state.resultPath = path.get('declaration');
 | |
|                     return path.stop();
 | |
|                 }
 | |
|                 path.skip();
 | |
|             },
 | |
|         },
 | |
|         ExportAllDeclaration: {
 | |
|             enter: function (path, state) {
 | |
|                 const { name, file, seen } = state;
 | |
|                 const resolvedPath = resolveImportedValue(path, name, file, seen);
 | |
|                 if (resolvedPath) {
 | |
|                     state.resultPath = resolvedPath;
 | |
|                     return path.stop();
 | |
|                 }
 | |
|                 path.skip();
 | |
|             },
 | |
|         },
 | |
|     });
 | |
|     // Traverses the program looking for an export that matches the requested name
 | |
|     function findExportedValue(file, name, seen) {
 | |
|         const state = {
 | |
|             file,
 | |
|             name,
 | |
|             seen,
 | |
|         };
 | |
|         file.traverse(explodedVisitors, state);
 | |
|         return state.resultPath || null;
 | |
|     }
 | |
|     return resolveImportedValue;
 | |
| }
 |