mq-bridge 0.2.0 → 0.3.1

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
@@ -22,9 +22,9 @@ npm run example
22
22
  ## Handler shape
23
23
 
24
24
  ```ts
25
- import { Message, Route } from "@mq-bridge/node";
25
+ import { Message, Route } from "mq-bridge";
26
26
 
27
- const route = Route.fromYamlStr(config, "orders");
27
+ const route = Route.fromStr(config, "orders");
28
28
 
29
29
  route.withHandler(async (message) => {
30
30
  const data = message.json();
@@ -39,3 +39,83 @@ route.start();
39
39
  ```
40
40
 
41
41
  Middleware is configured through the normal mq-bridge route config.
42
+
43
+ ## Loading config
44
+
45
+ The constructors mirror the Python bindings — the same capabilities are exposed
46
+ in both, with Node using camelCase names where Python uses snake_case:
47
+
48
+ - `Route.fromFile(path, name?)` loads from a YAML/JSON file
49
+ - `Route.fromStr(text, name?)` loads from an in-memory YAML/JSON string
50
+ - `Route.fromConfig(obj, name?)` loads from a JS object
51
+ - `Publisher.fromFile` / `Publisher.fromStr` / `Publisher.fromConfig` build a publisher endpoint
52
+
53
+ The `name` is optional: pass it to pick one entry out of a `routes:`/`publishers:`
54
+ document, or omit it to treat the whole config as a single bare route/endpoint body.
55
+ `fromYaml` / `fromYamlStr` remain as deprecated aliases for `fromFile` / `fromStr`.
56
+
57
+ ## Pull-based consumer
58
+
59
+ `Route` is push-based. To pull messages on your own schedule, use `Consumer`,
60
+ which wraps any input endpoint:
61
+
62
+ ```js
63
+ import { Consumer } from "mq-bridge";
64
+
65
+ const consumer = Consumer.fromConfig({ nats: { subject: "orders", url: "nats://localhost:4222" } });
66
+
67
+ while (!consumer.exhausted) {
68
+ const batch = await consumer.poll(500, 1000); // [] on timeout
69
+ if (batch.length === 0) continue;
70
+ for (const message of batch) handle(message.json());
71
+ await consumer.commit(); // ack only after handling
72
+ }
73
+ ```
74
+
75
+ `poll(max?, timeoutMs?)` returns up to `max` messages (default 256) without
76
+ acking, waiting up to `timeoutMs` milliseconds (omit it to block until a message
77
+ arrives); `commit()` acks every batch returned since the last commit. Committing
78
+ only after the downstream write succeeds gives at-least-once delivery. `exhausted`
79
+ turns `true` once a bounded source (e.g. a file) is drained; streaming brokers
80
+ never set it. `Consumer.fromFile` / `fromStr` accept a named entry under a
81
+ `consumers:` section or a single bare endpoint body.
82
+
83
+ `consumer.status()` resolves to a snapshot (`healthy`, `target`, `pending`,
84
+ `capacity`, `error`, `details`). `pending` is the broker backlog/lag where the
85
+ transport reports it (Kafka offset lag, AMQP queue depth, NATS JetStream
86
+ `numPending`), so `pending === 0` is a precise "caught up" check; it's absent
87
+ where the broker exposes no backlog (core NATS, MQTT). `consumer.close()`
88
+ releases the connection — idempotent, and `poll()`/`status()` reject afterwards.
89
+ Node is garbage-collected, so close explicitly rather than waiting for GC.
90
+
91
+ > **You must call `commit()` — it is not optional.** It is the only thing that
92
+ > tells the broker a batch is done. If you keep polling without committing, the
93
+ > offset never advances (every message is **re-delivered** on the next run), most
94
+ > brokers **stall** once their unacknowledged/prefetch window fills, and the
95
+ > uncommitted batches are held in memory so the process **grows unbounded**.
96
+ > Commit after each batch you have durably handled; to retry a failed batch,
97
+ > simply don't commit it.
98
+
99
+ ## Analysis
100
+
101
+ HTTP comparison benchmark, driven by a native load generator (`wrk`) so the
102
+ client is never the bottleneck. It boots each server in its own process — the
103
+ mq-bridge Node route plus raw Node `http`, uWebSockets.js, Fastify, and Express
104
+ (all peers run only when installed) — and drives each with `wrk`:
105
+
106
+ ```bash
107
+ cd node/mq-bridge-node
108
+ npm run build # release addon (the bench is meaningless on a debug build)
109
+ npm i -D fastify express # optional Node HTTP peers
110
+ npm i -D uNetworking/uWebSockets.js#v20.51.0 # the http-arena Node leader (native, from GitHub)
111
+ npm run bench:http -- --connections 1,8,32 --duration 8
112
+ ```
113
+
114
+ Requires `wrk` on `PATH` (`brew install wrk`). The `mqb` target needs the addon
115
+ built with the `http` feature (`npm run build` or `npm run build:ci`). Each
116
+ server echoes a tiny JSON body with `value` incremented; mq-bridge routes on the
117
+ `kind` header while the framework peers post plain JSON.
118
+
119
+ `uws` (uWebSockets.js) is the framework that tops public Node benchmarks like
120
+ http-arena and TechEmpower — it bypasses Node's `http` stack with a C++ socket
121
+ layer, so it is the most demanding yardstick here.
package/index.d.ts CHANGED
@@ -22,19 +22,72 @@ export class Message {
22
22
  }
23
23
 
