{"id":13399665,"url":"https://github.com/tjanczuk/edge","last_synced_at":"2025-05-13T17:03:02.786Z","repository":{"id":7041108,"uuid":"8318401","full_name":"tjanczuk/edge","owner":"tjanczuk","description":"Run .NET and Node.js code in-process on Windows, MacOS, and Linux","archived":false,"fork":false,"pushed_at":"2024-11-14T13:15:40.000Z","size":25368,"stargazers_count":5438,"open_issues_count":15,"forks_count":638,"subscribers_count":243,"default_branch":"master","last_synced_at":"2025-05-05T22:52:13.725Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://tjanczuk.github.io/edge","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tjanczuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-02-20T17:37:24.000Z","updated_at":"2025-05-05T02:12:16.000Z","dependencies_parsed_at":"2024-06-18T12:23:17.402Z","dependency_job_id":"eb012676-bda5-4e92-8133-10ca3949820f","html_url":"https://github.com/tjanczuk/edge","commit_stats":{"total_commits":618,"total_committers":40,"mean_commits":15.45,"dds":0.4449838187702265,"last_synced_commit":"2d6b045e7862cd4160ac31dcdedda4ac627bc789"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjanczuk%2Fedge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjanczuk%2Fedge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjanczuk%2Fedge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjanczuk%2Fedge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tjanczuk","download_url":"https://codeload.github.com/tjanczuk/edge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252590529,"owners_count":21772935,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:00:41.142Z","updated_at":"2025-05-05T22:52:15.917Z","avatar_url":"https://github.com/tjanczuk.png","language":"C++","funding_links":[],"categories":["C++","包","others","Packages","JavaScript Engines","JavaScript引擎"],"sub_categories":["跨平台的集成","Cross-platform integration","GUI - other"],"readme":"Edge.js: .NET and Node.js in-process [![Build Status](https://travis-ci.org/tjanczuk/edge.svg)](https://travis-ci.org/tjanczuk/edge)\n====\n\n## Up to date project can be found here https://github.com/agracio/edge-js\n### NPM package is published as `edge-js`\n### Nuget package is published as `EdgeJs`\n### Any Issues or PRs should be created in https://github.com/agracio/edge-js\n-------\n\n**NEW** Edge.js is now on Slack at https://edgejs.slack.com. Join [here](https://tjanczuk.sandbox.auth0-extend.com/edgejs-slack-invite). \n \nAn edge connects two nodes. This edge connects Node.js and .NET. V8 and CLR/.NET Core/Mono - in process. On Windows, MacOS, and Linux. \n\n![image](https://cloud.githubusercontent.com/assets/822369/11969685/e9476f3a-a8d1-11e5-94d4-847bfc4ed960.png)\n\nYou can script C# from a Node.js process:\n\n**ES5**\n```javascript\nvar edge = require('edge');\n\nvar helloWorld = edge.func(function () {/*\n    async (input) =\u003e { \n        return \".NET Welcomes \" + input.ToString(); \n    }\n*/});\n\nhelloWorld('JavaScript', function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n**ES6**\n\nIn ES6 you can use [template strings](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/template_strings) to write multiline C# code.\n```javascript\nvar edge = require('edge');\n\nvar helloWorld = edge.func(`\n    async (input) =\u003e { \n        return \".NET Welcomes \" + input.ToString(); \n    }\n`);\n\nhelloWorld('JavaScript', function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\nYou can also script Node.js from C#:\n\n```c#\nusing System;\nusing System.Threading.Tasks;\nusing EdgeJs;\n\nclass Program\n{\n    public static async Task Start()\n    {\n        var func = Edge.Func(@\"\n            return function (data, callback) {\n                callback(null, 'Node.js welcomes ' + data);\n            }\n        \");\n\n        Console.WriteLine(await func(\".NET\"));\n    }\n\n    static void Main(string[] args)\n    {\n        Start().Wait();\n    }\n}\n```\n\n## What problems does Edge.js solve?\n\n\u003e Ah, whatever problem you have. If you have this problem, this solves it.\n\n*[--Scott Hanselman (@shanselman)](https://twitter.com/shanselman/status/461532471037677568)*\n\n## Before you dive in\n\nSee the [Edge.js overview](http://tjanczuk.github.com/edge).  \nRead the [Edge.js introduction on InfoQ](http://www.infoq.com/articles/the_edge_of_net_and_node).  \nListen to the [Edge.js podcast on Herdingcode](http://herdingcode.com/herding-code-166-tomasz-janczuk-on-edge-js/). \n\n![image](https://cloud.githubusercontent.com/assets/822369/2808101/87f73a5c-cd0f-11e3-9f7a-f53be86641be.png)\n\n## Contents\n\n[Introduction](#introduction)  \n[Scripting CLR from Node.js](#scripting-clr-from-nodejs)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[What you need](#what-you-need)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Windows](#windows)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Linux](#linux)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[OSX](#osx)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Docker](#docker)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: C# hello, world](#how-to-c-hello-world)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: integrate C# code into Node.js code](#how-to-integrate-c-code-into-nodejs-code)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: specify additional CLR assembly references in C# code](#how-to-specify-additional-clr-assembly-references-in-c-code)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: marshal data between C# and Node.js](#how-to-marshal-data-between-c-and-nodejs)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: call Node.js from C#](#how-to-call-nodejs-from-c)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: export C# function to Node.js](#how-to-export-c-function-to-nodejs)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: script Python in a Node.js application](#how-to-script-python-in-a-nodejs-application)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: script PowerShell in a Node.js application](#how-to-script-powershell-in-a-nodejs-application)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: script F# in a Node.js application](#how-to-script-f-in-a-nodejs-application)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: script Lisp in a Node.js application](#how-to-script-lisp-in-a-nodejs-application)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: script T-SQL in a Node.js application](#how-to-script-t-sql-in-a-nodejs-application)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: support for other CLR languages](#how-to-support-for-other-clr-languages)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: exceptions](#how-to-exceptions)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: app.config](#how-to-appconfig)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: debugging](#how-to-debugging)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Performance](#performance)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Building on Windows](#building-on-windows)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Building on OSX](#building-on-osx)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Building on Linux](#building-on-linux)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Running tests](#running-tests)  \n[Scripting Node.js from CLR](#scripting-nodejs-from-clr)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[What you need](#what-you-need-1)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: Node.js hello, world](#how-to-nodejs-hello-world)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: integrate Node.js into CLR code](#how-to-integrate-nodejs-code-into-clr-code)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: use Node.js built-in modules](#how-to-use-nodejs-built-in-modules)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: use external Node.js modules](#how-to-use-external-nodejs-modules)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: handle Node.js events in .NET](#how-to-handle-nodejs-events-in-net)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: expose Node.js state to .NET](#how-to-expose-nodejs-state-to-net)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: use Node.js in ASP.NET application](#how-to-use-nodejs-in-aspnet-web-applications)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[How to: debug Node.js code running in a CLR application](#how-to-debug-nodejs-code-running-in-a-clr-application)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Building Edge.js NuGet package](#building-edgejs-nuget-package)  \n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Running tests of scripting Node.js in C#](#running-tests-of-scripting-nodejs-in-c)  \n[Use cases and other resources](#use-cases-and-other-resources)  \n[Contribution and derived work](#contribution-and-derived-work)  \n\n## Introduction \n\nEdge.js allows you to run Node.js and .NET code in one process on Windows, MacOS, and Linux. \n\nYou can call .NET functions from Node.js and Node.js functions from .NET. Edge.js takes care of marshalling data between CLR and V8. Edge.js also reconciles threading models of single threaded V8 and multi-threaded CLR. Edge.js ensures correct lifetime of objects on V8 and CLR heaps. The CLR code can be pre-compiled or specified as C#, F#, Python, or PowerShell source: Edge.js can compile CLR scripts at runtime. Edge can be extended to support other CLR languages or DSLs.\n\n![Edge.js interop model](https://f.cloud.github.com/assets/822369/234085/b305625c-8768-11e2-8de0-e03ae98e7249.PNG)\n\nEdge.js provides an asynchronous, in-process mechanism for interoperability between Node.js and .NET. You can use this mechanism to:\n\n* script Node.js from a .NET application (console app, ASP.NET, etc.)\n* script C# from a Node.js application on Windows, MacOS, and Linux\n* access MS SQL from Node.js using ADO.NET [more...](http://blog.codeship.io/2014/04/22/leverage-sql-server-with-node-js-using-edge-js.html)  \n* use CLR multi-threading from Node.js for CPU intensive work [more...](http://tomasz.janczuk.org/2013/02/cpu-bound-workers-for-nodejs.html)  \n* write native extensions to Node.js in C# instead of C/C++  \n* integrate existing .NET components into Node.js applications\n\nRead more about the background and motivations of the project [here](http://tomasz.janczuk.org/2013/02/hosting-net-code-in-nodejs-applications.html). \n\n[Follow @tjanczuk](https://twitter.com/tjanczuk) for updates related to the module. \n\n## Scripting CLR from Node.js\n\nIf you are writing a Node.js application, this section explains how you include and run CLR code in your app. It works on Windows, MacOS, and Linux.\n\n### What you need\n\nEdge.js runs on Windows, Linux, and OSX and requires Node.js 8.x, 7.x, 6.x, as well as .NET Framework 4.5 (Windows), Mono 4.2.4 (OSX, Linux), or .NET Core 1.0.0 Preview 2 (Windows, OSX, Linux). \n\n**NOTE** there is a known issue with Mono after 4.2.4 that will be addressed in Mono 4.6.\n\n#### Windows\n\n* Node.js 8.x, 7.x, or 6.x \n* [.NET 4.5](http://www.microsoft.com/en-us/download/details.aspx?id=30653) and/or [.NET Core](https://www.microsoft.com/net/core)\n* to use Python, you also need [IronPython 2.7.3 or later](http://ironpython.codeplex.com/releases/view/81726)  \n* to use F#, read [Dave Thomas blog post](http://7sharpnine.com/blog/2013-05-05-i-node-something/)\n\nIf you have both desktop CLR and .NET Core installed, read [using .NET Core](#using-net-core) for how to configure Edge to use one or the other. \n\n![image](https://cloud.githubusercontent.com/assets/822369/2808066/3707f37c-cd0d-11e3-9b4e-7257ffc27c9c.png)\n\n#### Linux\n\n* Node.js 8.x, 7.x, or 6.x  \n* Mono 4.2.4 x64 and/or .NET Core\n* Follow [Linux setup instructions](#building-on-linux)\n\n![image](https://cloud.githubusercontent.com/assets/822369/2808077/03f92874-cd0e-11e3-88ea-79f67b8b1d49.png)\n\n#### OSX  \n\n* Node.js 8.x, 7.x, or 6.x  \n* Mono 4.2.4 x64 and/or .NET Core\n* Follow [OSX setup instructions](#building-on-osx)  \n\n![image](https://cloud.githubusercontent.com/assets/822369/2808046/8f4ce378-cd0b-11e3-95dc-ef0842c28821.png)\n\n#### Docker\n\nEdge.js is available as a Docker image on the [tjanczuk/edgejs repository on Docker Hub](https://registry.hub.docker.com/u/tjanczuk/edgejs/). The image is based on Debian Trusty, and contains Node.js 6.3.0 x64, Mono 4.2.4 x64, .NET Core 1.0.0 Preview 2 x64 (dotnet-dev-1.0.0-preview2-003121), and Edge.js 6.5.1:\n\nBy default Edge uses Mono to execute CLR code: \n\n```\n\u003e docker run -it tjanczuk/edgejs:6.5.1\n\u003e cd samples\n\u003e node 101_hello_lambda.js\n.NET welcomes Node.js\n```\n\nSpecify the `EDGE_USE_CORECLR=1` environment variable to use .NET Core instead: \n\n```\n\u003e docker run -it tjanczuk/edgejs:6.5.1\n\u003e cd samples\n\u003e EDGE_USE_CORECLR=1 node 101_hello_lambda.js\n.NET welcomes Node.js\n```\n\nAlternatively, you can also specify `EDGE_USE_CORECLR` when starting the container: \n\n```\n\u003e docker run -it -e EDGE_USE_CORECLR=1 tjanczuk/edgejs:6.5.1\n```\n\n### How to: C# hello, world\n\nFollow setup instructions [for your platform](#what-you-need). \n\nInstall edge:\n\n```\nnpm install edge\n```\n\nIn your server.js:\n\n```javascript\nvar edge = require('edge');\n\nvar helloWorld = edge.func(function () {/*\n    async (input) =\u003e { \n        return \".NET Welcomes \" + input.ToString(); \n    }\n*/});\n\nhelloWorld('JavaScript', function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\nRun and enjoy:\n\n```\n$\u003enode server.js\n.NET welcomes JavaScript\n```\n\nIf you want to use .NET Core as your runtime and are running in a dual runtime environment (i.e. Windows with .NET 4.5 installed as well or Linux with Mono installed), you will need to tell edge to use .NET Core by setting the `EDGE_USE_CORECLR` environment variable:\n\n```\n$\u003eEDGE_USE_CORECLR=1 node server.js\n.NET Welcomes JavaScript\n```\n\n### How to: integrate C# code into Node.js code\n\nEdge provides several ways to integrate C# code into a Node.js application. Regardless of the way you choose, the entry point into the .NET code is normalized to a `Func\u003cobject,Task\u003cobject\u003e\u003e` delegate. This allows Node.js code to call .NET asynchronously and avoid blocking the Node.js event loop. \n\nEdge provides a function that accepts a reference to C# code in one of the supported representations, and returns a Node.js function which acts as a JavaScript proxy to the `Func\u003cobject,Task\u003cobject\u003e\u003e` .NET delegate:\n\n```javascript\nvar edge = require('edge');\n\nvar myFunction = edge.func(...);\n```\n\nThe function proxy can then be called from Node.js like any asynchronous function:\n\n```javascript\nmyFunction('Some input', function (error, result) {\n    //...\n});\n```\n\nAlternatively, if you know the C# implementation will complete synchronously given the circumstances, you can call this function as any synchronous JavaScript function as follows:\n\n```javascript\nvar result = myFunction('Some input', true);\n```\n\nThe `true` parameter instead of a callback indicates that Node.js expects the C# implementation to complete synchronously. If the CLR function implementation does not complete synchronously, the call above will result in an exception. \n\nOne representation of CLR code that Edge.js accepts is C# source code. You can embed C# literal representing a .NET async lambda expression implementing the `Func\u003cobject,Task\u003cobject\u003e\u003e` delegate directly inside Node.js code:\n\n```javascript\nvar add7 = edge.func('async (input) =\u003e { return (int)input + 7; }');\n``` \n\nIn another representation, you can embed multi-line C# source code by providing a function with a body containing a multi-line comment. Edge extracts the C# code from the function body using regular expressions:\n\n```javascript\nvar add7 = edge.func(function() {/*\n    async (input) =\u003e {\n        return (int)input + 7;\n    }\n*/});\n```\n\nOr if you use ES6 you can use [template strings](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/template_strings) to define a multiline string:\n\n```javascript\nvar add7 = edge.func(`\n    async (input) =\u003e {\n        return (int)input + 7;\n    }\n`);\n```\n\nIf your C# code is more involved than a simple lambda, you can specify entire class definition. By convention, the class must be named `Startup` and it must have an `Invoke` method that matches the `Func\u003cobject,Task\u003cobject\u003e\u003e` delegate signature. This method is useful if you need to factor your code into multiple methods:\n\n```javascript\nvar add7 = edge.func(function() {/*\n    using System.Threading.Tasks;\n\n    public class Startup\n    {\n        public async Task\u003cobject\u003e Invoke(object input)\n        {\n            int v = (int)input;\n            return Helper.AddSeven(v);\n        }\n    }\n\n    static class Helper\n    {\n        public static int AddSeven(int v) \n        {\n            return v + 7;\n        }\n    }\n*/});\n```\n\nIf your C# code grows substantially, it is useful to keep it in a separate file. You can save it to a file with `*.csx` or `*.cs` extension, and then reference from your Node.js application:\n\n```javascript\nvar add7 = edge.func(require('path').join(__dirname, 'add7.csx'));\n```\n\nIf you integrate C# code into your Node.js application by specifying C# source using one of the methods above, edge will compile the code on the fly. If you prefer to pre-compile your C# sources to a CLR assembly, or if your C# component is already pre-compiled, you can reference a CLR assembly from your Node.js code. In the most generic form, you can specify the assembly file name, the type name, and the method name when creating a Node.js proxy to a .NET method:\n\n```javascript\nvar clrMethod = edge.func({\n    assemblyFile: 'My.Edge.Samples.dll',\n    typeName: 'Samples.FooBar.MyType',\n    methodName: 'MyMethod' // This must be Func\u003cobject,Task\u003cobject\u003e\u003e\n});\n```\n\nIf you don't specify methodName, `Invoke` is assumed. If you don't specify typeName, a type name is constructed by assuming the class called `Startup` in the namespace equal to the assembly file name (without the `.dll`). In the example above, if typeName was not specified, it would default to `My.Edge.Samples.Startup`.\n\nThe assemblyFile is relative to the working directory. If you want to locate your assembly in a fixed location relative to your Node.js application, it is useful to construct the assemblyFile using `__dirname`.  If you are using .NET Core, assemblyFile can also be a project name or NuGet package name that is specified in your `project.json` or `.deps.json` dependency manifest.\n\nYou can also create Node.js proxies to .NET functions specifying just the assembly name as a parameter:\n\n```javascript\nvar clrMethod = edge.func('My.Edge.Samples.dll');\n```\n\nIn that case the default typeName of `My.Edge.Samples.Startup` and methodName of `Invoke` is assumed as explained above. \n\n### How to: specify additional CLR assembly references in C# code\n\nWhen you provide C# source code and let edge compile it for you at runtime, edge will by default reference only mscorlib.dll and System.dll assemblies.  If you're using .NET Core, we automatically reference the most recent versions of the System.Runtime, System.Threading.Tasks, System.Dynamic.Runtime, and the compiler language packages, like Microsoft.CSharp. In applications that require additional assemblies you can specify them in C# code using a special hash pattern, similar to Roslyn. For example, to use ADO.NET you must reference System.Data.dll:\n\n```javascript\nvar add7 = edge.func(function() {/*\n\n    #r \"System.Data.dll\"\n\n    using System.Data;\n    using System.Threading.Tasks;\n\n    public class Startup\n    {\n        public async Task\u003cobject\u003e Invoke(object input)\n        {\n            // ...\n        }\n    }\n*/});\n```\n\nIf you prefer, instead of using comments you can specify references by providing options to the `edge.func` call:\n\n```javascript\nvar add7 = edge.func({\n    source: function() {/*\n\n        using System.Data;\n        using System.Threading.Tasks;\n\n        public class Startup\n        {\n            public async Task\u003cobject\u003e Invoke(object input)\n            {\n                // ...\n            }\n        }\n    */},\n    references: [ 'System.Data.dll' ]\n});\n```\n\nIf you are using .NET Core and are using the .NET Core SDK and CLI, you must have a `project.json` file (specification [here](https://github.com/aspnet/Home/wiki/Project.json-file)) that specifies the dependencies for the application.  This list of dependencies must also include the [Edge.js runtime package](https://www.nuget.org/packages/Edge.js/) and, if you need to be able to dynamically compile your code, the package(s) for the compilers that you plan to use, like [Edge.js.CSharp](https://www.nuget.org/packages/Edge.js.CSharp/).  You must have run the `dotnet restore` (to restore the dependencies) and `dotnet build` (to build your project and generate the dependency manifest) commands in that project's directory to generate a `.deps.json` file under `bin/[configuration]/[framework]`, i.e. `bin/Release/netstandard1.6/MyProject.deps.json`.  This `.deps.json` file must either be in the current working directory that `node` is executed in or you must specify its directory by setting the `EDGE_APP_ROOT` environment variable.  For example, if for a `netstandard1.6` project in the `c:\\DotNet\\MyProject` directory, you would run something like:\n\n```\nset EDGE_APP_ROOT=c:\\DotNet\\MyProject\\bin\\Release\\netstandard1.6\nnode app.js\n```\n\nEdge.js also supports running published .NET Core applications on servers that do not have the .NET Core SDK and CLI installed, which is a common scenario in production environments.  To do so, the `project.json` for your application should meet the following requirements:\n\n 1. It should target the `netcoreapp1.0` framework moniker.\n 2. It should reference `Microsoft.NETCore.DotNetHost` and `Microsoft.NETCore.DotNetHostPolicy`.  This is required so that the publish process can provide all the native libraries required to create a completely standalone version of your application.\n 3. `\"emitEntryPoint\": true` should be present under `buildOptions`.  You can add an empty `Main()` implementation to your project to accomodate it; this method will not be called, but is just a requirement in order for `dotnet publish` to generate a completely standalone app.\n\nOn your development machine, you would run `dotnet publish -r [target runtime for your production server]` (i.e. `dotnet publish -r ubuntu.14.04-x64`) to aggregate the package assemblies and native libraries necessary to run your application.  You can copy the contents of the publish directory up to your SDK- and CLI-less server and use them directly in Edge.js by setting the  `EDGE_APP_ROOT` environment variable to the directory on the server that you copied the published application to.\n\n### How to: marshal data between C# and Node.js\n\nEdge.js can marshal any JSON-serializable value between .NET and Node.js (although JSON serialization is not used in the process). Edge also supports marshalling between Node.js `Buffer` instance and a CLR `byte[]` array to help you efficiently pass binary data.\n\nYou can call .NET from Node.js and pass in a complex JavaScript object as follows:\n\n```javascript\nvar dotNetFunction = edge.func('Edge.Sample.dll');\n\nvar payload = {\n    anInteger: 1,\n    aNumber: 3.1415,\n    aString: 'foo',\n    aBoolean: true,\n    aBuffer: new Buffer(10),\n    anArray: [ 1, 'foo' ],\n    anObject: { a: 'foo', b: 12 }\n};\n\ndotNetFunction(payload, function (error, result) { });\n```\n\nIn .NET, JavaScript objects are represented as dynamics (which can be cast to `IDictionary\u003cstring,object\u003e` if desired), JavaScript arrays as `object[]`, and JavaScript `Buffer` as `byte[]`. Scalar JavaScript values have their corresponding .NET types (`int`, `double`, `bool`, `string`). Here is how you can access the data in .NET:\n\n```c#\nusing System.Threading.Tasks;\n\npublic class Startup\n{\n    public async Task\u003cobject\u003e Invoke(dynamic input)\n    {\n        int anInteger = (int)input.anInteger;\n        double aNumber = (double)input.aNumber;\n        string aString = (string)input.aString;\n        bool aBoolean = (bool)input.aBoolean;\n        byte[] aBuffer = (byte[])input.aBuffer;\n        object[] anArray = (object[])input.anArray;\n        dynamic anObject = (dynamic)input.anObject;\n\n        return null;\n    }\n}\n\n```\n\nSimilar type marshalling is applied when .NET code passes data back to Node.js code. In .NET code you can provide an instance of any CLR type that would normally be JSON serializable, including domain specific types like `Person` or anonymous objects. For example:\n\n```c#\nusing System.Threading.Tasks;\n\npublic class Person\n{\n    public int anInteger = 1;\n    public double aNumber = 3.1415;\n    public string aString = \"foo\";\n    public bool aBoolean = true;\n    public byte[] aBuffer = new byte[10];\n    public object[] anArray = new object[] { 1, \"foo\" };\n    public object anObject = new { a = \"foo\", b = 12 };\n}\n\npublic class Startup\n{\n    public async Task\u003cobject\u003e Invoke(dynamic input)\n    {\n        Person person = new Person();\n        return person;\n    }\n}\n```\n\nIn your Node.js code that invokes this .NET method you can display the result object that the callback method receives:\n\n```javascript\nvar edge = require('edge');\n\nvar getPerson = edge.func(function () {/*\n    using System.Threading.Tasks;\n\n    public class Person\n    {\n        public int anInteger = 1;\n        public double aNumber = 3.1415;\n        public string aString = \"foo\";\n        public bool aBoolean = true;\n        public byte[] aBuffer = new byte[10];\n        public object[] anArray = new object[] { 1, \"foo\" };\n        public object anObject = new { a = \"foo\", b = 12 };\n    }\n\n    public class Startup\n    {\n        public async Task\u003cobject\u003e Invoke(dynamic input)\n        {\n            Person person = new Person();\n            return person;\n        }\n    }\n*/});\n\ngetPerson(null, function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\nPassing this .NET object to Node.js generates a JavaScript object as follows:\n\n```\n$\u003enode sample.js\n{ anInteger: 1,\n  aNumber: 3.1415,\n  aString: 'foo',\n  aBoolean: true,\n  aBuffer: \u003cBuffer 00 00 00 00 00 00 00 00 00 00\u003e,\n  anArray: [ 1, 'foo' ],\n  anObject: { a: 'foo', b: 12 } }\n```\n\nWhen data is marshalled from .NET to Node.js, no checks for circular references are made. They will typically result in stack overflows. Make sure the object graph you are passing from .NET to Node.js is a tree and does not contain any cycles. \n\n**WINDOWS ONLY** When marshalling strongly typed objects (e.g. Person) from .NET to Node.js, you can optionally tell Edge.js to observe the [System.Web.Script.Serialization.ScriptIgnoreAttribute](http://msdn.microsoft.com/en-us/library/system.web.script.serialization.scriptignoreattribute.aspx). You opt in to this behavior by setting the `EDGE_ENABLE_SCRIPTIGNOREATTRIBUTE` environment variable:\n\n```\nset EDGE_ENABLE_SCRIPTIGNOREATTRIBUTE=1\n```\n\nEdge.js by default does not observe the ScriptIgnoreAttribute to avoid the associated performance cost. \n\n### How to: call Node.js from C#  \n\nIn addition to marshalling data, edge can marshal proxies to JavaScript functions when invoking .NET code from Node.js. This allows .NET code to call back into Node.js. \n\nSuppose the Node.js application passes an `add` function to the .NET code as a property of an object. The function receives two numbers and returns the sum of them via the provided callback:\n\n```javascript\nvar edge = require('edge');\n\nvar addAndMultiplyBy2 = edge.func(function () {/*\n    async (dynamic input) =\u003e {\n        var add = (Func\u003cobject, Task\u003cobject\u003e\u003e)input.add;\n        var twoNumbers = new { a = (int)input.a, b = (int)input.b };\n        var addResult = (int)await add(twoNumbers);\n        return addResult * 2;\n    }   \n*/});\n\nvar payload = {\n    a: 2,\n    b: 3,\n    add: function (data, callback) {\n        callback(null, data.a + data.b);\n    }\n};\n\naddAndMultiplyBy2(payload, function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\nThe .NET code implements the addAndMultiplyBy2 function. It extracts the two numbers passed from Node.js, calls back into the `add` function exported from Node.js to add them, multiplies the result by 2 in .NET, and returns the result back to Node.js:\n\n```\n$\u003enode sample.js\n10\n```\n\nThe Node.js function exported from Node.js to .NET must follow the prescriptive async pattern of accepting two parameters: payload and a callback. The callback function accepts two parameters. The first one is the error, if any, and the second the result of the operation:\n\n```javascript\nfunction (payload, callback) {\n    var error;  // must be null or undefined in the absence of error\n    var result; \n\n    // do something\n\n    callback(error, result);\n}\n```\n\nThe proxy to that function in .NET has the following signature:\n\n```c#\nFunc\u003cobject,Task\u003cobject\u003e\u003e\n```\n\nUsing TPL in CLR to provide a proxy to an asynchronous Node.js function allows the .NET code to use the convenience of the `await` keyword when invoking the Node.js functionality. The example above shows the use of the `await` keyword when calling the proxy of the Node.js `add` method.  \n\n### How to: export C# function to Node.js\n\nSimilarly to marshalling functions from Node.js to .NET, Edge.js can also marshal functions from .NET to Node.js. The .NET code can export a `Func\u003cobject,Task\u003cobject\u003e\u003e` delegate to Node.js as part of the return value of a .NET method invocation. For example:\n\n```javascript\nvar createHello = edge.func(function () {/*\n    async (input) =\u003e\n    {\n        return (Func\u003cobject,Task\u003cobject\u003e\u003e)(async (i) =\u003e { \n            Console.WriteLine(\"Hello from .NET\"); \n            return null; \n        });\n    }\n*/});\n\nvar hello = createHello(null, true); \nhello(null, true); // prints out \"Hello from .NET\"\n```\n\nThis mechanism in conjunction with a closure can be used to expose CLR class instances or CLR state in general to JavaScript. For example:\n\n```javascript\nvar createCounter = edge.func(function () {/*\n    async (input) =\u003e\n    {\n        var k = (int)input; \n        return (Func\u003cobject,Task\u003cobject\u003e\u003e)(async (i) =\u003e { return ++k; });\n    }\n*/});\n\nvar counter = createCounter(12, true); // create counter with 12 as initial state\nconsole.log(counter(null, true)); // prints 13\nconsole.log(counter(null, true)); // prints 14\n```\n\n### How to: script Python in a Node.js application\n\n**NOTE** This functionality requires IronPython and has been tested on Windows only. \n\nEdge.js enables you to run Python and Node.js in-process.\n\nIn addition to [platform specific prerequisites](#what-you-need) you need [IronPython 2.7.3](http://ironpython.codeplex.com/releases/view/81726) to proceed.\n\n#### Hello, world\n\nInstall edge and edge-py modules:\n\n```\nnpm install edge\nnpm install edge-py\n```\n\nIn your server.js:\n\n```javascript\nvar edge = require('edge');\n\nvar hello = edge.func('py', function () {/*\n    def hello(input):\n        return \"Python welcomes \" + input\n\n    lambda x: hello(x)\n*/});\n\nhello('Node.js', function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\nRun and enjoy:\n\n```\n$\u003enode py.js\nPython welcomes Node.js\n```\n\n#### The interop model\n\nYour Python script must evaluate to a lambda expression that accepts a single parameter. The parameter represents marshalled input from the Node.js code. The return value of the lambda expression is passed back as the result to Node.js code. The Python script can contain constructs (e.g. Python functions) that are used in the closure of the lambda expression. The instance of the script with associated state is created when `edge.func` is called in Node.js. Each call to the function referes to that instance.\n\nThe simplest *echo* Python script you can embed in Node.js looks like this:\n\n```python\nlambda x: x\n```\n\nTo say hello, you can use something like this:\n\n```python\nlambda: x: \"Hello, \" + x\n```\n\nTo maintain a running sum of numbers:\n\n```python\ncurrent = 0\n\ndef add(x):\n    global current\n    current = current + x\n    return current\n\nlambda x: add(x)\n```\n\n#### Python in its own file\n\nYou can reference Python script stored in a *.py file instead of embedding Python code in a Node.js script.\n\nIn your hello.py file:\n\n```python\ndef hello(input):\n    return \"Python welcomes \" + input\n\nlambda x: hello(x)\n```\n\nIn your hello.js file:\n\n```javascript\nvar edge = require('edge');\n\nvar hello = edge.func('py', 'hello.py');\n\nhello('Node.js', function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\nRun and enjoy:\n\n```\n$\u003enode hello.js\nPython welcomes Node.js\n```\n\n#### To sync or to async, that is the question\n\nIn the examples above Python script was executing asynchronously on its own thread without blocking the singleton V8 thread on which the Node.js event loop runs. This means your Node.js application remains responsive while the Python code executes in the background. \n\nIf you know your Python code is non-blocking, or if you know what you are doing, you can tell Edge.js to execute Python code on the singleton V8 thread. This will improve performance for non-blocking Python scripts embedded in a Node.js application:\n\n```javascript\nvar edge = require('edge');\n\nvar hello = edge.func('py', {\n    source: function () {/*\n        def hello(input):\n            return \"Python welcomes \" + input\n\n        lambda x: hello(x)\n    */},\n    sync: true\n});\n\nconsole.log(hello('Node.js', true));\n```\n\nThe `sync: true` property in the call to `edge.func` tells Edge.js to execute Python code on the V8 thread as opposed to creating a new thread to run Python script on. The `true` parameter in the call to `hello` requests that Edge.js does in fact call the `hello` function synchronously, i.e. return the result as opposed to calling a callback function. \n\n### How to: script PowerShell in a Node.js application\n\n**NOTE** This functionality only works on Windows. \n\nEdge.js enables you to run PowerShell and Node.js in-process on Windows. [Edge-PS](https://github.com/dfinke/edge-ps) connects the PowerShell ecosystem with Node.js.\n\nYou need Windows, [Node.js](http://nodejs.org), [.NET 4.5](http://www.microsoft.com/en-us/download/details.aspx?id=30653), and [PowerShell 3.0](http://www.microsoft.com/en-us/download/details.aspx?id=34595) to proceed.\n\n### Hello, world\n\nInstall edge and edge-ps modules:\n\n``` \nnpm install edge\nnpm install edge-ps\n```\n\nIn your server.js:\n\n```javascript\nvar edge = require('edge');\n\nvar hello = edge.func('ps', function () {/*\n\"PowerShell welcomes $inputFromJS on $(Get-Date)\"\n*/});\n\nhello('Node.js', function (error, result) {\n    if (error) throw error;\n    console.log(result[0]);\n});\n```\n\nRun and enjoy:\n\n```\nC:\\testEdgeps\u003enode server\nPowerShell welcomes Node.js on 05/04/2013 09:38:40\n```\n\n#### Tapping into PowerShell's ecosystem\n\nRather than embedding PowerShell directly, you can use PowerShell files, dot source them and even use *Import-Module*.\n\nWhat you can do in native PowerShell works in Node.js.\n\n#### Interop PowerShell and Python\n\nHere you can reach out to IronPython from PowerShell from within Node.js on Windows. This holds true for working with JavaScript frameworks and C#.\n\n```javascript\nvar edge = require('edge');\n\nvar helloPowerShell = edge.func('ps', function () {/*\n\t\"PowerShell welcomes $inputFromJS\"\n*/});\n\nvar helloPython = edge.func('py', function () {/*\n    def hello(input):\n        return \"Python welcomes \" + input\n\n    lambda x: hello(x)\n*/});\n\n\nhelloPython('Node.js', function(error, result){\n\tif(error) throw error;\n\n\thelloPowerShell(result, function(error, result){\n\t\tif(error) throw error;\n\t\tconsole.log(result[0]);\n\t});\n});\n```\n\n### How to: script F# in a Node.js application\n\n**NOTE** This functionality has not been tested on non-Windows platforms. \n\nThis section is coming up. In the meantime please refer to [Dave Thomas blog post](http://7sharpnine.com/posts/i-node-something/). This has been validated on Windows only. \n\n```javascript\nvar edge = require('edge');\n\nvar helloFs = edge.func('fs', function () {/*\n    fun input -\u003e async { \n        return \"F# welcomes \" + input.ToString()\n    }\n*/});\n\nhelloFs('Node.js', function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\n### How to: script Lisp in a Node.js application\n\n**NOTE** This functionality has not been tested on non-Windows platforms. \n\nThe [edge-lsharp](https://github.com/richorama/edge-lsharp) extension uses [LSharp](https://github.com/RobBlackwell/LSharp) to compile and run Lisp to .NET.\n\nInstall edge and edge-lsharp modules:\n\n```\nnpm install edge\nnpm install edge-lsharp\n```\n\nIn your server.js:\n\n```javascript\nvar edge = require('edge');\nvar fact = edge.func('lsharp', function(){/*\n\n;; Factorial\n(def fact(n) \n    (if (is n 0) 1 (* n (fact (- n 1)))))\n\n*/});\n\nfact([5], function(err, answer){\n    console.log(answer);\n    // = 120\n});\n```\n\nAn LSharp filename can be passed in instead of the Lisp string/comment:\n\n```js\nvar edge = require('edge');\nvar lisp = edge.func('lsharp', 'lisp-func.ls');\n\nlisp(['arg1', 'arg2'], function(err, result){\n    \n});\n```\n\nIn Lisp you can specify either a function (as shown in the first example) or just return a value:\n\n```js\nvar edge = require('edge');\nvar lisp = edge.func('lsharp', '(+ 2 3)');\n\nlisp([], function(err, answer){\n    console.log(answer);\n    // = 5\n});\n```\n\n### How to: script T-SQL in a Node.js application\n\n**NOTE** This functionality has only been tested on Windows. Although ADO.NET exist in Mono, your mileage can vary. \n\nThe edge-sql extension of Edge.js allows for accessing MS SQL databases by scripting T-SQL inside the Node.js application. The edge-sql extension uses async ADO.NET SQL client to access MS SQL. \n\nYou need Windows, [Node.js](http://nodejs.org), and [.NET 4.5](http://www.microsoft.com/en-us/download/details.aspx?id=30653). To run the sample code below you also need a connection string to the sample Northwind database that ships with MS SQL. \n\n#### Hello, world\n\nInstall edge and edge-sql modules:\n\n```\nnpm install edge\nnpm install edge-sql\n```\n\nSet the connection string as an environment variable (your connection string may be different):\n\n```\nset EDGE_SQL_CONNECTION_STRING=Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True\n```\n\nIn your server.js:\n\n```javascript\nvar edge = require('edge');\n\nvar getTop10Products = edge.func('sql', function () {/*\n    select top 10 * from Products\n*/});\n\ngetTop10Products(null, function (error, result) {\n    if (error) throw error;\n    console.log(result);\n    console.log(result[0].ProductName);\n    console.log(result[1].ReorderLevel);\n});\n```\n\nRun and enjoy:\n\n```\nC:\\projects\\edge\\samples\u003enode server.js\n[ { ProductID: 10,\n    ProductName: 'New Ikura',\n    SupplierID: 4,\n    CategoryID: 8,\n    QuantityPerUnit: '12 - 200 ml jars',\n    UnitPrice: '31.000',\n    UnitsInStock: 31,\n    UnitsOnOrder: 0,\n    ReorderLevel: 0,\n    Discontinued: false },\n    ...\n]\nNew Ikura\n12\n```\n\n#### Parameterized queries\n\nYou can construct a parameterized query once and provide parameter values on a per-call basis:\n\n```javascript\nvar edge = require('edge');\n\nvar getProduct = edge.func('sql', function () {/*\n    select * from Products \n    where ProductId = @myProductId\n*/});\n\ngetProduct({ myProductId: 10 }, function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\n#### Basic CRUD support: select, update, insert, delete\n\nThe four basic CRUD operations are supported. For example, here is how an update can look like:\n\n```javascript\nvar edge = require('edge');\n\nvar updateProductName = edge.func('sql', function () {/*\n    update Products\n    set ProductName = @newName \n    where ProductId = @myProductId\n*/});\n\nupdateProductName({ myProductId: 10, newName: 'New Ikura' }, function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\n### How to: support for other CLR languages\n\nEdge.js can work with any pre-compiled CLR assembly that contains the `Func\u003cobject,Task\u003cobject\u003e\u003e` delegate. Out of the box, Edge.js also allows you to embed C# source code in a Node.js application and compile it on the fly. \n\nTo enable compilation of other CLR languages (e.g. F#) at runtime, or to support domain specific languages (DSLs) like T-SQL, you can use the compiler composability model provided by Edge.js. Please read the [add support for a CLR language](https://github.com/tjanczuk/edge/wiki/Add-support-for-a-CLR-language) guide to get started. \n\n### How to: exceptions\n\nEdge.js marshals Node.js errors and exceptions to .NET as well as .NET exceptions to Node.js. \n\nCLR exceptions thrown in .NET code invoked from Node.js are marshalled as the `error` parameter to the Node.js callback function. Consider this example:\n\n```javascript\nvar edge = require('edge');\n\nvar clrFunc = edge.func(function () {/*\n    async (dynamic input) =\u003e {\n        throw new Exception(\"Sample exception\");\n    }\n*/});\n\nclrFunc(null, function (error, result) {\n    if (error) {\n\t\tconsole.log('Is Error?', error instanceof Error);\n\t\tconsole.log('-----------------');\n\t\tconsole.log(util.inspect(error, showHidden=true, depth=99, colorize=false));\n\t\treturn;\n\t}\n});\n```\n\nRunning this Node.js application shows that the CLR exception was indeed received by the Node.js callback. The `error` parameter contains an Error object having most of the properties of the Exceptions copied over:\n```\nIs Error? true\n-----------------\n{ [System.AggregateException: One or more errors occurred.]\n  message: 'One or more errors occurred.',\n  name: 'System.AggregateException',\n  InnerExceptions: 'System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]',\n  Message: 'One or more errors occurred.',\n  Data: 'System.Collections.ListDictionaryInternal',\n  InnerException:\n   { [System.Exception: Sample exception]\n     message: 'Sample exception',\n     name: 'System.Exception',\n     Message: 'Sample exception',\n     Data: 'System.Collections.ListDictionaryInternal',\n     TargetSite: 'System.Reflection.RuntimeMethodInfo',\n     StackTrace: '   at Startup.\u003c\u003cInvoke\u003eb__0\u003ed__2.MoveNext() in c:\\\\Users\\\\User.Name\\\\Source\\\\Repos\\\\eCash2\\\\test\\\\edge2.js:line 7\\r\\n--- End of stack trace from previous location where exception was thrown ---\\r\\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\\r\\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\\r\\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\\r\\n   at Startup.\u003cInvoke\u003ed__4.MoveNext() in c:\\\\Users\\\\User.Name\\\\Source\\\\Repos\\\\eCash2\\\\test\\\\edge2.js:line 5',\n     Source: 'cp2luegt',\n     HResult: -2146233088 },\n  HResult: -2146233088 }\n```\nThe exception is copied back as Error object like every normal result object from the .NET world to JavaScript. \nTherefore all properties and their values are available on the Error object.\n\nAdditionally, the following happens during the mapping:\n* To represent the Exception type, its full name is stored as `name`.\n* To follow the [JavaScript convention for Errors](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error), the `Message` is also stored as the property `message`.\n* `System::Reflection::RuntimeMethodInfo`s are not copied to avoid stack overflows\n\n```\n$\u003enode sample.js\n\nEdge.js:58\n    edge.callClrFunc(appId, data, callback);\n                     ^\nSystem.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. \n---\u003e System.Exception: Sample exception\n   at Startup.Invoke(Object input) in sample.cs:line 12\n``` \n\nJavaScript exceptions thrown in Node.js code invoked from .NET are wrapped in a CLR exception and cause the asynchronous `Task\u003cobject\u003e` to complete with a failure. Errors passed by Node.js code invoked from .NET code to the callback function's `error` parameter have the same effect. Consider this example:\n\n```javascript\nvar edge = require('edge');\n\nvar multiplyBy2 = edge.func(function () {/*\n    async (dynamic input) =\u003e {\n        var aFunctionThatThrows = (Func\u003cobject, Task\u003cobject\u003e\u003e)input.aFunctionThatThrows;\n        try {\n            var aResult = await aFunctionThatThrows(null);\n        }\n        catch(Exception e)\n        {\n            Console.WriteLine(e);\n        }\n\n        return null;\n    }\n*/});\n\nvar payload = {\n    someParameter: 'arbitrary parameter',\n    aFunctionThatThrows: function (data, callback) {\n        throw new Error('Sample JavaScript error');\n    }\n};\n\nmultiplyBy2(payload, function (error, result) {\n    if (error) throw error;\n    console.log(result);\n});\n```\n\nRunning the code shows the .NET code receiving a CLR exception as a result of the Node.js function throwing a JavaScript error. The exception shows the complete stack trace, including the part that executed in the Node.js code:\n\n```\n$\u003enode sample.js\nSystem.Exception: Error: Sample JavaScript error\n    at payload.aFunctionThatThrows (sample.js:7:11)\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\n   at Edge.Sample.Startup.\u003cInvoke\u003ed__0.MoveNext()\n```\n\n### How to: app.config\n\nWhen running C# code within Node.js app, the app config file is node.exe.config and should be located right next to the node.exe file.\n\n### How to: debugging\n\n**NOTE** This is Windows-only functionality.\n\nOn Windows, you can debug the .NET code running as part of your Node.js application by attaching a managed code debugger (e.g. Visual Studio) to node.exe. You can debug .NET code in a pre-compiled CLR assembly as well C# literals embedded in the application and compiled by Edge.js at runtime. \n\n#### Debugging pre-compiled .NET code\n\nIf you have integrated .NET code into a Node.js application using a pre-compiled CLR assembly like this:\n\n```javascript\nvar hello = edge.func('My.Assembly.dll');\n```\n\nthen the best way to debug your .NET code is to attach a managed code debugger (e.g. Visual Studio) to the node.exe process. Since the node.exe process runs both native and managed code, make sure to select managed code type as target:\n\n![debug](https://f.cloud.github.com/assets/822369/190564/a41bab2c-7efb-11e2-878f-82ae2325876c.PNG)\n\nFrom there, you can set breakpoints in your .NET code and the debugger will stop when they are reached.\n\n#### Debugging embedded C# code\n\nDebugging embedded C# code (on Windows) requires that `EDGE_CS_DEBUG` environment variable is set in the environment of the node.exe process:\n\n```\nset EDGE_CS_DEBUG=1\n```\n\nWithout this setting (the default), Edge.js will not generate debugging information when compiling embedded C# code.\n\nYou can debug C# code embedded into a Node.js application using a reference to a *.cs or *.csx file:\n\n```javascript\nvar hello = edge.func('MyClass.cs');\n```\n\nYou can also debug C# code embedded directly into a *.js file using the function comment syntax:\n\n```javscript\nvar hello = edge.func(function () {/*\n    async (input) =\u003e\n    {\n        System.Diagnostics.Debugger.Break();\n        var result = \".NET welcomes \" + input.ToString();\n        return result;\n    }\n*/});\n```\n\nYou *cannot* debug C# code embedded as a simple string literal:\n\n```javascript\nvar hello = edge.func('async (input) =\u003e { return 2 * (int)input; }');\n```\n\nAfter setting `EDGE_CS_DEBUG=1` environment variable before starting node.exe and attaching the managed debugger to the node.exe process, you can set breakpoints in C# code (which may appear as a JavaScript comment), or use `System.Diagnostics.Debugger.Break()` to break into the debugger from .NET code. \n\n![debug-inline](https://f.cloud.github.com/assets/822369/326781/923d870c-9b4a-11e2-8f45-201a6431afbf.PNG)\n\n### Performance\n\nRead more about [performance of Edge.js on the wiki](https://github.com/tjanczuk/edge/wiki/Performance). Here is the gist of the latency (smaller is better):\n\n![edgejs-performance1](https://f.cloud.github.com/assets/822369/486393/645f696a-b920-11e2-8a20-9fa6932bb092.png)\n\n### Building on Windows\n\nYou must have Visual Studio 2015 toolset, Python 2.7.x, and node-gyp installed for building.\n\nTo build and test the project against all supported versions of Node.js in x86 and x64 flavors, run the following:\n\n```\ntools\\buildall.bat\ntest\\testall.bat\nnpm run jshint\n```\n\nTo build one of the versions of Node.js officially released by [Node.js](http://nodejs.org/dist), do the following:\n\n```\ncd tools\nbuild.bat release 8.2.1\n```\n\nNote: the Node.js version number you provide must be version number corresponding to one of the subdirectories of http://nodejs.org/dist. The command will build both x32 and x64 architectures (assuming you use x64 machine). The command will also copy the edge\\_\\*.node executables to appropriate locations under lib\\native directory where they are looked up from at runtime. The `npm install` step copies the C standard library shared DLL to the location of the edge\\_\\*.node files for the component to be ready to go.\n\nTo build the C++\\CLI native extension using the version of Node.js installed on your machine, issue the following command:\n\n```\nnpm install -g node-gyp\nnode-gyp configure --msvs_version=2015\nnode-gyp build -debug\n```\n\nYou can then set the `EDGE_NATIVE` environment variable to the fully qualified file name of the built edge_\\*.node binary (edge\\_nativeclr.node if you're using the native CLR runtime or edge\\_coreclr.node if you're using .NET Core). It is useful during development, for example:\n\n```\nset EDGE_NATIVE=C:\\projects\\edge\\build\\Debug\\edge_nativeclr.node\n``` \n\nYou can also set the `EDGE_DEBUG` environment variable to 1 to have the edge module generate debug traces to the console when it runs.\n\n### Running tests\n\nYou must have mocha installed on the system. Then:\n\n```\nnpm test\n```\n\nor, from the root of the enlistment:\n\n```\nmocha -R spec\n```\n\n**NOTE** in environments with both desktop CLR/Mono and .NET Core installed, tests will by default use desktop CLR/Mono. To run tests against .NET Core, use: \n\n```\nEDGE_USE_CORECLR=1 npm test\n```\n\n#### Node.js version targeting on Windows\n\n**NOTE** this is Windows only functionality.\n\nIf you want to run tests after building against a specific version of Node.js that one of the previous builds used, issue the following command:\n\n```\ncd test\ntest.bat ia32 0.10.0\n```\n\nWhich will run the tests using Node.js x86 v0.10.0. Similarly:\n\n```\ncd test\ntest.bat x64 0.8.22\n```\n\nWould run tests against Node.js 0.8.22 on x64 architecture.\n\nLastly, you can run jshint on the project with:\n\n```\nnpm run jshint\n```\n\n### Building on OSX\n\nPrerequisities:\n\n* [Homebrew](http://brew.sh/)  \n* [Mono x64](http://www.mono-project.com/download/#download-mac) and/or [.NET Core](https://dotnet.github.io/getting-started/) - see below  \n* [Node.js x64](http://nodejs.org/) (tested with v4.1.1)  \n\nYou can use Edge.js on OSX with either Mono or .NET Core installed, or both.\n\nIf you choose to [install Mono](http://www.mono-project.com/download/#download-mac), select the universal installer to make sure you get the x64 version. Edge.js requires Mono x64.  If you choose to install .NET Core, follow the steps [here](https://www.microsoft.com/net/core#macosx)\n\nThen install and build Edge.js:\n\n```bash\nbrew install pkg-config\nnpm install edge\n```\n\n**NOTE** if the build process complains about being unable to locate Mono libraries, you may need to specify the search path explicitly. This may be installation dependent, but in most cases will look like: \n\n```bash\nPKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig \\\n  npm install edge\n```\n\nIf you installed both Mono and .NET Core, by default Edge will use Mono. You opt in to using .NET Core with the `EDGE_USE_CORECLR` environment variable: \n\n```bash\nEDGE_USE_CORECLR=1 node myapp.js\n```\n\n#### Building on OSX (advanced)\n\nTo build edge from a clone of the repository or source code:\n\n```bash\nnode-gyp configure build\n```\n\nTo build a debug build instead of release, you need to:\n\n```bash\nnode-gyp configure build -debug\nexport EDGE_NATIVE=/Users/tomek/edge/build/Debug/edge_nativeclr.node\n```\n\n### Building on Linux \n\nFor a normative set of steps to set up Edge.js on Linux with both Mono and CoreCLR please refer to the [Dockerfile](https://github.com/tjanczuk/edge/blob/master/Dockerfile). You can also use the ready-made [Docker image](#docker). \n\n### Using .NET Core\n\nIf you have only .NET Core installed on your system and not Mono, you can run Edge with no changes.  However, if you have both runtimes installed, Edge will automatically use Mono unless directed otherwise.  To use .NET Core in a dual-runtime environment, set the `EDGE_USE_CORECLR=1` environment variable when starting node, i.e.\n\n```bash\nEDGE_USE_CORECLR=1 node sample.js\n```\n\nEdge will try to find the .NET Core runtime in the following locations:\n\n * The path in the `CORECLR_DIR` environment variable, if provided\n * The current directory\n * The directory containing `edge_*.node`\n * Directories in the `PATH` environment variable.  Once a directory containing the `dotnet` executable is located, we then do the following to decide which version of the framework (you can have several installed at once) to load\n\t * If the `CORECLR_VERSION` environment variable was specified, we try to load that version\n\t * Else, if the project.json/*.deps.json has a reference to `Microsoft.NETCore.App`, indicating that it was built for a specific framework version, we try to load that version\n\t * Otherwise, we pick the maximum installed version\n  \nSo, if the CLR is another location or you want to use a version of the CLR other than the default that you've set, the best way to specify that is through the `CORECLR_DIR` or `CORECLR_VERSION` environment variables, i.e.\n\n```bash\nEDGE_USE_CORECLR=1 \\\nCORECLR_DIR=/usr/share/dotnet/dnx-coreclr-linux-x64.1.0.0-beta6-11944 \\\nnode sample.js\n```\n\n## Scripting Node.js from CLR\n\nIf you are writing a CLR application (e.g. a C# console application or ASP.NET web app), this section explains how you include and run Node.js code in your app. Currently it works on Windows using desktop CLR, but support for MacOS, and Linux as well as .NET Core is coming soon. \n\n### What you need\n\nYou need Windows with:\n\n* [.NET 4.5](http://www.microsoft.com/en-us/download/details.aspx?id=30653)  \n* [Edge.js NuGet package](https://www.nuget.org/packages/Edge.js)  \n* [Node.js](http://nodejs.org) (optional, if you want to use additional NPM packages)\n\nEdge.js support for scripting Node.js ships as a NuGet Package called `Edge.js`. It comes with everything you need to get started writing applications for x86 and x64 architectures. However, if you want to use additional Node.js packages from NPM, you must separately install Node.js runtime to access the NPM package manager. The latest Edge.js NuGet package has been developed and tested with Node.js v8.2.1. Older Edge.js packages exist for prior versions of Node.js. If you choose a different version of Node.js to install NPM packages, your mileage can vary. \n\n**NOTE** you cannot use native Node.js extensions when scripting Node.js from CLR using Edge. \n\nYou can install the [Edge.js NuGet package](https://www.nuget.org/packages/Edge.js) using the Visual Studio built-in NuGet package management functionality or using the stand-alone [NuGet client](http://docs.nuget.org/docs/start-here/installing-nuget). \n\n### How to: Node.js hello, world\n\nCreate a .NET 4.5 Console Application in Visual Studio. Add the Edge.js NuGet package to the project. Then in your code:\n\n```c#\nusing System;\nusing System.Threading.Tasks;\nusing EdgeJs;\n\nclass Program\n{\n    public static async Task Start()\n    {\n        var func = Edge.Func(@\"\n            return function (data, callback) {\n                callback(null, 'Node.js welcomes ' + data);\n            }\n        \");\n\n        Console.WriteLine(await func(\".NET\"));\n    }\n\n    static void Main(string[] args)\n    {\n        Start().Wait();\n    }\n}\n```\n\nCompile and run:\n\n```\nC:\\project\\sample\\bin\\Debug\u003e sample.exe\nNode.js welcomes .NET\n```\n\n### How to: integrate Node.js code into CLR code\n\nThe Edge.js NuGet package contains a single managed assembly `EdgeJs.dll` with a single class `EdgeJs.Edge` exposing a single static function `Func`. The function accepts a string containing code in Node.js that constructs and *returns* a JavaScript function. The JavaScript function must have the signature required by Edge.js's prescriptive interop pattern: it must accept one parameter and a callback, and the callback must be called with an error and one return value: \n\n```c#\nvar func = Edge.Func(@\"\n    return function (data, callback) {\n        callback(null, 'Hello, ' + data);\n    }\n\");\n```\n\nEdge.js creates a `Func\u003cobject,Task\u003cobject\u003e\u003e` delegate in CLR that allows .NET code to call the Node.js function asynchronously. You can use the standard TPL mechanisms or the async/await keywords to conveniently await completion of the asynchornous Node.js function:\n\n```c#\nvar result = await func(\".NET\");\n// result == \"Hello, .NET\"\n```\n\nNote that the Node.js code snippet is not a function *definition*. Instead it must create and *return* a function instance. This allows you to initialize and maintain encapsulated Node.js state associated with the instance of the created function. The initialization code will execute only once when you call `Edge.Func`. Conceptually this is similar to defining a Node.js module that exports a single function (by returning it to the caller).  For example:\n\n```c#\nvar increment = Edge.Func(@\"\n    var current = 0;\n\n    return function (data, callback) {\n        current += data;\n        callback(null, current);\n    }\n\");\n\nConsole.WriteLine(await increment(4)); // outputs 4\nConsole.WriteLine(await increment(7)); // outputs 11\n```\n\nUsing multiline C# string literals is convenient for short Node.js code snippets, but you may want to store larger Node.js code in its own `*.js` file or files. \n\nOne pattern is to store your Node.js code in a `myfunc.js` file:\n\n```javascript\nreturn function (data, callback) {\n    callback(null, 'Node.js welcomes ' + data);\n}\n```\n\nAnd then load such file into memory with `File`:\n\n```c#\nvar func = Edge.Func(File.ReadAllText(\"myfunc.js\"));\n```\n\nAnother pattern is to define a Node.js module that itself is a function:\n\n```javascript\nmodule.exports = function (data, callback) {\n    callback(null, 'Node.js welcomes ' + data);\n};\n```\n\nAnd then load and return this module with a short snippet of Node.js:\n\n```c#\nvar func = Edge.Func(@\"return require('./../myfunc.js')\");\n```\n\n(Note the relative location of the file).\n\n### How to: use Node.js built-in modules\n\nYou can use Node.js built-in modules out of the box. For example, you can set up a Node.js HTTP server hosted in a .NET application and call it from C#:\n\n```c#\nvar createHttpServer = Edge.Func(@\"\n    var http = require('http');\n\n    return function (port, cb) {\n        var server = http.createServer(function (req, res) {\n            res.end('Hello, world! ' + new Date());\n        }).listen(port, cb);\n    };\n\");\n\nawait createHttpServer(8080);\nConsole.WriteLine(await new WebClient().DownloadStringTaskAsync(\"http://localhost:8080\"));\n```\n\n### How to: use external Node.js modules\n\nYou can use external Node.js modules, for example modules installed from NPM. \n\nNote: Most Node.js modules are written in JavaScript and will execute in Edge as-is. However, some Node.js external modules are native binary modules, rebuilt by NPM on module installation to suit your local execution environment. Native binary modules will not run in Edge unless they are rebuilt to link against the NodeJS dll that Edge uses.\n\nTo install modules from NPM, you must first [install Node.js](http://nodejs.org) on your machine and use the `npm` package manager that comes with the Node.js installation. NPM modules must be installed in the directory where your build system places the Edge.js NuGet package (most likely the same location as the rest of your application binaries), or any ancestor directory. Alternatively, you can install NPM modules globally on the machine using `npm install -g`:\n\n```\nC:\\projects\\websockets\u003e npm install ws\n...\nws@0.4.31 node_modules\\ws\n├── tinycolor@0.0.1\n├── options@0.0.5\n├── nan@0.3.2\n└── commander@0.6.1\n```\n\nYou can then use the installed `ws` module to create a WebSocket server inside of a .NET application:\n\n```c#\nclass Program\n{\n    public static async void Start()\n    {\n        var createWebSocketServer = Edge.Func(@\"\n            var WebSocketServer = require('ws').Server;\n\n            return function (port, cb) {\n                var wss = new WebSocketServer({ port: port });\n                wss.on('connection', function (ws) {\n                    ws.on('message', function (message) {\n                        ws.send(message.toUpperCase());\n                    });\n                    ws.send('Hello!');\n                });\n                cb();\n            };\n        \");\n\n        await createWebSocketServer(8080);\n    }\n\n    static void Main(string[] args)\n    {\n        Task.Run((Action)Start);\n        new ManualResetEvent(false).WaitOne();\n    }\n}\n```\n\nThis WebSocket server sends a *Hello* message to the client when a new connection is established, and then echos a capitalized version of every message it receives back to the client. You can test this webserver with the `wscat` tool included with the `ws` module. To make it convenient to use, first install the `ws` module globally:\n\n```\nnpm install ws -g\n```\n\nThen start the .NET application conatining the WebSocket server and establish a connection to it with `wscat`:\n\n```\nC:\\projects\\websockets\u003e wscat -c ws://localhost:8080/\n\nconnected (press CTRL+C to quit)\n\n\u003c Hello!\n\u003e foo\n\u003c FOO\n\u003e bar\n\u003c BAR\n```\n\nA self-contained Node.js WebSocket server, even if running within a .NET application, is rather unexciting. After all, the same could be accomplished with a stand-alone Node.js process. Ideally you could extablish a WebSocket server in Node.js, but handle the messages in .NET. Let's do it - read on. \n\n### How to: handle Node.js events in .NET\n\nIt is often useful to handle certain events raised by the Node.js code within .NET. For example, you may want to establish a WebSocket server in Node.js, and handle the incoming messages in the .NET part of your application. This can be accomplished by passig a .NET callback function to Node.js when the the WebSocket server is created:\n\n```c#\nclass Program\n{\n    public static async void Start()\n    {\n        // Define an event handler to be called for every message from the client\n\n        var onMessage = (Func\u003cobject, Task\u003cobject\u003e\u003e)(async (message) =\u003e\n        {\n            return \"Received string of length \" + ((string)message).Length;\n        });\n\n        // The WebSocket server delegates handling of messages from clients\n        // to the supplied .NET handler\n\n        var createWebSocketServer = Edge.Func(@\"\n            var WebSocketServer = require('ws').Server;\n\n            return function (options, cb) {\n                var wss = new WebSocketServer({ port: options.port });\n                wss.on('connection', function (ws) {\n                    ws.on('message', function (message) {\n                        options.onMessage(message, function (error, result) {\n                            if (error) throw error;\n                            ws.send(result);\n                        });\n                    });\n                    ws.send('Hello!');\n                });\n                cb();\n            };\n        \");\n\n        // Create a WebSocket server on a specific TCP port and using the .NET event handler\n\n        await createWebSocketServer(new\n        {\n            port = 8080,\n            onMessage = onMessage\n        });\n    }\n\n    static void Main(string[] args)\n    {\n        Task.Run((Action)Start);\n        new ManualResetEvent(false).WaitOne();\n    }\n}\n```\n\nUsing `wscat`, you can verify the .NET handler is indeed invoked for every websocket message:\n\n```\nC:\\projects\\websockets\u003e wscat -c ws://localhost:8080/\n\nconnected (press CTRL+C to quit)\n\n\u003c Hello!\n\u003e Foo\n\u003c Received string of length 3\n\u003e FooBar\n\u003c Received string of length 6\n```\n\nThis example shows how Edge.js can create JavaScript proxies to .NET functions and marshal calls across the V8/CLR boundary in-process. Read more about [data marshaling between Node.js and CLR](#how-to-marshal-data-between-c-and-nodejs).\n\n### How to: expose Node.js state to .NET\n\nIn the previous example [a Node.js HTTP server was created and started from .NET](#how-to-use-nodejs-built-in-modules). Suppose at some point you want to stop the HTTP server from your .NET code. Given that all references to it are embedded within Node.js code, it is not possible. However, just as Edge.js can [pass a .NET function to Node.js](#how-to-handle-nodejs-events-in-net), it also can export a Node.js function to .NET. Moreover, that function can be implemented as a closure over Node.js state. This is how it would work:\n\n```c#\nvar createHttpServer = Edge.Func(@\"\n    var http = require('http');\n\n    return function (port, cb) {\n        var server = http.createServer(function (req, res) {\n            res.end('Hello, world! ' + new Date());\n        }).listen(port, function (error) {\n            cb(error, function (data, cb) {\n                server.close();\n                cb();\n            });\n        });\n    };\n\");\n\nvar closeHttpServer = (Func\u003cobject,Task\u003cobject\u003e\u003e)await createHttpServer(8080);\nConsole.WriteLine(await new WebClient().DownloadStringTaskAsync(\"http://localhost:8080\"));\nawait closeHttpServer(null);\n```\n\nNotice how the `createHttpServer` function, in addition to starting an HTTP server in Node.js, is also returning a .NET proxy to a JavaScript function that allows that server to be stopped. \n\n### How to: use Node.js in ASP.NET web applications\n\nUsing Node.js via Edge.js in ASP.NET web applications is no different than in a .NET console application. The Edge.js NuGet package must be referenced in your ASP.NET web application. If you are using any external Node.js modules, the entire `node_modules` subdirectory structure must be binplaced to the `bin` folder of you web application, and deployed that way to the server. \n\n### How to: debug Node.js code running in a CLR application\n\nThe `EDGE_NODE_PARAMS` environment variable allows you to specify any options that are normally passed via command line to the node executable. This includes the `--debug` options necessary to use [node-inspector](https://github.com/node-inspector/node-inspector) to debug Node.js code. \n\n### Building Edge.js NuGet package\n\n**Note** This mechanism requires hardening, expect the road ahead to be bumpy. \n\nThese are unstructions for building the Edge.js NuGet package on Windows. The package will support running apps in both x86 and x64 architectures using a selected version of Node.js. The resulting NuGet package is all-inclusive with the only dependency being .NET 4.5. \n\nPreprequisties:\n\n* Visual Studio 2015   \n* Node.js (tested with v8.2.1)  \n* Python 2.7.x  \n* node-gyp (tested with 3.6.1)  \n\nTo buid the NuGet package, open the Visual Studio 2013 Developer Command Prompt and call:\n\n```\ntools\\build_double.bat 8.2.1\n```\n\n(you can substitite another version of Node.js).\n\nThe script takes several minutes to complete and does the following:\n\n* builds a few helper tools in C#  \n* downloads sources of the selected Node.js version  \n* downloads nuget.exe from http://nuget.org  \n* builds Node.js shared library for the x86 and x64 flavor\n* builds Edge.js module for the x86 and x64 flavor\n* builds managed EdgeJs.dll library that bootstraps running Node.js in a CLR process and provides the Edge.Func programming model  \n* packs everything into a NuGet package\n\nIf everything goes well, the resulting NuGet package is located in the `tools\\build\\nuget` directory. \n\n### Running tests of scripting Node.js in C#\n\nThere are functional tests in `test\\double\\double_test` and stress tests in `test\\double\\double_stress`. Before you can compile these tests, you must register the location of the built NuGet package as a local NuGet feed through the NuGet configuration manager in Visual Studio. \n\nAfter you have compiled the function tests, the best way to run them is from the command line:\n\n```\nC:\\projects\\edge\\test\\double\\double_tests\\bin\\Release\u003e mstest /testcontainer:double_test.dll /noisolation\n```\n\nAfter you have compiled the stress tests, simply launch the executable, attach resource monitor to the process, and leave it running to observe stability:\n\n```\nC:\\projects\\edge\\test\\double\\double_stress\\bin\\Release\u003e double_stress.exe\n```\n\n## Use cases and other resources\n\n[Accessing MS SQL from Node.js via Edge.js](https://blog.codeship.com/node-js-sql-server-edge-js/) by [David Neal](https://twitter.com/reverentgeek)  \n[Using ASP.NET and React on the server via Edge.js](http://navigation4asp.net/2015/10/13/progressive-enhancement-enhanced/) by [Graham Mendick](https://twitter.com/grahammendick)  \n\n## Contribution and derived work\n\nI do welcome contributions via pull request and derived work. \n\nThe edge module is intended to remain a very small component with core functionality that supports interop between .NET and Node.js. Domain specific functionality (e.g. access to SQL, writing to ETW, writing connect middleware in .NET) should be implemented as separate modules with a dependency on edge. When you have a notable derived work, I would love to know about it to include a pointer here.  \n\n## More\n\nIssues? Feedback? You [know what to do](https://github.com/tjanczuk/edge/issues/new). Pull requests welcome.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjanczuk%2Fedge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftjanczuk%2Fedge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjanczuk%2Fedge/lists"}