I do want to make two things clear though. First, placing JS Scripting libraries anywhere except the automation/js/node_modules is not officially supported and not guaranteed to work forever. And since it’s not supported, any such change would not be announced or treated like a breaking change. This may be slightly simpler now, but it could set you up for a lot of extra work later on.
Secondly, you only have to do the npm thing once. I don’t mean once per change, or once per file, I mean once for all time.
When you have the module installed and configured and initialized correctly, you can add, remove, and modify the library in place as much as you want.
And it’s not really that complicated. You can copy the following to a shell script and run it once, and you are done with the npm stuff forever. You’ll pass the name you want to use for your library as the first argument.
This assumes you are already logged in to your openHAB machine, it’s an installed openHAB, and npm is installed. All of this will be true for an openHABian install. If your OH isn’t installed, change line 21 to the path to your automation/js folder.
createLibrary.sh
#!/bin/bash
# initialize the library
mkdir /tmp/$1
cd /tmp/$1
npm init
echo -e "var someProperty = 'Hello world!'\n" \
"function someFunction() {\n" \
" console.log('Hello from your personal library!');\n" \
"}\n\n" \
"module.exports = {\n" \
" someProperty,\n" \
" someFunction\n" \
"};" > index.js
# tar the library
npm pack
# install the library
cd /etc/openhab/automation/js
npm install /tmp/$1/$1-1.0.0.tgz
Or you can run these steps manually. index.js is just a copy of the stub from the docs.
When you run this script you’ll be asked a bunch of questions. You can just keep hitting enter until the script completes or provide your own answers. Just do not change the library name nor the version because both of these are hard coded in the script for the next steps.
Example run (I use starship, so my prompt didn’t come over very well in the copy and paste):
argus rich ~ 08:30
./createLibrary.sh test
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (test)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /tmp/test/package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
npm notice
npm notice 📦 test@1.0.0
npm notice === Tarball Contents ===
npm notice 175B index.js
npm notice 200B package.json
npm notice === Tarball Details ===
npm notice name: test
npm notice version: 1.0.0
npm notice filename: test-1.0.0.tgz
npm notice package size: 361 B
npm notice unpacked size: 375 B
npm notice shasum: 2f11486f0e2e2d088a1b7759d904da2a12698832
npm notice integrity: sha512-wr/klz8z+xTIn[...]vaHH7OCleJ/ZQ==
npm notice total files: 2
npm notice
test-1.0.0.tgz
added 1 package, and audited 8 packages in 539ms
found 0 vulnerabilities
argus rich ~ 08:30
ls /srv/openhab/conf/automation/js/node_modules/
'@js-joda'/ openhab_rules_tools/ rlk_personal/ test/
argus rich ~ 08:30
cat /srv/openhab/conf/automation/js/node_modules/test/index.js
var someProperty = 'Hello world!'
function someFunction() {
console.log('Hello from your personal library!');
}
module.exports = {
someProperty,
someFunction
};
From this point on I can make any changes to any file in automation/js/node_modules/test and they will be picked up and won’t be removed if I install or update the other libraries. If “Enable dependency tracking” is enabled (it’s enabled by default) any change to a library will cause the rules that require that library to reload and pick up the changes automatically.
index.js is the “entrypoint” for the library. You can put all your stuff in there if you have a small library, or you can modify it to just export your other files.
For example, my library as two files, alerting.js and utils.js. My index.js looks like:
module.exports = {
get alerting() { return require('./alerting.js') },
get utils() { return require('./utils.js') }
}
and I use them in a rule using (this is a script condition):
const {alerting} = require('rlk_personal');
return !alerting.isNight();
isNight() is a function exported in alerting.js which returns true when it’s night. What is considered night differs depending on a number of factors like the type of day.
When I change alerting.js, all rules that require alerting will be reloaded. But those rules that only require utils will not because utils didn’t change.