24
24
  export class Publisher {
25
- static fromYaml(path: string, name: string): Publisher;
26
- static fromYamlStr(text: string, name: string): Publisher;
27
- static fromConfig(config: JsonValue, name: string): Publisher;
28
- send(message: Message): void;
29
- request(message: Message): Message;
30
- sendJson(data: JsonValue, metadata?: Metadata | null, id?: string | null): void;
31
- requestJson(data: JsonValue, metadata?: Metadata | null, id?: string | null): Message;
25
+ static fromFile(path: string, name?: string | null): Publisher;
26
+ static fromStr(text: string, name?: string | null): Publisher;
27
+ static fromConfig(config: JsonValue, name?: string | null): Publisher;
28
+ /** @deprecated Use {@link Publisher.fromFile} instead. */
29
+ static fromYaml(path: string, name?: string | null): Publisher;
30
+ /** @deprecated Use {@link Publisher.fromStr} instead. */
31
+ static fromYamlStr(text: string, name?: string | null): Publisher;
32
+ send(message: Message): Promise<void>;
33
+ request(message: Message): Promise<Message>;
34
+ sendJson(data: JsonValue, metadata?: Metadata | null, id?: string | null): Promise<void>;
35
+ requestJson(data: JsonValue, metadata?: Metadata | null, id?: string | null): Promise<Message>;
36
+ }
37
+
38
+ export interface ConsumerStatus {
39
+ healthy: boolean;
40
+ target: string;
41
+ /** Broker backlog/lag where the transport reports it; absent otherwise. */
42
+ pending?: number;
43
+ capacity?: number;
44
+ error?: string;
45
+ details: JsonValue;
46
+ }
47
+
48
+ export class Consumer {
49
+ static fromFile(path: string, name?: string | null): Consumer;
50
+ static fromStr(text: string, name?: string | null): Consumer;
51
+ static fromConfig(config: JsonValue, name?: string | null): Consumer;
52
+ /**
53
+ * Receive up to `max` messages (default 256) without acking. Resolves to an
54
+ * empty array if `timeoutMs` milliseconds elapse with nothing received, or the
55
+ * source is exhausted. Omit `timeoutMs` to block until a message arrives. The
56
+ * returned messages are acked by the next `commit()` call — which you must
57
+ * call (see {@link Consumer.commit}).
58
+ */
59
+ poll(max?: number | null, timeoutMs?: number | null): Promise<Message[]>;
60
+ /**
61
+ * Acknowledge every batch returned by `poll()` since the last `commit()`,
62
+ * advancing the consumer offset.
63
+ *
64
+ * Calling this is required, not optional. Without it the offset never advances
65
+ * (messages are re-delivered on the next run), most brokers stall once their
66
+ * unacknowledged/prefetch window fills, and uncommitted batches are held in
67
+ * memory so the process grows unbounded. To retry a failed batch, simply
68
+ * don't commit it — it will be redelivered.
69
+ */
70
+ commit(): Promise<void>;
71
+ /**
72
+ * Status snapshot for the underlying endpoint. `pending === 0` is a precise
73
+ * "caught up" signal on transports that report backlog (Kafka, AMQP, NATS
74
+ * JetStream); `pending` is absent where the broker exposes none.
75
+ */
76
+ status(): Promise<ConsumerStatus>;
77
+ /** Release the broker connection. Idempotent; `poll()`/`status()` reject after. */
78
+ close(): Promise<void>;
79
+ /** `true` once the source has signalled end-of-stream (e.g. a drained file). */
80
+ get exhausted(): boolean;
32
81
  }
33
82
 
