Compare commits

...
1 Commits
Author SHA1 Message Date
kingchenc 371d338a8b Release 0.1.1: fix Node publish + bump everything
v0.1.0 reached crates.io, PyPI, and the wickra-wasm npm package, but
the wickra Node binding never published because the workflow called
`napi create-npm-dirs` (plural). The actual napi CLI command is
`create-npm-dir` (singular, per target).

Changes that make the next tag's release actually finish:

- workflow: replace the broken step with a loop that runs
  `napi create-npm-dir -t <triple>` for each of our four build targets.

- workflow: every registry publish step now treats "version already
  uploaded" as success. That makes re-runs (and partial-failure
  recoveries) safe instead of failing the whole job.

- bindings/node/package.json: trim the napi.triples list to the four
  platforms we actually build (linux-x64-gnu, darwin-x64, darwin-arm64,
  win32-x64-msvc). The previous defaults+9-extras configuration would
  have made napi prepublish expect platform packages we never produced.

- bindings/node/index.js: switch from local-only binary lookup to the
  proper napi loader that tries the local `.node` file first and falls
  back to the per-platform npm subpackage that's installed as an
  optional dependency in production.

- Versions across all four published packages bumped to 0.1.1 so the
  Node binding can publish for the first time alongside refreshed
  cargo/pypi/wasm artefacts.
