896b71fc62
Versions bumped to 0.1.5 in every authoritative location:
- workspace `Cargo.toml` (`[workspace.package].version`, the
`wickra-core` path dependency pin).
- `bindings/python/pyproject.toml`.
- `bindings/node/package.json` (main + all six `optionalDependencies`
pins).
- All six per-platform `bindings/node/npm/<target>/package.json`
templates.
CHANGELOG: the accumulated `[Unreleased]` block is promoted to
`[0.1.5] - TBD` (date left for the user to set at tag time); the new
`[Unreleased]` header sits empty above it; the compare link table is
extended with `[0.1.5]: …compare/v0.1.4...v0.1.5` and the
`[Unreleased]` link is repointed to `…compare/v0.1.5...HEAD`.
Wiki refresh for 0.1.5 (R20 + Z2):
- `Home.md` version pin table updated; the Quickstart-Node hint replaces
the "spam filter holding back Windows" caveat with "0.1.5 is the
first release in which `npm install wickra` works end-to-end on
Windows" (npm Support released the name on 2026-05-22).
- `Quickstart-Node.md`'s Windows caveat is rewritten to explain the
history (`0.1.1`–`0.1.4` of `wickra-win32-x64-msvc` are burned) and
the resolution (0.1.5+ installs cleanly).
- `Quickstart-Rust.md` version mention bumped.
- `Warmup-Periods.md` note bumped + corrected: every Node and WASM
class — single- and multi-output — now exposes `warmupPeriod()` after
R3 (this branch), not only the single-output ones.
`release.yml` `publish_dir` no longer silently swallows a
second-attempt platform-package publish failure with a `::warning::`
and `return 0`. A real failure (after the existing 30s retry) now
emits an `::error::` and fails the job. The original mask is exactly
what allowed the `wickra-win32-x64-msvc@0.1.1–0.1.4` spam-filter
rejections to land four times in a row without anyone noticing (audit
finding R20). Failing loud means the next regression of this shape is
caught at the release run, not by a Windows user trying to
`require('wickra')`.
This commit does NOT push, tag, or trigger a release — the user
publishes the 0.1.5 tag themselves once the manual npm-republish
smoke test confirms `wickra-win32-x64-msvc@0.1.5` accepts publish on
the freshly-released name.
175 lines
6.0 KiB
Markdown
175 lines
6.0 KiB
Markdown
# Quickstart: Node
|
||
|
||
A five-minute tour of the Wickra Node.js binding. The binding is generated by
|
||
[napi-rs](https://napi.rs/), so it's a native addon — no WebAssembly, no
|
||
slow JS reimplementation.
|
||
|
||
## Install
|
||
|
||
```bash
|
||
npm install wickra
|
||
```
|
||
|
||
> **Windows install (0.1.5+).** Earlier patch releases were blocked on
|
||
> Windows x64 because the platform-specific sub-package
|
||
> `wickra-win32-x64-msvc` was held back by npm's automated spam filter, so
|
||
> `require('wickra')` threw `Error: Cannot find module
|
||
> 'wickra-win32-x64-msvc'` after a successful `npm install`. npm Support
|
||
> released the name on 2026-05-22; 0.1.5 is the first version in which
|
||
> Windows x64 installs cleanly end-to-end (version numbers `0.1.1`–`0.1.4`
|
||
> of that sub-package remain burned and cannot be republished — see the
|
||
> npm registry page for `wickra-win32-x64-msvc`). Linux x64, Linux arm64
|
||
> and macOS (x64 + arm64) were unaffected throughout.
|
||
|
||
## A first run
|
||
|
||
```javascript
|
||
const wickra = require('wickra');
|
||
|
||
console.log('wickra', wickra.version());
|
||
|
||
// Simple moving average over a fixed window.
|
||
const sma = new wickra.SMA(3);
|
||
console.log(sma.batch([2, 4, 6, 8, 10]));
|
||
// -> [ NaN, NaN, 4, 6, 8 ]
|
||
```
|
||
|
||
Two things to notice:
|
||
|
||
1. The `batch` return type is a regular JavaScript `Array<number>`. Warmup
|
||
slots are `NaN`, not `null` or `undefined`, so the array is
|
||
`Number.isFinite`-checkable in one pass.
|
||
2. `new wickra.SMA(0)` does **not** throw. Constructors in the Node binding
|
||
currently cannot raise errors from JS (a napi-rs 2.16 limitation), so
|
||
pathological values like `period = 0` are clamped to the smallest valid
|
||
window. This is exactly the behaviour pinned by
|
||
`bindings/node/__tests__/smoke.test.js` ("zero period is clamped to a
|
||
valid window").
|
||
|
||
## Streaming
|
||
|
||
```javascript
|
||
const wickra = require('wickra');
|
||
|
||
const sma = new wickra.SMA(3);
|
||
for (const price of [2, 4, 6, 8, 10]) {
|
||
const value = sma.update(price);
|
||
console.log('update', price, '->', value);
|
||
}
|
||
```
|
||
|
||
Output:
|
||
|
||
```
|
||
update 2 -> null
|
||
update 4 -> null
|
||
update 6 -> 4
|
||
update 8 -> 6
|
||
update 10 -> 8
|
||
```
|
||
|
||
`update` returns either a JavaScript `number` or `null` while the indicator
|
||
is still warming up. (Compare with `batch`, where warmup slots are `NaN`.
|
||
The asymmetry exists because the streaming API surfaces "no value yet"
|
||
through the JS type system, whereas the batch result is shaped as a numeric
|
||
array for downstream numeric code.)
|
||
|
||
## MACD: streaming and batch
|
||
|
||
`MACD` is the canonical multi-output indicator. The Node API surfaces this in
|
||
two shapes:
|
||
|
||
- `update(price)` returns either `null` (during warmup) or
|
||
`{ macd, signal, histogram }`.
|
||
- `batch(prices)` returns a **flat** `Array<number>` of length `prices.length * 3`,
|
||
laid out as `[macd_0, signal_0, hist_0, macd_1, signal_1, hist_1, ...]`,
|
||
with each warmup row written as three `NaN`s.
|
||
|
||
Streaming form:
|
||
|
||
```javascript
|
||
const wickra = require('wickra');
|
||
|
||
const macd = new wickra.MACD(12, 26, 9);
|
||
let last = null;
|
||
for (let i = 0; i < 40; i++) {
|
||
last = macd.update(100 + i * 0.5);
|
||
}
|
||
console.log(last);
|
||
// -> { macd: 3.5, signal: 3.500000000000001, histogram: -8.881784197001252e-16 }
|
||
```
|
||
|
||
Batch form (note the flat layout):
|
||
|
||
```javascript
|
||
const wickra = require('wickra');
|
||
|
||
const prices = Array.from({ length: 40 }, (_, i) => 100 + i * 0.5);
|
||
const macd = new wickra.MACD(12, 26, 9);
|
||
const flat = macd.batch(prices);
|
||
|
||
console.log('total values:', flat.length); // -> 120 (= 40 * 3)
|
||
console.log('row 33 :', flat.slice(99, 102)); // -> [ 3.5, 3.5, 0 ]
|
||
console.log('row 39 :', flat.slice(117, 120)); // -> [ 3.5, 3.5000000..., -8.88e-16 ]
|
||
|
||
// Reshape into 3-tuples if you want:
|
||
const rows = [];
|
||
for (let i = 0; i < flat.length; i += 3) {
|
||
rows.push({ macd: flat[i], signal: flat[i + 1], histogram: flat[i + 2] });
|
||
}
|
||
```
|
||
|
||
`MACD(12, 26, 9)` emits its first non-NaN row at index 33 because the
|
||
underlying Rust `warmup_period()` is `slow + signal − 1 = 34` (the first
|
||
ready row is `warmup_period - 1` in 0-indexed terms).
|
||
|
||
## API surface
|
||
|
||
The complete TypeScript definitions live at
|
||
`bindings/node/index.d.ts`. Every indicator class exposes some subset of:
|
||
|
||
| Member | Notes |
|
||
|---------------------------|------------------------------------------------------------------------|
|
||
| `constructor(...)` | Pathological values are clamped, not thrown. |
|
||
| `update(...)` | Returns the indicator output or `null` during warmup. |
|
||
| `batch(...)` | Single-output: flat `Array<number>` with `NaN` warmup.<br>Multi-output: flat interleaved `Array<number>`. |
|
||
| `reset()` | Returns to a freshly-constructed state. |
|
||
| `isReady()` | `true` once the first value has been emitted. |
|
||
| `warmupPeriod()` | Present on single-output indicators (SMA, EMA, WMA, RSI, ...). Not exposed on every multi-output class — check `index.d.ts`. |
|
||
|
||
A complete reference run lives in `bindings/node/__tests__/smoke.test.js`:
|
||
|
||
```bash
|
||
cd bindings/node
|
||
npm install
|
||
npm run build # only needed if you cloned the repo (Windows: see above)
|
||
npm test
|
||
```
|
||
|
||
## Building from source (Windows workaround)
|
||
|
||
If you are on Windows x64 and want to use Wickra today, build the binding
|
||
locally from the repository:
|
||
|
||
```bash
|
||
git clone https://github.com/kingchenc/wickra
|
||
cd wickra/bindings/node
|
||
npm install
|
||
npm run build # requires a Rust toolchain (rustup) on PATH
|
||
npm test
|
||
```
|
||
|
||
`npm run build` produces `wickra.win32-x64-msvc.node` in the binding
|
||
directory; the platform loader in `index.js` then picks it up before falling
|
||
through to the npm sub-package and the install just works.
|
||
|
||
## See also
|
||
|
||
- [Quickstart: Python](Quickstart-Python.md) — sibling binding with NumPy
|
||
shapes.
|
||
- [Streaming vs Batch](Streaming-vs-Batch.md) — why `update` is the primary
|
||
entry point, not `batch`.
|
||
- [Warmup Periods](Warmup-Periods.md) — exact `warmup_period()` for every
|
||
indicator.
|
||
- Source: <https://github.com/kingchenc/wickra>
|