Skip to content

Node πŸ’– Nim = Denim! Build powerful NodeJS / BunJS addons with Nim language via Node API (NAPI)

License

Notifications You must be signed in to change notification settings

openpeeps/denim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

b4b6bc7 Β· Dec 31, 2024
Dec 31, 2024
Dec 31, 2024
Apr 19, 2024
Jun 29, 2023
Jul 2, 2021
Oct 9, 2023
May 20, 2024

Repository files navigation

Denim
Denim - Native NodeJS/BunJS addons powered by Nim
πŸ‘‘ Written in Nim language

nimble install denim

API reference
Github Actions Github Actions

😍 Key Features

  • CLI build via Nim + node-gyp or CMake.js (faster)
  • CLI publish to NPM
  • Low-level API
  • High-level API
  • Open Source | MIT License
  • Written in πŸ‘‘ Nim language

Requirements

  • Nim (latest / via choosenim)
  • Node (latest) and node-gyp or CMake.js

CLI

Denim is a hybrid package, you can use it as a CLI for compiling Nim code to .node addon via Nim + NodeGYP and as a library for importing NAPI bindings.

Simply run denim -h

DENIM πŸ”₯ Native Node/BunJS addons powered by Nim

  build <entry> <links> --cmake --yes --verbose          Build Nim project to a native NodeJS addon
  publish                                                Publish addon to NPM (requires npm cli)

Use Denim as a Nimble task:

task napi, "Build a .node addon":
  exec "denim build src/myprogram.nim"

Want to pass custom flags to Nim Compiler? Create a .nims file:

when defined napibuild:
  # add some flags

Note Check fully-working examples in /tests

Defining a module

Use init to define module initialization.

when defined napibuild:
  # optionally, you can use `napibuild` flag to wrap your code
  # this flag is set when compiling via `denim build src/myprogram.nim` 
  import denim # import NAPI bindings 
  init proc(module: Module) =
    # registering properties and functions here
    # this is similar with javascript `module.exports`
elif isMainModule:
  echo "just a normal nim program"

Nim Type to NapiValueType

Use low-level API to convert Nim values to napi_value (NapiValueType). Use assert to check if a low-level function returns a success or failure. Currently, the following status codes are supported

import denim
init proc(module: Module) =
  module.registerFn(0, "awesome"):
    var str2napi: napi_value
    var str = "Nim is awesome!"
    assert Env.napi_create_string_utf8(str, str.len.csize_t, str2napi.addr) 
    return str2napi

Alternatively, use %* to auto-convert Nim values to NapiValueType.

let
  a: napi_value = %* "Hey"
  b: napi_value = %* true
assert a.kind == napi_string
assert b.kind == napi_boolean

Exports

Since v0.1.5, you can use {.export_napi.} pragma to export functions and object properties.

import denim

init proc(module: Module): # the name `module` is required
  proc hello(name: string) {.export_napi} =
    ## A simple function from Nim
    return %*("Hello, " & args.get("name").getStr)

  var awesome {.export_napi.} = "Nim is Awesome!"

Calling a function/property from Node/Bun

const app = require('myaddon.node')
console.log(app.hello("World!"))       // Hello, World!
console.log(app.awesome)               // Nim is Awesome!

Built-in type checker

app.hello()
/*
 * A simple function from Nim
 * @param {string} name
 * @return {string}
 */
Type mismatch parameter: `name`. Got `undefined`, expected `string`

Real-World Examples

  • Tim Engine β€” A template engine. GitHub
  • Bro β€” A fast stylesheet language, alternative to SassC, DartSass. GitHub
  • HappyX β€” Macro-oriented asynchronous web-framework written in Nim. GitHub

Todo

  • Option to link external C Headers/libraries
  • Extend High-level API with compile-time functionality.

❀ Contributions & Support

🎩 License

Denim | MIT license. Made by Humans from OpenPeeps
Thanks to Andrew Breidenbach and Andrei Rosca for their work.

Copyright Β© 2023 OpenPeeps & Contributors β€” All rights reserved.