2026-05-21 21:06:42 +02:00
6 changed files with 82 additions and 50 deletions
+27 -10
View File
@@ -20,24 +20,35 @@ jobs:
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
- name: Publish wickra-core # Idempotent publishing: if the version is already on crates.io we
run: cargo publish -p wickra-core --token "$CARGO_REGISTRY_TOKEN" # treat that as success so re-runs of the workflow don't fail.
- name: Publish wickra-core (idempotent)
run: |
out=$(cargo publish -p wickra-core --token "$CARGO_REGISTRY_TOKEN" 2>&1) && echo "$out" \
|| (echo "$out" | grep -q "already uploaded\|already exists" && echo "skip: already published" \
|| (echo "$out"; exit 1))
env: env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Wait for crates.io index to refresh - name: Wait for crates.io index to refresh
run: sleep 45 run: sleep 45
- name: Publish wickra-data - name: Publish wickra-data (idempotent)
run: cargo publish -p wickra-data --token "$CARGO_REGISTRY_TOKEN" run: |
out=$(cargo publish -p wickra-data --token "$CARGO_REGISTRY_TOKEN" 2>&1) && echo "$out" \
|| (echo "$out" | grep -q "already uploaded\|already exists" && echo "skip: already published" \
|| (echo "$out"; exit 1))
env: env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Wait for crates.io index to refresh - name: Wait for crates.io index to refresh
run: sleep 45 run: sleep 45
- name: Publish wickra - name: Publish wickra (idempotent)
run: cargo publish -p wickra --token "$CARGO_REGISTRY_TOKEN" run: |
out=$(cargo publish -p wickra --token "$CARGO_REGISTRY_TOKEN" 2>&1) && echo "$out" \
|| (echo "$out" | grep -q "already uploaded\|already exists" && echo "skip: already published" \
|| (echo "$out"; exit 1))
env: env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
@@ -170,9 +181,12 @@ jobs:
path: bindings/node/artifacts path: bindings/node/artifacts
pattern: bindings-* pattern: bindings-*
- name: Create npm/<platform>/ scaffolding - name: Create npm/<platform>/ scaffolding (one per target)
working-directory: bindings/node working-directory: bindings/node
run: npx napi create-npm-dirs run: |
for t in x86_64-unknown-linux-gnu x86_64-apple-darwin aarch64-apple-darwin x86_64-pc-windows-msvc; do
npx napi create-npm-dir -t "$t" .
done
- name: Move binaries into platform package layout - name: Move binaries into platform package layout
working-directory: bindings/node working-directory: bindings/node
@@ -228,8 +242,11 @@ jobs:
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)); fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
" "
- name: Publish wickra-wasm to npm - name: Publish wickra-wasm to npm (idempotent)
working-directory: bindings/wasm/pkg working-directory: bindings/wasm/pkg
run: npm publish --access public run: |
out=$(npm publish --access public 2>&1) && echo "$out" \
|| (echo "$out" | grep -q "You cannot publish over" && echo "skip: version already on npm" \
|| (echo "$out"; exit 1))
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Generated
+6 -6
View File
@@ -1883,7 +1883,7 @@ dependencies = [
[[package]] [[package]]
name = "wickra" name = "wickra"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"approx", "approx",
"criterion", "criterion",
@@ -1894,7 +1894,7 @@ dependencies = [
[[package]] [[package]]
name = "wickra-core" name = "wickra-core"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"approx", "approx",
"proptest", "proptest",
@@ -1904,7 +1904,7 @@ dependencies = [
[[package]] [[package]]
name = "wickra-data" name = "wickra-data"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"approx", "approx",
"csv", "csv",
@@ -1922,7 +1922,7 @@ dependencies = [
[[package]] [[package]]
name = "wickra-node" name = "wickra-node"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"napi", "napi",
"napi-build", "napi-build",
@@ -1932,7 +1932,7 @@ dependencies = [
[[package]] [[package]]
name = "wickra-python" name = "wickra-python"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"numpy", "numpy",
"pyo3", "pyo3",
@@ -1941,7 +1941,7 @@ dependencies = [
[[package]] [[package]]
name = "wickra-wasm" name = "wickra-wasm"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"console_error_panic_hook", "console_error_panic_hook",
"js-sys", "js-sys",
+2 -2
View File
@@ -11,7 +11,7 @@ members = [
exclude = [] exclude = []
[workspace.package] [workspace.package]
version = "0.1.0" version = "0.1.1"
authors = ["Wickra Contributors"] authors = ["Wickra Contributors"]
edition = "2021" edition = "2021"
rust-version = "1.75" rust-version = "1.75"
@@ -23,7 +23,7 @@ keywords = ["finance", "trading", "indicators", "technical-analysis", "ta"]
categories = ["finance", "mathematics", "science"] categories = ["finance", "mathematics", "science"]
[workspace.dependencies] [workspace.dependencies]
wickra-core = { path = "crates/wickra-core", version = "0.1.0" } wickra-core = { path = "crates/wickra-core", version = "0.1.1" }
thiserror = "2" thiserror = "2"
rayon = "1.10" rayon = "1.10"
+41 -21
View File
@@ -1,30 +1,50 @@
/* eslint-disable */ /* eslint-disable */
/* prettier-ignore */ /* prettier-ignore */
// This loader is generated by `napi build --platform` at publish time. For // Platform-aware loader for the Wickra Node native binding.
// editable development just `require` the local debug binary that napi places //
// at the package root. // In production (after `npm install wickra`) the actual `.node` binary
// lives inside a per-platform subpackage that npm installs as an
// optional dependency — e.g. `wickra-linux-x64-gnu`. In development
// (after `napi build --platform`) the binary sits next to this file.
// We try the local path first and fall back to the subpackage so the
// same loader works in both modes.
const { platform, arch } = process;
const { join } = require('node:path'); const { join } = require('node:path');
const { existsSync } = require('node:fs'); const { existsSync } = require('node:fs');
const { platform, arch } = process;
function loadNative() { const TARGETS = {
// Try precompiled per-platform binary first (published wheels do this). 'linux-x64': 'linux-x64-gnu',
const candidates = [ 'darwin-x64': 'darwin-x64',
`./wickra.${platform}-${arch}.node`, 'darwin-arm64': 'darwin-arm64',
`./wickra.${platform}-${arch}-musl.node`, 'win32-x64': 'win32-x64-msvc',
'./wickra.node', };
];
for (const c of candidates) { function load() {
const p = join(__dirname, c); const key = `${platform}-${arch}`;
if (existsSync(p)) { const target = TARGETS[key];
return require(p); if (!target) {
} throw new Error(
`wickra: this platform/architecture combination is not supported (${key}). ` +
'Open an issue at https://github.com/kingchenc/wickra/issues with your platform details.'
);
}
const localBinary = join(__dirname, `wickra.${target}.node`);
if (existsSync(localBinary)) {
return require(localBinary);
}
try {
return require(`wickra-${target}`);
} catch (err) {
throw new Error(
`wickra: failed to load the native binding for ${key}. ` +
`Expected either ${localBinary} or the wickra-${target} package to be installed. ` +
`Run \`npm install\` again, or build from source with \`npm run build\`. ` +
`Underlying error: ${err.message}`
);
} }
throw new Error(
`Wickra: no precompiled binary found for ${platform}-${arch}. ` +
'Build from source with `napi build --release` or install a platform-specific package.'
);
} }
module.exports = loadNative(); module.exports = load();
+5 -10
View File
@@ -1,6 +1,6 @@
{ {
"name": "wickra", "name": "wickra",
"version": "0.1.0", "version": "0.1.1",
"description": "Streaming-first technical indicators: incremental, fast, install-free. Node bindings powered by Rust.", "description": "Streaming-first technical indicators: incremental, fast, install-free. Node bindings powered by Rust.",
"author": "kingchenc <kingchencp@gmail.com>", "author": "kingchenc <kingchencp@gmail.com>",
"main": "index.js", "main": "index.js",
@@ -32,17 +32,12 @@
"napi": { "napi": {
"name": "wickra", "name": "wickra",
"triples": { "triples": {
"defaults": true, "defaults": false,
"additional": [ "additional": [
"x86_64-unknown-linux-musl", "x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-gnu", "x86_64-apple-darwin",
"i686-pc-windows-msvc",
"armv7-unknown-linux-gnueabihf",
"aarch64-apple-darwin", "aarch64-apple-darwin",
"aarch64-linux-android", "x86_64-pc-windows-msvc"
"x86_64-unknown-freebsd",
"aarch64-unknown-linux-musl",
"aarch64-pc-windows-msvc"
] ]
} }
}, },
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "maturin"
[project] [project]
name = "wickra" name = "wickra"
version = "0.1.0" version = "0.1.1"
description = "Streaming-first technical indicators: incremental, fast, install-free." description = "Streaming-first technical indicators: incremental, fast, install-free."
readme = "README.md" readme = "README.md"
license = { text = "PolyForm-Noncommercial-1.0.0" } license = { text = "PolyForm-Noncommercial-1.0.0" }