Denim
Node 💖 Nim = Denim! Build powerful NodeJS / BunJS addons with Nim language via Node API (NAPI)
Install / Use
/learn @openpeeps/DenimREADME
😍 Key Features
- [x] CLI build via Nim +
node-gypor CMake.js (faster) - [ ] CLI publish to NPM
- [x] Low-level API
- [x] High-level API
- [x] Open Source |
MITLicense - [x] Written in 👑 Nim language
Requirements
- Nim (latest / via
choosenim) - Node (latest) and
node-gypor 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
- 🐛 Found a bug? Create a new Issue
- 👋 Wanna help? Fork it!
- 😎 Get €20 in cloud credits from Hetzner
🎩 License
Denim | MIT license. Made by Humans from OpenPeeps<br> Thanks to Andrew Breidenbach and Andrei Rosca for their work.<br>
Copyright © 2023 OpenPeeps & Contributors — All rights reserved.
Related Skills
node-connect
342.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
342.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.7kCommit, push, and open a PR
