Edge.js

in-process interop with Node.js + .NET

(also, sry - not sry, memes aren't done)

Reasons not to use Node.js

Single threaded, event driven

Working with legacy tech?

You have existing components / knowledge of .NET

There's a superior implementation elsewhere 

Reasons not to use C# / .NET

It's .NET

Not isomorphic (in the context of web dev)

Smaller package ecosystem / OSS community

You may have / need components that are already in Node

Less familiarity

\rightleftharpoons
\rightleftharpoons

Node.exe

MyService.exe

Node.exe

Edge.js

const edge = require('edge');

const helloWorld = edge.func(`
    async (input) => { 
        return ".NET Welcomes " + input.ToString(); 
    }
`);

helloWorld('JavaScript', (error, result) => {
    if (error) throw error;
    console.log(result);
});
const add7 = edge.func('async (input) => { return (int)input + 7; }');
var add7 = edge.func(function() {/*
    async (input) => {
        return (int)input + 7;
    }
*/});
const add7 = edge.func(`
    async (input) => {
        return (int)input + 7;
    }
`);
const add7 = edge.func(`
    using System.Threading.Tasks;

    public class Startup
    {
        public async Task<object> Invoke(object input)
        {
            int v = (int)input;
            return Helper.AddSeven(v);
        }
    }

    static class Helper
    {
        public static int AddSeven(int v) 
        {
            return v + 7;
        }
    }
`);
const path = require('path');

const add7 = edge.func(path.join(__dirname, 'add7.cs'));
const clrMethod = edge.func({
    assemblyFile: 'My.Edge.Samples.dll',
    typeName: 'Samples.FooBar.MyType',
    methodName: 'MyMethod' // This must be Func<object,Task<object>>,
    references: [ 'System.Data.dll' ]
});
const clrMethod = edge.func('My.Edge.Samples.dll');
myFunction('Some input', (error, result) => {
    //...
});
let result = myFunction('Some input', true);

Async

Synchronous

var dotNetFunction = edge.func('Edge.Sample.dll');

var payload = {
    anInteger: 1,
    aNumber: 3.1415,
    aString: 'foo',
    aBoolean: true,
    aBuffer: new Buffer(10),
    anArray: [ 1, 'foo' ],
    anObject: { a: 'foo', b: 12 }
};

dotNetFunction(payload, function (error, result) { });
using System.Threading.Tasks;

public class Startup
{
    public async Task<object> Invoke(dynamic input)
    {
        int anInteger = (int)input.anInteger;
        double aNumber = (double)input.aNumber;
        string aString = (string)input.aString;
        bool aBoolean = (bool)input.aBoolean;
        byte[] aBuffer = (byte[])input.aBuffer;
        object[] anArray = (object[])input.anArray;
        dynamic anObject = (dynamic)input.anObject;

        return null;
    }
}
const heavyLifting = require('edge').func(`

  async (input) => {

    // we are on V8 thread here
    return await Task.Run<object>(async () => {

      // we are on CLR thread pool thread here
      await Task.Delay(5000); // simulate CPU bound  

      return "Done!";

    });
  }

`);

Multi-threading

const authenticate = require('edge').func(`
  class Startup {
    [DllImport("advapi32.dll")] static extern bool LogonUser(...);

    public async Task<object> Invoke(dynamic i) {
      IntPtr t;
      return Startup.LogonUser(i.user, null, i.password, 3, 0, out t));
    }
  }
`);

authenticate({
  user: 'satya@microsoft.com',
  password: 'clippy4eva'
}, (error, result) => { ... });

Windows Auth

const convertImageToJpg = require('edge').func(`
  #r "System.Drawing.dll"
  using System.Drawing;

  async (src) => {
    await Task.Run(async () => {
      Image.FromFile(src).Save((string)src + ".jpg", ImageFormat.Jpeg);
    });
    return null;
  }
`);

convertImageToJpg('.\\edge.png', (error) => { ... });

Image Conversion

Symmetric

Other languages that compile to CLR

F#

Python

VB (lol)

Powershell

Lisp

Edge-ts

Typed bindings

Promises

Simple API for building from similar contexts

Search "edge-ts" on npm

simple.industries

acaprojects.com

edge.js

By Kim Burgess