{"id":13528044,"url":"https://github.com/andi23rosca/napi-nim","last_synced_at":"2025-07-14T14:33:20.111Z","repository":{"id":52527017,"uuid":"329265886","full_name":"andi23rosca/napi-nim","owner":"andi23rosca","description":"Write NodeJS native extensions in Nim","archived":false,"fork":false,"pushed_at":"2021-02-02T16:55:55.000Z","size":51,"stargazers_count":33,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-02T13:34:11.294Z","etag":null,"topics":["n-api","nim","nim-lang","nim-language","node-addon","node-js"],"latest_commit_sha":null,"homepage":"","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andi23rosca.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-13T10:04:48.000Z","updated_at":"2024-05-29T17:48:40.000Z","dependencies_parsed_at":"2022-09-26T18:22:03.206Z","dependency_job_id":null,"html_url":"https://github.com/andi23rosca/napi-nim","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Fnapi-nim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Fnapi-nim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Fnapi-nim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Fnapi-nim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andi23rosca","download_url":"https://codeload.github.com/andi23rosca/napi-nim/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225869908,"owners_count":17537169,"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":["n-api","nim","nim-lang","nim-language","node-addon","node-js"],"created_at":"2024-08-01T06:02:11.067Z","updated_at":"2024-11-23T00:14:15.045Z","avatar_url":"https://github.com/andi23rosca.png","language":"Nim","readme":"# Write NodeJS native extensions in Nim\nIf you don't like the verbosity of C code and feel that C++ is too complex, then try to improve the performance of your NodeJS apps with `napi-nim`.\n\nThe new `n-api` which is now part of NodeJS lets you interface with JavaScript code from any language that supports the C ABI. [Nim](https://nim-lang.org/) is a language that values efficiency above all else, but provides a lot of high level constructs and niceties for developer productivity, making it a very suitable choice for writing performant add-ons to your NodeJS code.\n\n- [Write NodeJS native extensions in Nim](#write-nodejs-native-extensions-in-nim)\n  * [Prerequisites](#prerequisites)\n  * [Installation](#installation)\n  * [Basic usage](#basic-usage)\n  * [API](#api)\n    + [Defining a module](#defining-a-module)\n    + [Registering module exports](#registering-module-exports)\n    + [Converting between `napi_value` and Nim types](#converting-between--napi-value--and-nim-types)\n      - [napi_value -\u003e Nim](#napi-value----nim)\n      - [Nim -\u003e napi_value](#nim----napi-value)\n    + [Function with arguments](#function-with-arguments)\n  * [Low level API](#low-level-api)\n  * [Roadmap](#roadmap)\n\n## Prerequisites\nSince we're building a NodeJS extension in Nim you should install both from:\n- NodeJS:  https://nodejs.org/en/\n- Nim:     https://nim-lang.org/install.html\n\nMake sure you have `node-gyp` installed globally by doing \n```\nnpm i -g node-gyp\n```\n\n## Installation\nInstall `napi-nim` globally\n```\nnpm i -g napi-nim\n```\n\n\n## Basic usage\nTo get started run the following command:\n```\nnapi-nim init hello-world\n```\nIf it didn't work one of the following things might be the cause:\n- The location in which you ran the command should not contain a folder named `hello-world`.\n- You need an internet connection when running the command since it does an `npm install` of the dependencies of the project for you.\n\nIf everything went fine the output of the command should say:\n```\nDONE Project ready.\n\nTest that it works by building and running:\n  cd hello-world\n  napi-nim main.nim\n  node --napi-modules index.js\n```\n\n`napi-nim` has now created a new folder in the directory in which you ran the command called `hello-world`.\nThe folder contains all of the necessary dependencies to start working on your Nim add-on.\n\nNext up, follow the next steps outlined in the output:\n\n1. `cd hello-world` to navigate to the project directory.\n2. `napi-nim main.nim` will compile the Nim file to a C file, and then use `node-gyp` to build the final NodeJS add-on.\n3. `node --napi-modules index.js` will run the JS file. the `--napi-modules` flag ensures that node knows to look for a n-api add-on.\n\n\nRunning the last command should output `Hello world` in the command line.\n\n## API\n`napi-nim` provides a high level API over the classic `n-api`.\nThis readme might be incomplete, to see all available high level APIs see `napi/napibindings.nim`.\n\n### Defining a module\nThe `init` macro will help you define a module initialization proc.\nThe proc definition following it should accept an argument of the type `Module`.\n```nim\ninit proc(module: Module) =\n```\n\n### Registering module exports\nFor exporting properties and functions there are 2 separate templates to use.\n```nim\ninit proc(module: Module) =\n  # equivalent to module.exports.hello = function () ....\n  module.registerFn(0, \"hello\"):\n    echo \"hello world\"\n\n  # equivalent to module.exports.num = 23\n  module.register(\"num\", 23)\n```\n\n### Converting between `napi_value` and Nim types\nThe node api defines the type `napi_value` which can take the value of the JS types such as number, string, object, etc.\nFor you to be able to translate between JS types and Nim types and vice-versa, `napi-nim` exposes a few helpers.\n\n#### napi_value -\u003e Nim\n```nim\njsString.getStr # to get the string equivalent\njsNumber.getInt # to convert a js number to int, getInt32/64 and getFloat32/64 are also available\n```\nSee the rest in `napi/napibindings.nim`.\n\n#### Nim -\u003e napi_value\nUse the `%*` operator to convert Nim types to JS.\nMake sure there's an empty space between the operator and the definition.\n```nim\nlet obj = %* {\"someProp\": 23}\n```\n\n### Function with arguments\nWhen registering a function, the first argument should be the number of arguments you expect for it.\n\nYou can get the arguments from the `args` array that is made available by `registerFn`. Keep in mind the arguments you receive will be JS types so you have to convert to Nim types if you want to use them.\n```nim\nmodule.registerFn(1, \"hello\"):\n  let toGreet = args[0].getStr; # Getting the first and only argument as a string\n  echo \"Hello \" \u0026 toGreet\n```\n\n## Low level API\nFor the things that the high level API might not support yet there's the option to use the lower level functions and types provided\nby the node_api header.\nYou can see in the rest of the files in `napi` like `napi/jsNativeApi.nim` the wrappers which are just Nim type definitions equivalent to the header files from the n-api.\n\nCheck the original docs here: https://nodejs.org/api/n-api.html#n_api_basic_n_api_data_types\n\nOne function to mention is `assessStatus`. It checks that a low level api function returns a success, and if not throws an error.\nYou could also use `discard` instead to ignore the returned status, but it's not recommended.\n\n```nim\nvar\n  obj: napi_value\n  value: napi_value\nassessStatus module.env.napi_create_string_utf8(\"level\", 5, addr value) # create a js string and put it in value\nassessStatus module.env.napi_create_object(addr lowObj); # create a js object and put it in obj\nassessStatus module.env.napi_set_named_property(obj, \"low\", value) # Set the property low to be the value string\n```\n\n\n\n## Roadmap\nThe project is still new and unfinished.\nIt can already be used to create add-ons but it is missing the following features/nice-to-haves:\n\n- [ ] Examples folder to show how to use.\n- [ ] In-depth explanation of the code-base.\n- [ ] Collaboration guide.\n- [ ] `napi-nim init` should include bundling and publishing an add-on out of the box. (Right now you have to figure it out yourself 😕)\n\nCredit to https://github.com/AjBreidenbach/napibindings which this project is heavily based on. I opted for a new repository instead of PR since it seems that the project is completely abandoned.\n","funding_links":[],"categories":["Nim"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandi23rosca%2Fnapi-nim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandi23rosca%2Fnapi-nim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandi23rosca%2Fnapi-nim/lists"}