34
83
  export class Route {
35
- static fromYaml(path: string, name: string): Route;
36
- static fromYamlStr(text: string, name: string): Route;
37
- static fromConfig(config: JsonValue, name: string): Route;
84
+ static fromFile(path: string, name?: string | null): Route;
85
+ static fromStr(text: string, name?: string | null): Route;
86
+ static fromConfig(config: JsonValue, name?: string | null): Route;
87
+ /** @deprecated Use {@link Route.fromFile} instead. */
88
+ static fromYaml(path: string, name?: string | null): Route;
89
+ /** @deprecated Use {@link Route.fromStr} instead. */
90
+ static fromYamlStr(text: string, name?: string | null): Route;
38
91
  withHandler(handler: MessageHandler): void;
39
92
  addHandler(kind: string, handler: JsonHandler): void;
40
93
  start(): void;
@@ -42,4 +95,10 @@ export class Route {
42
95
  join(): void;
43
96
  }
44
97
 
98
+ /**
99
+ * JSON Schema for the route/config mapping, generated from the compiled Rust
100
+ * models. Throws if the addon was built without the `schema` feature.
101
+ */
102
+ export function configSchema(): JsonValue;
103
+
45
104
  export const version: string;
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- const native = require("./mq_bridge_node.node");
3
+ const native = require("./native.js");
4
4
 
5
5
  class Message {
6
6
  constructor(payload, metadata = null, id = null) {
@@ -57,32 +57,81 @@ class Publisher {
57
57
  this._native = nativePublisher;
58
58
  }
59
59
 
60
- static fromYaml(path, name) {
61
- return new Publisher(native.Publisher.fromYaml(path, name));
60
+ static fromFile(path, name) {
61
+ return new Publisher(native.Publisher.fromFile(path, name));
62
62
  }
63
63
 
64
- static fromYamlStr(text, name) {
65
- return new Publisher(native.Publisher.fromYamlStr(text, name));
64
+ static fromStr(text, name) {
65
+ return new Publisher(native.Publisher.fromStr(text, name));
66
66
  }
67
67
 
68
68
  static fromConfig(config, name) {
69
69
  return new Publisher(native.Publisher.fromConfig(config, name));
70
70
  }
71
71
 
72
+ /** @deprecated Use {@link Publisher.fromFile} instead. */
73
+ static fromYaml(path, name) {
74
+ return new Publisher(native.Publisher.fromFile(path, name));
75
+ }
76
+
77
+ /** @deprecated Use {@link Publisher.fromStr} instead. */
78
+ static fromYamlStr(text, name) {
79
+ return new Publisher(native.Publisher.fromStr(text, name));
80
+ }
81
+
72
82
  send(message) {
73
- this._native.send(Message._toNative(message));
83
+ return this._native.send(Message._toNative(message));
74
84
  }
75
85
 
76
- request(message) {
77
- return Message._fromNative(this._native.request(Message._toNative(message)));
86
+ async request(message) {
87
+ return Message._fromNative(await this._native.request(Message._toNative(message)));
78
88
  }
79
89
 
80
90
  sendJson(data, metadata = null, id = null) {
81
- this._native.sendJson(data, metadata, id);
91
+ return this._native.sendJson(data, metadata, id);
82
92
  }
83
93
 
84
- requestJson(data, metadata = null, id = null) {
85
- return Message._fromNative(this._native.requestJson(data, metadata, id));
94
+ async requestJson(data, metadata = null, id = null) {
95
+ return Message._fromNative(await this._native.requestJson(data, metadata, id));
96
+ }
97
+ }
98
+
99
+ class Consumer {
100
+ constructor(nativeConsumer) {
101
+ this._native = nativeConsumer;
102
+ }
103
+
104
+ static fromFile(path, name) {
105
+ return new Consumer(native.Consumer.fromFile(path, name));
106
+ }
107
+
108
+ static fromStr(text, name) {
109
+ return new Consumer(native.Consumer.fromStr(text, name));
110
+ }
111
+
112
+ static fromConfig(config, name) {
113
+ return new Consumer(native.Consumer.fromConfig(config, name));
114
+ }
115
+
116
+ async poll(max, timeoutMs) {
117
+ const messages = await this._native.poll(max, timeoutMs);
118
+ return messages.map((message) => Message._fromNative(message));
119
+ }
120
+
121
+ commit() {
122
+ return this._native.commit();
123
+ }
124
+
125
+ status() {
126
+ return this._native.status();
127
+ }
128
+
129
+ close() {
130
+ return this._native.close();
131
+ }
132
+
133
+ get exhausted() {
134
+ return this._native.exhausted;
86
135
  }
87
136
  }
88
137
 
@@ -91,18 +140,28 @@ class Route {
91
140
  this._native = nativeRoute;
92
141
  }
93
142
 
94
- static fromYaml(path, name) {
95
- return new Route(native.Route.fromYaml(path, name));
143
+ static fromFile(path, name) {
144
+ return new Route(native.Route.fromFile(path, name));
96
145
  }
97
146
 
98
- static fromYamlStr(text, name) {
99
- return new Route(native.Route.fromYamlStr(text, name));
147
+ static fromStr(text, name) {
148
+ return new Route(native.Route.fromStr(text, name));
100
149
  }
101
150
 
102
151
  static fromConfig(config, name) {
103
152
  return new Route(native.Route.fromConfig(config, name));
104
153
  }
105
154
 
155
+ /** @deprecated Use {@link Route.fromFile} instead. */
156
+ static fromYaml(path, name) {
157
+ return new Route(native.Route.fromFile(path, name));
158
+ }
159
+
160
+ /** @deprecated Use {@link Route.fromStr} instead. */
161
+ static fromYamlStr(text, name) {
162
+ return new Route(native.Route.fromStr(text, name));
163
+ }
164
+
106
165
  withHandler(handler) {
107
166
  this._native.withHandler(async (error, message) => {
108
167
  if (error) {
@@ -136,9 +195,20 @@ class Route {
136
195
  }
137
196
  }
138
197
 
198
+ function configSchema() {
199
+ if (typeof native.configSchema !== "function") {
200
+ throw new Error(
201
+ "configSchema() is unavailable: this build was compiled without the 'schema' feature",
202
+ );
203
+ }
204
+ return native.configSchema();
205
+ }
206
+
139
207
  module.exports = {
140
208
  Message,
141
209
  Publisher,
210
+ Consumer,
142
211
  Route,
143
- version: native.version,
212
+ configSchema,
213
+ version: native.VERSION,
144
214
  };
package/native.d.ts ADDED
@@ -0,0 +1,157 @@
1
+ /* auto-generated by NAPI-RS */
2
+ /* eslint-disable */
3
+ /**
4
+ * A pull-based consumer over any mq-bridge input endpoint.
5
+ *
6
+ * `poll()` receives a batch of messages but does **not** acknowledge them;
7
+ * call `commit()` once they have been durably handled to ack every batch
8
+ * returned since the previous commit (advancing offsets / removing them from
9
+ * the source). This manual-commit model gives at-least-once delivery across a
10
+ * failed downstream load. The endpoint config decides durability (consumer vs
11
+ * subscriber mode), exactly as it does for a route input.
12
+ *
13
+ * Relationship to the Rust core: this is a boundary-friendly projection of the
14
+ * core `MessageConsumer::receive_batch`, which is the low-level primitive. Two
15
+ * differences are deliberate, both because a Rust commit closure cannot be
16
+ * handed across the FFI boundary for JS to call later:
17
+ * - `receive_batch` returns the messages *and* their commit closure together;
18
+ * `poll()` returns only the messages and keeps the closure on the Rust side,
19
+ * so committing becomes the separate `commit()` call.
20
+ * - that closure accepts a per-message disposition vector (ack/nack/reject);
21
+ * `poll()` + `commit()` only ack the whole batch.
22
+ * `poll()` additionally layers a `timeoutMs` over `receive_batch` (which has no
23
+ * timeout of its own). Native Rust code should use `receive_batch` directly — it
24
+ * is strictly more expressive and needs no deferred-commit state.
25
+ */
26
+ export declare class Consumer {
27
+ /**
28
+ * Build a consumer from a YAML or JSON config file. Accepts a `consumers:`
29
+ * document entry (with `name`) or a single bare endpoint body.
30
+ */
31
+ static fromFile(path: string, name?: string | undefined | null): Consumer
32
+ /** Build a consumer from an in-memory YAML or JSON string. */
33
+ static fromStr(text: string, name?: string | undefined | null): Consumer
34
+ /**
35
+ * Build a consumer from an in-memory mapping (e.g. a JS object). Omit `name`
36
+ * to treat the mapping as a single bare endpoint body.
37
+ */
38
+ static fromConfig(config: JsonValue, name?: string | undefined | null): Consumer
39
+ /**
40
+ * Receive up to `max` messages without acking. Resolves to an empty array
41
+ * if `timeoutMs` milliseconds elapse with nothing received, or the source is
42
+ * exhausted (see `exhausted`). Omit `timeoutMs` to block until a message
43
+ * arrives. Acked by the next `commit()`.
44
+ */
45
+ poll(max?: number | undefined | null, timeoutMs?: number | undefined | null): Promise<Array<NativeMessage>>
46
+ /**
47
+ * Acknowledge every batch returned by `poll()` since the last `commit()`,
48
+ * advancing the consumer offset.
49
+ *
50
+ * Calling this is required, not optional. Without it the offset never
51
+ * advances (messages are re-delivered on the next run), most brokers stall
52
+ * once their unacknowledged/prefetch window fills, and uncommitted batches
53
+ * are held in memory so the process grows unbounded. To retry a failed
54
+ * batch, simply don't commit it — it will be redelivered.
55
+ */
56
+ commit(): Promise<void>
57
+ /**
58
+ * `true` once the source has signalled end-of-stream (e.g. a fully drained
59
+ * file). Streaming brokers never set this.
60
+ */
61
+ get exhausted(): boolean
62
+ /**
63
+ * Resolve to a status snapshot for the underlying endpoint: `healthy`,
64
+ * `target`, optional `pending` (broker backlog/lag where the transport
65
+ * reports it — Kafka offset lag, AMQP queue depth, NATS JetStream
66
+ * `numPending`), optional `capacity`/`error`, and `details`. `pending === 0`
67
+ * is a precise "caught up" signal on those transports; it is absent where
68
+ * the broker exposes no backlog (core NATS, MQTT). Point-in-time snapshot.
69
+ */
70
+ status(): Promise<JsonValue>
71
+ /**
72
+ * Release the underlying consumer connection. Idempotent. After this,
73
+ * `poll()` and `status()` reject. GC'd JS has no deterministic drop, so
74
+ * closing explicitly is how the broker connection is freed promptly.
75
+ */
76
+ close(): Promise<void>
77
+ }
78
+
79
+ export declare class Publisher {
80
+ /**
81
+ * Build a publisher endpoint from a YAML or JSON config file. Omit `name`
82
+ * (or pass `""`) when the file is a single bare endpoint body.
83
+ */
84
+ static fromFile(path: string, name?: string | undefined | null): Publisher
85
+ /** Deprecated alias for `from_file`. */
86
+ static fromYaml(path: string, name?: string | undefined | null): Publisher
87
+ /**
88
+ * Build a publisher endpoint from an in-memory YAML or JSON string. Omit
89
+ * `name` (or pass `""`) when the string is a single bare endpoint body.
90
+ */
91
+ static fromStr(text: string, name?: string | undefined | null): Publisher
92
+ /** Deprecated alias for `from_str`. */
93
+ static fromYamlStr(text: string, name?: string | undefined | null): Publisher
94
+ /**
95
+ * Build a publisher endpoint from an in-memory mapping (e.g. a JS object).
96
+ * Omit `name` (or pass `""`) to treat the mapping as a single bare endpoint
97
+ * body.
98
+ */
99
+ static fromConfig(config: JsonValue, name?: string | undefined | null): Publisher
100
+ send(message: NativeMessage): Promise<void>
101
+ request(message: NativeMessage): Promise<NativeMessage>
102
+ sendJson(data: JsonValue, metadata?: Record<string, string> | undefined | null, id?: string | undefined | null): Promise<void>
103
+ requestJson(data: JsonValue, metadata?: Record<string, string> | undefined | null, id?: string | undefined | null): Promise<NativeMessage>
104
+ }
105
+
106
+ export declare class Route {
107
+ /**
108
+ * Build a route from a YAML or JSON config file. Accepts a `routes:`
109
+ * document, a bare `{name: route}` map, or a single route body. Omit
110
+ * `name` (or pass `""`) when the file is a single bare route body.
111
+ */
112
+ static fromFile(path: string, name?: string | undefined | null): Route
113
+ /** Deprecated alias for `from_file`. */
114
+ static fromYaml(path: string, name?: string | undefined | null): Route
115
+ /**
116
+ * Build a route from an in-memory YAML or JSON string. Accepts the same
117
+ * shapes as `from_file`. Omit `name` (or pass `""`) when the string is a
118
+ * single bare route body.
119
+ */
120
+ static fromStr(text: string, name?: string | undefined | null): Route
121
+ /** Deprecated alias for `from_str`. */
122
+ static fromYamlStr(text: string, name?: string | undefined | null): Route
123
+ /**
124
+ * Build a route from an in-memory mapping (e.g. a JS object). Accepts a
125
+ * `routes:` document, a bare `{name: route}` map, or a single route body.
126
+ * Omit `name` (or pass `""`) to treat the mapping as a single bare route
127
+ * body, in which case a name is generated automatically.
128
+ */
129
+ static fromConfig(config: JsonValue, name?: string | undefined | null): Route
130
+ withHandler(callback: ((err: Error | null, arg: NativeMessage) => Promise<NativeMessage | undefined | null>)): void
131
+ addHandler(kind: string, callback: ((err: Error | null, arg: JsonValue) => Promise<NativeMessage | undefined | null>)): void
132
+ start(): void
133
+ stop(): void
134
+ join(): void
135
+ }
136
+
137
+ /**
138
+ * JSON Schema for the route/config mapping, generated on demand from the
139
+ * compiled Rust models (no checked-in copy, so it cannot drift).
140
+ */
141
+ export declare function configSchema(): JsonValue
142
+
143
+ export declare function createMessage(payload: Buffer, metadata?: Record<string, string> | undefined | null, id?: string | undefined | null): NativeMessage
144
+
145
+ export declare function messageFromJson(data: JsonValue, metadata?: Record<string, string> | undefined | null, id?: string | undefined | null): NativeMessage
146
+
147
+ export declare function messageJson(message: NativeMessage): JsonValue
148
+
149
+ export declare function messageText(message: NativeMessage): string
150
+
151
+ export interface NativeMessage {
152
+ payload: Buffer
153
+ metadata?: Record<string, string>
154
+ id?: string
155
+ }
156
+
157
+ export const version: string
package/native.js ADDED
@@ -0,0 +1,599 @@
1
+ // prettier-ignore
2
+ /* eslint-disable */
3
+ // @ts-nocheck
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ const { readFileSync } = require('fs')
7
+ let nativeBinding = null
8
+ const loadErrors = []
9
+
10
+ const isMusl = () => {
11
+ let musl = false
12
+ if (process.platform === 'linux') {
13
+ musl = isMuslFromFilesystem()
14
+ if (musl === null) {
15
+ musl = isMuslFromReport()
16
+ }
17
+ if (musl === null) {
18
+ musl = isMuslFromChildProcess()
19
+ }
20
+ }
21
+ return musl
22
+ }
23
+
24
+ const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
25
+
26
+ const isMuslFromFilesystem = () => {
27
+ try {
28
+ return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl')
29
+ } catch {
30
+ return null
31
+ }
32
+ }
33
+
34
+ const isMuslFromReport = () => {
35
+ let report = null
36
+ if (process.report && typeof process.report.getReport === 'function') {
37
+ process.report.excludeNetwork = true
38
+ report = process.report.getReport()
39
+ }
40
+ if (!report) {
41
+ return null
42
+ }
43
+ if (report.header && report.header.glibcVersionRuntime) {
44
+ return false
45
+ }
46
+ if (Array.isArray(report.sharedObjects)) {
47
+ if (report.sharedObjects.some(isFileMusl)) {
48
+ return true
49
+ }
50
+ }
51
+ return false
52
+ }
53
+
54
+ const isMuslFromChildProcess = () => {
55
+ try {
56
+ return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
57
+ } catch (e) {
58
+ // If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
59
+ return false
60
+ }
61
+ }
62
+
63
+ function requireNative() {
64
+ if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
65
+ try {
66
+ return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
67
+ } catch (err) {
68
+ loadErrors.push(err)
69
+ }
70
+ } else if (process.platform === 'android') {
71
+ if (process.arch === 'arm64') {
72
+ try {
73
+ return require('./mq_bridge_node.android-arm64.node')
74
+ } catch (e) {
75
+ loadErrors.push(e)
76
+ }
77
+ try {
78
+ const binding = require('mq-bridge-android-arm64')
79
+ const bindingPackageVersion = require('mq-bridge-android-arm64/package.json').version
80
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
81
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
82
+ }
83
+ return binding
84
+ } catch (e) {
85
+ loadErrors.push(e)
86
+ }
87
+ } else if (process.arch === 'arm') {
88
+ try {
89
+ return require('./mq_bridge_node.android-arm-eabi.node')
90
+ } catch (e) {
91
+ loadErrors.push(e)
92
+ }
93
+ try {
94
+ const binding = require('mq-bridge-android-arm-eabi')
95
+ const bindingPackageVersion = require('mq-bridge-android-arm-eabi/package.json').version
96
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
97
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
98
+ }
99
+ return binding
100
+ } catch (e) {
101
+ loadErrors.push(e)
102
+ }
103
+ } else {
104
+ loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`))
105
+ }
106
+ } else if (process.platform === 'win32') {
107
+ if (process.arch === 'x64') {
108
+ if ((process.config && process.config.variables && process.config.variables.shlib_suffix === 'dll.a') || (process.config && process.config.variables && process.config.variables.node_target_type === 'shared_library')) {
109
+ try {
110
+ return require('./mq_bridge_node.win32-x64-gnu.node')
111
+ } catch (e) {
112
+ loadErrors.push(e)
113
+ }
114
+ try {
115
+ const binding = require('mq-bridge-win32-x64-gnu')
116
+ const bindingPackageVersion = require('mq-bridge-win32-x64-gnu/package.json').version
117
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
118
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
119
+ }
120
+ return binding
121
+ } catch (e) {
122
+ loadErrors.push(e)
123
+ }
124
+ } else {
125
+ try {
126
+ return require('./mq_bridge_node.win32-x64-msvc.node')
127
+ } catch (e) {
128
+ loadErrors.push(e)
129
+ }
130
+ try {
131
+ const binding = require('mq-bridge-win32-x64-msvc')
132
+ const bindingPackageVersion = require('mq-bridge-win32-x64-msvc/package.json').version
133
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
134
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
135
+ }
136
+ return binding
137
+ } catch (e) {
138
+ loadErrors.push(e)
139
+ }
140
+ }
141
+ } else if (process.arch === 'ia32') {
142
+ try {
143
+ return require('./mq_bridge_node.win32-ia32-msvc.node')
144
+ } catch (e) {
145
+ loadErrors.push(e)
146
+ }
147
+ try {
148
+ const binding = require('mq-bridge-win32-ia32-msvc')
149
+ const bindingPackageVersion = require('mq-bridge-win32-ia32-msvc/package.json').version
150
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
151
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
152
+ }
153
+ return binding
154
+ } catch (e) {
155
+ loadErrors.push(e)
156
+ }
157
+ } else if (process.arch === 'arm64') {
158
+ try {
159
+ return require('./mq_bridge_node.win32-arm64-msvc.node')
160
+ } catch (e) {
161
+ loadErrors.push(e)
162
+ }
163
+ try {
164
+ const binding = require('mq-bridge-win32-arm64-msvc')
165
+ const bindingPackageVersion = require('mq-bridge-win32-arm64-msvc/package.json').version
166
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
167
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
168
+ }
169
+ return binding
170
+ } catch (e) {
171
+ loadErrors.push(e)
172
+ }
173
+ } else {
174
+ loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`))
175
+ }
176
+ } else if (process.platform === 'darwin') {
177
+ try {
178
+ return require('./mq_bridge_node.darwin-universal.node')
179
+ } catch (e) {
180
+ loadErrors.push(e)
181
+ }
182
+ try {
183
+ const binding = require('mq-bridge-darwin-universal')
184
+ const bindingPackageVersion = require('mq-bridge-darwin-universal/package.json').version
185
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
186
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
187
+ }
188
+ return binding
189
+ } catch (e) {
190
+ loadErrors.push(e)
191
+ }
192
+ if (process.arch === 'x64') {
193
+ try {
194
+ return require('./mq_bridge_node.darwin-x64.node')
195
+ } catch (e) {
196
+ loadErrors.push(e)
197
+ }
198
+ try {
199
+ const binding = require('mq-bridge-darwin-x64')
200
+ const bindingPackageVersion = require('mq-bridge-darwin-x64/package.json').version
201
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
202
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
203
+ }
204
+ return binding
205
+ } catch (e) {
206
+ loadErrors.push(e)
207
+ }
208
+ } else if (process.arch === 'arm64') {
209
+ try {
210
+ return require('./mq_bridge_node.darwin-arm64.node')
211
+ } catch (e) {
212
+ loadErrors.push(e)
213
+ }
214
+ try {
215
+ const binding = require('mq-bridge-darwin-arm64')
216
+ const bindingPackageVersion = require('mq-bridge-darwin-arm64/package.json').version
217
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
218
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
219
+ }
220
+ return binding
221
+ } catch (e) {
222
+ loadErrors.push(e)
223
+ }
224
+ } else {
225
+ loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`))
226
+ }
227
+ } else if (process.platform === 'freebsd') {
228
+ if (process.arch === 'x64') {
229
+ try {
230
+ return require('./mq_bridge_node.freebsd-x64.node')
231
+ } catch (e) {
232
+ loadErrors.push(e)
233
+ }
234
+ try {
235
+ const binding = require('mq-bridge-freebsd-x64')
236
+ const bindingPackageVersion = require('mq-bridge-freebsd-x64/package.json').version
237
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
238
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
239
+ }
240
+ return binding
241
+ } catch (e) {
242
+ loadErrors.push(e)
243
+ }
244
+ } else if (process.arch === 'arm64') {
245
+ try {
246
+ return require('./mq_bridge_node.freebsd-arm64.node')
247
+ } catch (e) {
248
+ loadErrors.push(e)
249
+ }
250
+ try {
251
+ const binding = require('mq-bridge-freebsd-arm64')
252
+ const bindingPackageVersion = require('mq-bridge-freebsd-arm64/package.json').version
253
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
254
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
255
+ }
256
+ return binding
257
+ } catch (e) {
258
+ loadErrors.push(e)
259
+ }
260
+ } else {
261
+ loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`))
262
+ }
263
+ } else if (process.platform === 'linux') {
264
+ if (process.arch === 'x64') {
265
+ if (isMusl()) {
266
+ try {
267
+ return require('./mq_bridge_node.linux-x64-musl.node')
268
+ } catch (e) {
269
+ loadErrors.push(e)
270
+ }
271
+ try {
272
+ const binding = require('mq-bridge-linux-x64-musl')
273
+ const bindingPackageVersion = require('mq-bridge-linux-x64-musl/package.json').version
274
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
275
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
276
+ }
277
+ return binding
278
+ } catch (e) {
279
+ loadErrors.push(e)
280
+ }
281
+ } else {
282
+ try {
283
+ return require('./mq_bridge_node.linux-x64-gnu.node')
284
+ } catch (e) {
285
+ loadErrors.push(e)
286
+ }
287
+ try {
288
+ const binding = require('mq-bridge-linux-x64-gnu')
289
+ const bindingPackageVersion = require('mq-bridge-linux-x64-gnu/package.json').version
290
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
291
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
292
+ }
293
+ return binding
294
+ } catch (e) {
295
+ loadErrors.push(e)
296
+ }
297
+ }
298
+ } else if (process.arch === 'arm64') {
299
+ if (isMusl()) {
300
+ try {
301
+ return require('./mq_bridge_node.linux-arm64-musl.node')
302
+ } catch (e) {
303
+ loadErrors.push(e)
304
+ }
305
+ try {
306
+ const binding = require('mq-bridge-linux-arm64-musl')
307
+ const bindingPackageVersion = require('mq-bridge-linux-arm64-musl/package.json').version
308
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
309
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
310
+ }
311
+ return binding
312
+ } catch (e) {
313
+ loadErrors.push(e)
314
+ }
315
+ } else {
316
+ try {
317
+ return require('./mq_bridge_node.linux-arm64-gnu.node')
318
+ } catch (e) {
319
+ loadErrors.push(e)
320
+ }
321
+ try {
322
+ const binding = require('mq-bridge-linux-arm64-gnu')
323
+ const bindingPackageVersion = require('mq-bridge-linux-arm64-gnu/package.json').version
324
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
325
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
326
+ }
327
+ return binding
328
+ } catch (e) {
329
+ loadErrors.push(e)
330
+ }
331
+ }
332
+ } else if (process.arch === 'arm') {
333
+ if (isMusl()) {
334
+ try {
335
+ return require('./mq_bridge_node.linux-arm-musleabihf.node')
336
+ } catch (e) {
337
+ loadErrors.push(e)
338
+ }
339
+ try {
340
+ const binding = require('mq-bridge-linux-arm-musleabihf')
341
+ const bindingPackageVersion = require('mq-bridge-linux-arm-musleabihf/package.json').version
342
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
343
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
344
+ }
345
+ return binding
346
+ } catch (e) {
347
+ loadErrors.push(e)
348
+ }
349
+ } else {
350
+ try {
351
+ return require('./mq_bridge_node.linux-arm-gnueabihf.node')
352
+ } catch (e) {
353
+ loadErrors.push(e)
354
+ }
355
+ try {
356
+ const binding = require('mq-bridge-linux-arm-gnueabihf')
357
+ const bindingPackageVersion = require('mq-bridge-linux-arm-gnueabihf/package.json').version
358
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
359
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
360
+ }
361
+ return binding
362
+ } catch (e) {
363
+ loadErrors.push(e)
364
+ }
365
+ }
366
+ } else if (process.arch === 'loong64') {
367
+ if (isMusl()) {
368
+ try {
369
+ return require('./mq_bridge_node.linux-loong64-musl.node')
370
+ } catch (e) {
371
+ loadErrors.push(e)
372
+ }
373
+ try {
374
+ const binding = require('mq-bridge-linux-loong64-musl')
375
+ const bindingPackageVersion = require('mq-bridge-linux-loong64-musl/package.json').version
376
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
377
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
378
+ }
379
+ return binding
380
+ } catch (e) {
381
+ loadErrors.push(e)
382
+ }
383
+ } else {
384
+ try {
385
+ return require('./mq_bridge_node.linux-loong64-gnu.node')
386
+ } catch (e) {
387
+ loadErrors.push(e)
388
+ }
389
+ try {
390
+ const binding = require('mq-bridge-linux-loong64-gnu')
391
+ const bindingPackageVersion = require('mq-bridge-linux-loong64-gnu/package.json').version
392
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
393
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
394
+ }
395
+ return binding
396
+ } catch (e) {
397
+ loadErrors.push(e)
398
+ }
399
+ }
400
+ } else if (process.arch === 'riscv64') {
401
+ if (isMusl()) {
402
+ try {
403
+ return require('./mq_bridge_node.linux-riscv64-musl.node')
404
+ } catch (e) {
405
+ loadErrors.push(e)
406
+ }
407
+ try {
408
+ const binding = require('mq-bridge-linux-riscv64-musl')
409
+ const bindingPackageVersion = require('mq-bridge-linux-riscv64-musl/package.json').version
410
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
411
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
412
+ }
413
+ return binding
414
+ } catch (e) {
415
+ loadErrors.push(e)
416
+ }
417
+ } else {
418
+ try {
419
+ return require('./mq_bridge_node.linux-riscv64-gnu.node')
420
+ } catch (e) {
421
+ loadErrors.push(e)
422
+ }
423
+ try {
424
+ const binding = require('mq-bridge-linux-riscv64-gnu')
425
+ const bindingPackageVersion = require('mq-bridge-linux-riscv64-gnu/package.json').version
426
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
427
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
428
+ }
429
+ return binding
430
+ } catch (e) {
431
+ loadErrors.push(e)
432
+ }
433
+ }
434
+ } else if (process.arch === 'ppc64') {
435
+ try {
436
+ return require('./mq_bridge_node.linux-ppc64-gnu.node')
437
+ } catch (e) {
438
+ loadErrors.push(e)
439
+ }
440
+ try {
441
+ const binding = require('mq-bridge-linux-ppc64-gnu')
442
+ const bindingPackageVersion = require('mq-bridge-linux-ppc64-gnu/package.json').version
443
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
444
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
445
+ }
446
+ return binding
447
+ } catch (e) {
448
+ loadErrors.push(e)
449
+ }
450
+ } else if (process.arch === 's390x') {
451
+ try {
452
+ return require('./mq_bridge_node.linux-s390x-gnu.node')
453
+ } catch (e) {
454
+ loadErrors.push(e)
455
+ }
456
+ try {
457
+ const binding = require('mq-bridge-linux-s390x-gnu')
458
+ const bindingPackageVersion = require('mq-bridge-linux-s390x-gnu/package.json').version
459
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
460
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
461
+ }
462
+ return binding
463
+ } catch (e) {
464
+ loadErrors.push(e)
465
+ }
466
+ } else {
467
+ loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`))
468
+ }
469
+ } else if (process.platform === 'openharmony') {
470
+ if (process.arch === 'arm64') {
471
+ try {
472
+ return require('./mq_bridge_node.openharmony-arm64.node')
473
+ } catch (e) {
474
+ loadErrors.push(e)
475
+ }
476
+ try {
477
+ const binding = require('mq-bridge-openharmony-arm64')
478
+ const bindingPackageVersion = require('mq-bridge-openharmony-arm64/package.json').version
479
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
480
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
481
+ }
482
+ return binding
483
+ } catch (e) {
484
+ loadErrors.push(e)
485
+ }
486
+ } else if (process.arch === 'x64') {
487
+ try {
488
+ return require('./mq_bridge_node.openharmony-x64.node')
489
+ } catch (e) {
490
+ loadErrors.push(e)
491
+ }
492
+ try {
493
+ const binding = require('mq-bridge-openharmony-x64')
494
+ const bindingPackageVersion = require('mq-bridge-openharmony-x64/package.json').version
495
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
496
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
497
+ }
498
+ return binding
499
+ } catch (e) {
500
+ loadErrors.push(e)
501
+ }
502
+ } else if (process.arch === 'arm') {
503
+ try {
504
+ return require('./mq_bridge_node.openharmony-arm.node')
505
+ } catch (e) {
506
+ loadErrors.push(e)
507
+ }
508
+ try {
509
+ const binding = require('mq-bridge-openharmony-arm')
510
+ const bindingPackageVersion = require('mq-bridge-openharmony-arm/package.json').version
511
+ if (bindingPackageVersion !== '0.3.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
512
+ throw new Error(`Native binding package version mismatch, expected 0.3.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
513
+ }
514
+ return binding
515
+ } catch (e) {
516
+ loadErrors.push(e)
517
+ }
518
+ } else {
519
+ loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`))
520
+ }
521
+ } else {
522
+ loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`))
523
+ }
524
+ }
525
+
526
+ nativeBinding = requireNative()
527
+
528
+ // NAPI_RS_FORCE_WASI is a tri-state flag:
529
+ // unset / any other value → native binding preferred, WASI is only a fallback
530
+ // 'true' → force WASI fallback even if native loaded
531
+ // 'error' → force WASI and throw if no WASI binding is found
532
+ // Treating any non-empty string as truthy (the historical behavior) meant
533
+ // NAPI_RS_FORCE_WASI=false, NAPI_RS_FORCE_WASI=0, etc. inadvertently triggered
534
+ // the WASI path, causing ENOENT for packages shipped without a .wasi.cjs file.
535
+ const forceWasi =
536
+ process.env.NAPI_RS_FORCE_WASI === 'true' || process.env.NAPI_RS_FORCE_WASI === 'error'
537
+
538
+ if (!nativeBinding || forceWasi) {
539
+ let wasiBinding = null
540
+ let wasiBindingError = null
541
+ try {
542
+ wasiBinding = require('./mq_bridge_node.wasi.cjs')
543
+ nativeBinding = wasiBinding
544
+ } catch (err) {
545
+ if (forceWasi) {
546
+ wasiBindingError = err
547
+ }
548
+ }
549
+ if (!nativeBinding || forceWasi) {
550
+ try {
551
+ wasiBinding = require('mq-bridge-wasm32-wasi')
552
+ nativeBinding = wasiBinding
553
+ } catch (err) {
554
+ if (forceWasi) {
555
+ if (!wasiBindingError) {
556
+ wasiBindingError = err
557
+ } else {
558
+ wasiBindingError.cause = err
559
+ }
560
+ loadErrors.push(err)
561
+ }
562
+ }
563
+ }
564
+ if (process.env.NAPI_RS_FORCE_WASI === 'error' && !wasiBinding) {
565
+ const error = new Error('WASI binding not found and NAPI_RS_FORCE_WASI is set to error')
566
+ error.cause = wasiBindingError
567
+ throw error
568
+ }
569
+ }
570
+
571
+ if (!nativeBinding) {
572
+ if (loadErrors.length > 0) {
573
+ const error = new Error(
574
+ `Cannot find native binding. ` +
575
+ `npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` +
576
+ 'Please try `npm i` again after removing both package-lock.json and node_modules directory.',
577
+ )
578
+ // assign instead of the `new Error(message, { cause })` options form,
579
+ // which Node < 16.9 silently ignores
580
+ error.cause = loadErrors.reduce((err, cur) => {
581
+ cur.cause = err
582
+ return cur
583
+ })
584
+ throw error
585
+ }
586
+ throw new Error(`Failed to load native binding`)
587
+ }
588
+
589
+ module.exports = nativeBinding
590
+ module.exports.Consumer = nativeBinding.Consumer
591
+ module.exports.Publisher = nativeBinding.Publisher
592
+ module.exports.Route = nativeBinding.Route
593
+ module.exports.configSchema = nativeBinding.configSchema
594
+ module.exports.createMessage = nativeBinding.createMessage
595
+ module.exports.messageFromJson = nativeBinding.messageFromJson
596
+ module.exports.messageJson = nativeBinding.messageJson
597
+ module.exports.messageText = nativeBinding.messageText
598
+ module.exports.version = nativeBinding.version
599
+ module.exports.VERSION = nativeBinding.VERSION
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mq-bridge",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Node.js bindings for mq-bridge",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -13,20 +13,38 @@
13
13
  "files": [
14
14
  "index.js",
15
15
  "index.d.ts",
16
- "*.node"
16
+ "native.js",
17
+ "native.d.ts"
17
18
  ],
