import { BehaviorSubject , merge , of } from 'rxjs' ; import { map , tap , throttleTime } from 'rxjs/operators' ; import * as vscode from 'vscode' ; import parseDepsFromFile from '../runtimes/parseDepsFromFile' ; import { vscToObservable } from '../util' ; const path = require ( 'path' ) ; const fs = require ( 'fs' ) ; const glob = require ( 'glob' ) ; /**
 * Given a folder path, return a list of substrate nodes contained inside.
 */ const findNodesInFolder = ( roots ) : string [ ] => { return glob . sync ( path . join ( roots , '**/Cargo.toml' ) , { ignore : '**/node_modules/**' } ) . filter ( ( b ) => { return fs . readFileSync ( b ) . toString ( ) . includes ( '[[bin]]' ) ; } ) . map ( ( nodeRs ) => path . dirname ( nodeRs ) ) ; } ; const findNodesInWorkspace = ( ) => { return vscode . workspace . workspaceFolders ?. map ( ( x ) => x . uri . fsPath ) . map ( root => { return findNodesInFolder ( root ) ; } ) . flat ( ) || [ ] ; } ; export type Node = { nodePath : string ; runtimePath ? : string ; deps ? : any [ ] ; } ; export default class Nodes { nodes$ : BehaviorSubject < Node [ ] > ; constructor ( ) { const watcher = vscode . workspace . createFileSystemWatcher ( '**/Cargo.toml' ) ; const nodesPath$ = merge ( of ( null ) , merge ( vscToObservable ( watcher . onDidChange . bind ( watcher ) ) , vscToObservable ( watcher . onDidCreate . bind ( watcher ) ) , vscToObservable ( watcher . onDidDelete . bind ( watcher ) ) ) . pipe ( throttleTime ( 100 ) ) ) . pipe ( map ( ( ) => findNodesInWorkspace ( ) ) ) ; this . nodes$ = new BehaviorSubject ( < Node [ ] > [ ] ) ; nodesPath$ . pipe ( map ( nodePaths => { return nodePaths . map ( nodePath => { try { const cargoToml = fs . readFileSync ( path . join ( nodePath , 'Cargo.toml' ) ) . toString ( ) ; const matches = cargoToml . match ( /^(?:[^#].*)?path ?= ?"([a-zA-Z./-]*runtime[a-zA-Z./-]*)"|^(?:[^#].*)?path ?= ?'([a-zA-Z./-]*runtime[a-zA-Z./-]*)'/m ) ; if ( matches === null ) return { nodePath } as Node ; else { const runtimePath = path . join ( nodePath , matches [ 1 ] || matches [ 2 ] ) ; return { nodePath , runtimePath : runtimePath , deps : parseDepsFromFile ( path . join ( runtimePath , 'Cargo.toml' ) ) } as Node ; } } catch ( e ) { console . error ( 'error' , e ) ; return { nodePath : '' } ; } } ) ; } ) ) . subscribe ( this . nodes$ ) ; this . nodes$ . subscribe ( x => { } ) ; } }