hello-lights 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,13 +10,37 @@ Works with a [Cleware USB traffic light](http://www.cleware.info/data/usbtischam
10
10
 
11
11
  ## Install
12
12
 
13
+ ### As a CLI (global)
14
+
15
+ ```sh
16
+ $ npm install -g hello-lights
17
+ ```
18
+
19
+ ### As a library
20
+
13
21
  ```sh
14
22
  $ npm install hello-lights --save
15
23
  ```
16
24
 
17
25
  ## Usage
18
26
 
19
- Issue commands to control a connected traffic light:
27
+ ### CLI
28
+
29
+ Install globally and run `hello-lights` from the command line:
30
+
31
+ ```sh
32
+ $ hello-lights exec bounce 300 # execute a command
33
+ $ hello-lights exec-file ./cmds.clj # execute commands from a file
34
+ $ hello-lights repl # start an interactive REPL
35
+ $ hello-lights serve # start the HTTP server on port 9000
36
+ $ hello-lights serve --port 3000 # start the HTTP server on a custom port
37
+ ```
38
+
39
+ Use `--help` for the full list of options, including `--serial-num` to target a specific device and `--selector multi` to control multiple traffic lights at once.
40
+
41
+ ### Library
42
+
43
+ Use `hello-lights` as a library in your Node.js project:
20
44
 
21
45
  ```js
22
46
  const {Commander} = require('hello-lights');
@@ -75,6 +99,79 @@ $ npm run cli -- serve --port 3000 # start the HTTP server on a custom port
75
99
 
76
100
  Use `--help` for the full list of options, including `--serial-num` to target a specific device and `--selector multi` to control multiple traffic lights at once.
77
101
 
102
+ ## HTTP Server REST API
103
+
104
+ The `serve` command starts an HTTP server that exposes the Commander interface as a REST API. By default it listens on port 9000.
105
+
106
+ | Endpoint | Method | Body | Response |
107
+ |---|---|---|---|
108
+ | `/run` | POST | Command string (plain text) | 202 Accepted |
109
+ | `/run?reset=true` | POST | Command string (plain text) | 202 Accepted (resets lights first) |
110
+ | `/cancel` | POST | — | 200 OK |
111
+ | `/definitions` | POST | Definition string (plain text) | 202 Accepted |
112
+ | `/commands` | GET | — | 200 + JSON array of command names |
113
+ | `/commands/:name` | GET | — | 200 + help text (`text/x-ansi`) or 404 |
114
+ | `/info` | GET | — | 200 + JSON array of `{ serialNum, status }` |
115
+
116
+ Examples:
117
+
118
+ ```sh
119
+ $ curl -X POST http://localhost:9000/run -d 'blink 3 green 300'
120
+ $ curl -X POST http://localhost:9000/run?reset=true -d 'twinkle red 400'
121
+ $ curl -X POST http://localhost:9000/cancel
122
+ $ curl -X POST http://localhost:9000/definitions -d '(def foo (blink 1 green 300))'
123
+ $ curl http://localhost:9000/commands
124
+ $ curl http://localhost:9000/commands/turn
125
+ $ curl http://localhost:9000/info
126
+ ```
127
+
128
+ The server also serves a browser demo at the root URL (`/`).
129
+
130
+ ## Running as a Linux Service
131
+
132
+ You can set up `hello-lights serve` to run automatically as a systemd user service on Linux.
133
+
134
+ Create the service file at `~/.config/systemd/user/hello-lights.service`:
135
+
136
+ ```ini
137
+ [Unit]
138
+ Description=Hello Lights Server
139
+ After=network.target
140
+
141
+ [Service]
142
+ Type=simple
143
+ Environment=PATH=/path/to/node/bin:/usr/bin:/bin
144
+ ExecStart=/path/to/node/bin/hello-lights serve
145
+ Restart=on-failure
146
+ RestartSec=5
147
+
148
+ [Install]
149
+ WantedBy=default.target
150
+ ```
151
+
152
+ Replace `/path/to/node/bin` with the directory containing your `node` and `hello-lights` binaries (e.g. `~/.nvm/versions/node/v24.13.1/bin`). The `Environment=PATH=...` line is needed because systemd doesn't load your shell profile, so tools installed via nvm won't be found otherwise.
153
+
154
+ Then enable and start the service:
155
+
156
+ ```sh
157
+ $ systemctl --user daemon-reload
158
+ $ systemctl --user enable hello-lights # start automatically on login
159
+ $ systemctl --user start hello-lights # start now
160
+ ```
161
+
162
+ To start the service on boot (without needing to log in), enable lingering for your user:
163
+
164
+ ```sh
165
+ $ sudo loginctl enable-linger $USER
166
+ ```
167
+
168
+ Check status and logs:
169
+
170
+ ```sh
171
+ $ systemctl --user status hello-lights
172
+ $ journalctl --user -u hello-lights -f # follow logs
173
+ ```
174
+
78
175
  ## CI
79
176
 
80
177
  The CI workflow runs on every push and pull request to `master`. It has three jobs:
@@ -10,14 +10,44 @@ function createApp(commander) {
10
10
  const app = express();
11
11
 
12
12
  app.use(express.static(path.join(__dirname, 'public')));
13
+ app.use(express.text({type: '*/*'}));
14
+
13
15
  app.post('/run', (req, res) => {
14
- let commandStr = '';
15
- req.on('data', data => commandStr += data);
16
- req.on('end', () => {
17
- commander.run(commandStr);
18
- res.statusCode = 202; // accepted
19
- res.end();
20
- });
16
+ let reset = req.query.reset === 'true';
17
+ commander.run(req.body || '', reset);
18
+ res.sendStatus(202);
19
+ });
20
+
21
+ app.post('/cancel', (req, res) => {
22
+ commander.cancel();
23
+ res.sendStatus(200);
24
+ });
25
+
26
+ app.post('/definitions', (req, res) => {
27
+ commander.runDefinitions(req.body || '');
28
+ res.sendStatus(202);
29
+ });
30
+
31
+ app.get('/commands', (req, res) => {
32
+ res.json(commander.commandNames);
33
+ });
34
+
35
+ app.get('/commands/:name', (req, res) => {
36
+ let command = commander.interpreter.lookup(req.params.name);
37
+ if (!command) {
38
+ res.status(404).send(`Command not found: "${req.params.name}"`);
39
+ return;
40
+ }
41
+ let helpText = commander.formatter.format(command.meta);
42
+ res.type('text/x-ansi').send(helpText);
43
+ });
44
+
45
+ app.get('/info', (req, res) => {
46
+ if (commander.manager) {
47
+ res.json(commander.manager.info());
48
+ } else {
49
+ res.json([]);
50
+ }
21
51
  });
22
52
 
23
53
  return app;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hello-lights",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Commands to control a traffic light",
5
5
  "main": "index.js",
6
6
  "bin": {