18
19
  "napi": {
19
- "binaryName": "mq_bridge_node"
20
+ "binaryName": "mq_bridge_node",
21
+ "targets": [
22
+ "x86_64-apple-darwin",
23
+ "aarch64-apple-darwin",
24
+ "x86_64-unknown-linux-gnu",
25
+ "aarch64-unknown-linux-gnu",
26
+ "x86_64-pc-windows-msvc"
27
+ ]
20
28
  },
21
29
  "scripts": {
22
- "build": "napi build --release",
23
- "build:basic": "napi build --release --no-default-features --features \"basic middleware\" --dts native.d.ts",
24
- "build:ci": "napi build --no-default-features --features \"http middleware\" --dts native.d.ts",
25
- "build:debug": "napi build",
30
+ "build": "napi build --platform --release --strip --js native.js --dts native.d.ts",
31
+ "build:basic": "napi build --platform --release --strip --no-default-features --features \"basic middleware\" --js native.js --dts native.d.ts",
32
+ "build:ci": "napi build --platform --no-default-features --features \"http middleware schema\" --js native.js --dts native.d.ts",
33
+ "build:debug": "napi build --platform --js native.js --dts native.d.ts",
26
34
  "example": "node examples/http-handler.js",
35
+ "bench:http": "node analysis/bench_http_native.js",
27
36
  "test": "node --test test/*.test.js",
37
+ "sync-version": "node scripts/sync-version.mjs",
38
+ "create-npm-dirs": "napi create-npm-dirs",
28
39
  "artifacts": "napi artifacts"
29
40
  },
41
+ "optionalDependencies": {
42
+ "mq-bridge-darwin-x64": "0.3.1",
43
+ "mq-bridge-darwin-arm64": "0.3.1",
44
+ "mq-bridge-linux-x64-gnu": "0.3.1",
45
+ "mq-bridge-linux-arm64-gnu": "0.3.1",
46
+ "mq-bridge-win32-x64-msvc": "0.3.1"
47
+ },
30
48
  "devDependencies": {
31
49
  "@napi-rs/cli": "^3.0.0"
32
50
  },
Binary file