Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Require nodejs "child_process" with TypeScript, SystemJS and Electron

I'm working on a simple nodejs electron (formerly known as atom shell) project. I'm writing it using angular 2, using the project the same project setup as they recommend in the documentation for typescript:

tsc:

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
  "node_modules",
  "typings/main",
  "typings/main.d.ts"
  ]
}

I need to run a command, I found out that I can do it with node "child_process". I couldn't find anyway for me to "import" or "require" it while having its type used from the node.d.ts file. I have found the "child_process" interface in the node.d.ts file which suits my need, this is how it looking in the node.d.ts file:

    declare module "child_process" {
    import * as events from "events";
    import * as stream from "stream";

    export interface ChildProcess extends events.EventEmitter {
        stdin:  stream.Writable;
        stdout: stream.Readable;
        stderr: stream.Readable;
        pid: number;
        kill(signal?: string): void;
        send(message: any, sendHandle?: any): void;
        disconnect(): void;
        unref(): void;
    }

    export function spawn(command: string, args?: string[], options?: {
        cwd?: string;
        stdio?: any;
        custom?: any;
        env?: any;
        detached?: boolean;
    }): ChildProcess;
    export function exec(command: string, options: {
        cwd?: string;
        stdio?: any;
        customFds?: any;
        env?: any;
        encoding?: string;
        timeout?: number;
        maxBuffer?: number;
        killSignal?: string;
    }, callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess;
    export function exec(command: string, callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess;
    export function execFile(file: string,
        callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess;
    export function execFile(file: string, args?: string[],
        callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess;
    export function execFile(file: string, args?: string[], options?: {
        cwd?: string;
        stdio?: any;
        customFds?: any;
        env?: any;
        encoding?: string;
        timeout?: number;
        maxBuffer?: number;
        killSignal?: string;
    }, callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess;
    export function fork(modulePath: string, args?: string[], options?: {
        cwd?: string;
        env?: any;
        execPath?: string;
        execArgv?: string[];
        silent?: boolean;
        uid?: number;
        gid?: number;
    }): ChildProcess;
    export function spawnSync(command: string, args?: string[], options?: {
        cwd?: string;
        input?: string | Buffer;
        stdio?: any;
        env?: any;
        uid?: number;
        gid?: number;
        timeout?: number;
        maxBuffer?: number;
        killSignal?: string;
        encoding?: string;
    }): {
        pid: number;
        output: string[];
        stdout: string | Buffer;
        stderr: string | Buffer;
        status: number;
        signal: string;
        error: Error;
    };
    export function execSync(command: string, options?: {
        cwd?: string;
        input?: string|Buffer;
        stdio?: any;
        env?: any;
        uid?: number;
        gid?: number;
        timeout?: number;
        maxBuffer?: number;
        killSignal?: string;
        encoding?: string;
    }): string | Buffer;
    export function execFileSync(command: string, args?: string[], options?: {
        cwd?: string;
        input?: string|Buffer;
        stdio?: any;
        env?: any;
        uid?: number;
        gid?: number;
        timeout?: number;
        maxBuffer?: number;
        killSignal?: string;
        encoding?: string;
    }): string | Buffer;
}

but I can only (as I know of) get this type only by using import:

import * as child_process from 'child_process'; 

Only problem is that when I do this, my app cant load and I get the following error in the console:

GET file:///C:/angular2Samples/NGW-electron-VS%20-%20TEMP/child_process net::ERR_FILE_NOT_FOUND

For now, im getting my way around by using:

var child_process = require('child_process');

but I couldn't find anyway to add the type information to this var:

var child_process : I_CANT_PUT_ANY_CHILD_PROCESS_TYPE_HERE = require('child_process');

Any ideas on how I can get the child_process (or any other declared node modules that arent public interface that I can state after ":" operator) with type information?

Thanks alot in advance for any help and explanations :)

UPDATE ------------------------------------------------------------------

As tenbits suggested I have added the reference as follows to the top of the file: ///

and used the import statment you said, but didnt chage my module loader. it still didnt work with the same error as expected. Im not feeling very comfortable about changing the module system, as my project uses angular 2 and their docs and some of their guides said that new projects that has no former prefernce to this matter (I am very new to the module loaders scene and im not fully understanding how it works yet). When I tried to change it I got some errors regarding angular 2 stuffs which I dont have enough time to get into at the moment. Shouldn't there be a way to this without changing the module loader? by glancing at the systemjs site it says at the start that it supports commonjs modules: Systemjs doc

I would really appriciate a solution that doesn't change the module system, or maybe a more depth explanition about what's going on and which approaches to these kind of module loading problems exists out there

like image 785
Ziv Glazer Avatar asked Apr 11 '16 11:04

Ziv Glazer


2 Answers

Ok, after some research #L138 I have found the solution

You can use import as before

import * as child from 'child_process';

var foo: child.ChildProcess = child.exec('foo.sh');
console.log(typeof foo.on);

But you should configure SystemJS to map the module to NodeJS.

System.config({
  map: {
    'child_process': '@node/child_process'
  }
});

That's it!

like image 101
tenbits Avatar answered Nov 18 '22 20:11

tenbits


If the error message is 'Cannot find module 'child_process' or its corresponding type declarations' the answer is 'npm install @types/watch'

like image 7
Gustavo Hernán Crucianelli Avatar answered Nov 18 '22 20:11

Gustavo Hernán Crucianelli