@push.rocks/smartrust 1.3.2 → 1.4.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.
@@ -1,124 +0,0 @@
1
- name: Default (tags)
2
-
3
- on:
4
- push:
5
- tags:
6
- - '*'
7
-
8
- env:
9
- IMAGE: code.foss.global/host.today/ht-docker-node:npmci
10
- NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@code.foss.global/${{gitea.repository}}.git
11
- NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
12
- NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
13
- NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
14
- NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
15
-
16
- jobs:
17
- security:
18
- runs-on: ubuntu-latest
19
- continue-on-error: true
20
- container:
21
- image: ${{ env.IMAGE }}
22
-
23
- steps:
24
- - uses: actions/checkout@v3
25
-
26
- - name: Prepare
27
- run: |
28
- pnpm install -g pnpm
29
- pnpm install -g @ship.zone/npmci
30
- npmci npm prepare
31
-
32
- - name: Audit production dependencies
33
- run: |
34
- npmci command npm config set registry https://registry.npmjs.org
35
- npmci command pnpm audit --audit-level=high --prod
36
- continue-on-error: true
37
-
38
- - name: Audit development dependencies
39
- run: |
40
- npmci command npm config set registry https://registry.npmjs.org
41
- npmci command pnpm audit --audit-level=high --dev
42
- continue-on-error: true
43
-
44
- test:
45
- if: ${{ always() }}
46
- needs: security
47
- runs-on: ubuntu-latest
48
- container:
49
- image: ${{ env.IMAGE }}
50
-
51
- steps:
52
- - uses: actions/checkout@v3
53
-
54
- - name: Prepare
55
- run: |
56
- pnpm install -g pnpm
57
- pnpm install -g @ship.zone/npmci
58
- npmci npm prepare
59
-
60
- - name: Test stable
61
- run: |
62
- npmci node install stable
63
- npmci npm install
64
- npmci npm test
65
-
66
- - name: Test build
67
- run: |
68
- npmci node install stable
69
- npmci npm install
70
- npmci npm build
71
-
72
- release:
73
- needs: test
74
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
75
- runs-on: ubuntu-latest
76
- container:
77
- image: ${{ env.IMAGE }}
78
-
79
- steps:
80
- - uses: actions/checkout@v3
81
-
82
- - name: Prepare
83
- run: |
84
- pnpm install -g pnpm
85
- pnpm install -g @ship.zone/npmci
86
- npmci npm prepare
87
-
88
- - name: Release
89
- run: |
90
- npmci node install stable
91
- npmci npm publish
92
-
93
- metadata:
94
- needs: test
95
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
96
- runs-on: ubuntu-latest
97
- container:
98
- image: ${{ env.IMAGE }}
99
- continue-on-error: true
100
-
101
- steps:
102
- - uses: actions/checkout@v3
103
-
104
- - name: Prepare
105
- run: |
106
- pnpm install -g pnpm
107
- pnpm install -g @ship.zone/npmci
108
- npmci npm prepare
109
-
110
- - name: Code quality
111
- run: |
112
- npmci command npm install -g typescript
113
- npmci npm install
114
-
115
- - name: Trigger
116
- run: npmci trigger
117
-
118
- - name: Build docs and upload artifacts
119
- run: |
120
- npmci node install stable
121
- npmci npm install
122
- pnpm install -g @git.zone/tsdoc
123
- npmci command tsdoc
124
- continue-on-error: true
@@ -1,11 +0,0 @@
1
- {
2
- "version": "0.2.0",
3
- "configurations": [
4
- {
5
- "command": "npm test",
6
- "name": "Run npm test",
7
- "request": "launch",
8
- "type": "node-terminal"
9
- }
10
- ]
11
- }
@@ -1,26 +0,0 @@
1
- {
2
- "json.schemas": [
3
- {
4
- "fileMatch": ["/npmextra.json"],
5
- "schema": {
6
- "type": "object",
7
- "properties": {
8
- "npmci": {
9
- "type": "object",
10
- "description": "settings for npmci"
11
- },
12
- "gitzone": {
13
- "type": "object",
14
- "description": "settings for gitzone",
15
- "properties": {
16
- "projectType": {
17
- "type": "string",
18
- "enum": ["website", "element", "service", "npm", "wcc"]
19
- }
20
- }
21
- }
22
- }
23
- }
24
- }
25
- ]
26
- }
package/changelog.md DELETED
@@ -1,84 +0,0 @@
1
- # Changelog
2
-
3
- ## 2026-03-14 - 1.3.2 - fix(rustbinarylocator)
4
- support resolving platform-suffixed local Rust binaries
5
-
6
- - Checks local Rust build paths for binaries with platform suffixes such as _linux_amd64 in addition to unsuffixed names
7
- - Adds platform and architecture suffix mapping for linux, darwin, windows, x64, and arm64
8
-
9
- ## 2026-02-26 - 1.3.1 - fix(readme)
10
- document socket transport and clarify stdio/socket differences in README
11
-
12
- - Add 'Two Transport Modes' section documenting stdio (spawn) and socket (connect) modes
13
- - Add examples for connect(), socket usage, and auto-reconnect with exponential backoff
14
- - Clarify protocol is transport-agnostic and update ready/stream/event descriptions
15
- - Update event docs: mark stderr as stdio-only and add 'reconnected' event for socket transports
16
- - Clarify kill() behavior for both stdio and socket transports
17
- - Add API reference entries for SocketTransport, StdioTransport, ISocketConnectOptions, IRustTransport, and LineScanner
18
- - Add platform notes, architecture diagram, and minimal Rust/socket usage guidance
19
-
20
- ## 2026-02-26 - 1.3.0 - feat(transport)
21
- introduce transport abstraction and socket-mode support for RustBridge
22
-
23
- - Add IRustTransport interface and two transport implementations: StdioTransport (spawns child process and uses stdin/stdout) and SocketTransport (connects to Unix socket / Windows named pipe).
24
- - Refactor RustBridge to use a transport abstraction (connectWithTransport) and add connect(socketPath) to attach to an existing daemon via socket.
25
- - Introduce LineScanner: a buffer-based newline scanner used by both transports to handle large/newline-delimited messages and avoid OOMs.
26
- - Add socket connection options (autoReconnect, reconnectBaseDelayMs, reconnectMaxDelayMs, maxReconnectAttempts) and implement auto-reconnect/backoff behavior in SocketTransport.
27
- - Implement backpressure-aware write semantics and proper disconnect/cleanup for both transports; RustBridge.kill() now disconnects the transport instead of directly managing processes.
28
- - Add tests and tooling: socket transport tests, line scanner tests, and a mock-socket-server.mjs helper script for testing socket mode.
29
- - Export new symbols (StdioTransport, SocketTransport, LineScanner) and update plugins to expose net; update interfaces to export transport types.
30
-
31
- ## 2026-02-12 - 1.2.1 - fix(rust-binary-locator)
32
- auto-fix missing execute permission for located Rust binaries
33
-
34
- - If a located binary exists but lacks the execute bit, attempt to chmod it to 0o755 and treat it as executable.
35
- - Logs an info message when the auto-fix is applied: 'Auto-fixed missing execute permission on: <filePath>'.
36
- - Addresses cases where npm/pnpm installs remove the execute permission from bundled binaries.
37
-
38
- ## 2026-02-11 - 1.2.0 - feat(rustbridge)
39
- add streaming responses and robust large-payload/backpressure handling to RustBridge
40
-
41
- - Introduce StreamingResponse type and export it (for-await-of iterator + .result promise)
42
- - Add sendCommandStreaming API to send streaming commands and receive chunks + final result
43
- - Implement buffer-based stdout newline scanner to handle large messages and avoid readline limits
44
- - Add backpressure-aware writeToStdin to wait for drain when writing large outbound payloads
45
- - Add maxPayloadSize option and enforce outbound/inbound size checks to prevent OOMs
46
- - Add streamTimeoutMs (inactivity timeout) and reset timeout on each received chunk
47
- - Improve stderr handling (cross-chunk buffering and trimmed emits)
48
- - Update mock test binary and extensive tests for streaming, large payloads, concurrency, and error cases
49
- - Add TypeScript types for streaming commands (TStreamingCommandKeys, TExtractChunk, IManagementStreamChunk)
50
-
51
- ## 2026-02-10 - 1.1.2 - fix(rust-binary-locator)
52
- use import.meta.resolve and url.fileURLToPath to locate bundled Rust binary in ESM environments
53
-
54
- - Replace require.resolve with import.meta.resolve to support ESM module resolution
55
- - Convert resolved file URL to a filesystem path using url.fileURLToPath
56
- - Export the url module from ts/plugins to provide fileURLToPath
57
-
58
- ## 2026-02-10 - 1.1.1 - fix(readme)
59
- update README with comprehensive documentation, usage examples, API reference, installation instructions, and legal/company information
60
-
61
- - Rewrote readme.md (≈ +298 −3 lines) to add detailed install, overview, IPC protocol, command definition examples, usage, API reference, issue reporting & security guidance, and legal/trademark/company information.
62
- - Documentation-only change — no source code modified.
63
- - Current package version is 1.1.0; recommend a patch release
64
-
65
- ## 2026-02-10 - 1.1.0 - feat(rustbridge)
66
- add RustBridge and RustBinaryLocator with typed IPC interfaces, plugins, tests and mock runner; export from index; add npm registries
67
-
68
- - Introduce RustBridge: spawn and manage a child binary, JSON-over-stdin/stdout request/response handling, events, timeouts, pending request tracking, kill/cleanup logic.
69
- - Introduce RustBinaryLocator: multi-strategy binary discovery (explicit path, env var, platform-specific package, local build paths, system PATH) with caching and logger hooks.
70
- - Add IPC and config TypeScript interfaces (IManagementRequest/Response/Event, ICommandDefinition, IBinaryLocatorOptions, IRustBridgeOptions) and re-export via interfaces/index.ts.
71
- - Update ts/plugins.ts to export fs, child_process, readline and events for easier native integration.
72
- - Add tests for RustBridge and RustBinaryLocator plus a test helper mock-rust-binary.mjs to simulate the IPC protocol and exercise commands, events, timeouts and locator behaviors.
73
- - Update ts/index.ts to export RustBridge and RustBinaryLocator and export interfaces; update npmextra.json to include internal Verdaccio registry alongside npmjs.org.
74
-
75
- ## 2026-02-08 - 1.0.2 - fix()
76
- no changes
77
-
78
- - No changes detected in git diff; no release necessary.
79
-
80
- ## 2026-02-08 - 1.0.1 - initial release
81
- Initial release of the project.
82
-
83
- - Initial commit creating the project repository and baseline files.
84
- - Tagged as version 1.0.1.
package/npmextra.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "@git.zone/cli": {
3
- "projectType": "npm",
4
- "module": {
5
- "githost": "code.foss.global",
6
- "gitscope": "push.rocks",
7
- "gitrepo": "smartrust",
8
- "description": "a bridge between JS engines and rust",
9
- "npmPackagename": "@push.rocks/smartrust",
10
- "license": "MIT",
11
- "projectDomain": "push.rocks"
12
- },
13
- "release": {
14
- "accessLevel": "public",
15
- "registries": [
16
- "https://verdaccio.lossless.digital",
17
- "https://registry.npmjs.org"
18
- ]
19
- }
20
- },
21
- "@ship.zone/szci": {
22
- "npmGlobalTools": []
23
- }
24
- }
@@ -1,104 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Mock "Rust binary" for testing the RustBridge IPC protocol.
5
- * Reads JSON lines from stdin via Buffer-based scanner, writes JSON lines to stdout.
6
- * Emits a ready event on startup.
7
- */
8
-
9
- // Emit ready event
10
- const readyEvent = JSON.stringify({ event: 'ready', data: { version: '1.0.0' } });
11
- process.stdout.write(readyEvent + '\n');
12
-
13
- // Buffer-based newline scanner for stdin (mirrors the RustBridge approach)
14
- let stdinBuffer = Buffer.alloc(0);
15
-
16
- process.stdin.on('data', (chunk) => {
17
- stdinBuffer = Buffer.concat([stdinBuffer, chunk]);
18
-
19
- let newlineIndex;
20
- while ((newlineIndex = stdinBuffer.indexOf(0x0A)) !== -1) {
21
- const lineBuffer = stdinBuffer.subarray(0, newlineIndex);
22
- stdinBuffer = stdinBuffer.subarray(newlineIndex + 1);
23
- const line = lineBuffer.toString('utf8').trim();
24
- if (line) {
25
- handleLine(line);
26
- }
27
- }
28
- });
29
-
30
- /**
31
- * Backpressure-aware write to stdout.
32
- */
33
- function writeResponse(data) {
34
- const json = JSON.stringify(data) + '\n';
35
- if (!process.stdout.write(json)) {
36
- // Wait for drain before continuing
37
- process.stdout.once('drain', () => {});
38
- }
39
- }
40
-
41
- function handleLine(line) {
42
- let request;
43
- try {
44
- request = JSON.parse(line);
45
- } catch {
46
- return;
47
- }
48
-
49
- const { id, method, params } = request;
50
-
51
- if (method === 'echo') {
52
- // Echo back the params as result
53
- writeResponse({ id, success: true, result: params });
54
- } else if (method === 'largeEcho') {
55
- // Echo back params (same as echo, named distinctly for large payload tests)
56
- writeResponse({ id, success: true, result: params });
57
- } else if (method === 'error') {
58
- // Return an error
59
- writeResponse({ id, success: false, error: 'Test error message' });
60
- } else if (method === 'emitEvent') {
61
- // Emit a custom event, then respond with success
62
- writeResponse({ event: params.eventName, data: params.eventData });
63
- writeResponse({ id, success: true, result: null });
64
- } else if (method === 'slow') {
65
- // Respond after a delay
66
- setTimeout(() => {
67
- writeResponse({ id, success: true, result: { delayed: true } });
68
- }, 100);
69
- } else if (method === 'streamEcho') {
70
- // Send params.count stream chunks, then final response
71
- const count = params.count || 0;
72
- let sent = 0;
73
- const interval = setInterval(() => {
74
- if (sent < count) {
75
- writeResponse({ id, stream: true, data: { index: sent, value: `chunk_${sent}` } });
76
- sent++;
77
- } else {
78
- clearInterval(interval);
79
- writeResponse({ id, success: true, result: { totalChunks: count } });
80
- }
81
- }, 10);
82
- } else if (method === 'streamError') {
83
- // Send 1 chunk, then error
84
- writeResponse({ id, stream: true, data: { index: 0, value: 'before_error' } });
85
- setTimeout(() => {
86
- writeResponse({ id, success: false, error: 'Stream error after chunk' });
87
- }, 20);
88
- } else if (method === 'streamEmpty') {
89
- // Zero chunks, immediate final response
90
- writeResponse({ id, success: true, result: { totalChunks: 0 } });
91
- } else if (method === 'exit') {
92
- // Graceful exit
93
- writeResponse({ id, success: true, result: null });
94
- process.exit(0);
95
- } else {
96
- // Unknown command
97
- writeResponse({ id, success: false, error: `Unknown method: ${method}` });
98
- }
99
- }
100
-
101
- // Handle SIGTERM gracefully
102
- process.on('SIGTERM', () => {
103
- process.exit(0);
104
- });
@@ -1,124 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Mock "Rust daemon" for testing the SocketTransport and RustBridge socket mode.
5
- * Creates a Unix socket server, accepts connections, and speaks the same
6
- * JSON-over-newline IPC protocol as mock-rust-binary.mjs.
7
- *
8
- * Usage: node mock-socket-server.mjs <socket-path>
9
- * Signals readiness by writing a JSON line to stdout: {"socketPath":"...","ready":true}
10
- */
11
-
12
- import * as net from 'net';
13
- import * as fs from 'fs';
14
-
15
- const socketPath = process.argv[2];
16
- if (!socketPath) {
17
- process.stderr.write('Usage: mock-socket-server.mjs <socket-path>\n');
18
- process.exit(1);
19
- }
20
-
21
- // Remove stale socket file
22
- try { fs.unlinkSync(socketPath); } catch { /* ignore */ }
23
-
24
- /**
25
- * Backpressure-aware write to a socket.
26
- */
27
- function writeResponse(conn, data) {
28
- const json = JSON.stringify(data) + '\n';
29
- if (!conn.write(json)) {
30
- conn.once('drain', () => {});
31
- }
32
- }
33
-
34
- function handleLine(line, conn) {
35
- let request;
36
- try {
37
- request = JSON.parse(line);
38
- } catch {
39
- return;
40
- }
41
-
42
- const { id, method, params } = request;
43
-
44
- if (method === 'echo') {
45
- writeResponse(conn, { id, success: true, result: params });
46
- } else if (method === 'largeEcho') {
47
- writeResponse(conn, { id, success: true, result: params });
48
- } else if (method === 'error') {
49
- writeResponse(conn, { id, success: false, error: 'Test error message' });
50
- } else if (method === 'emitEvent') {
51
- writeResponse(conn, { event: params.eventName, data: params.eventData });
52
- writeResponse(conn, { id, success: true, result: null });
53
- } else if (method === 'slow') {
54
- setTimeout(() => {
55
- writeResponse(conn, { id, success: true, result: { delayed: true } });
56
- }, 100);
57
- } else if (method === 'streamEcho') {
58
- const count = params.count || 0;
59
- let sent = 0;
60
- const interval = setInterval(() => {
61
- if (sent < count) {
62
- writeResponse(conn, { id, stream: true, data: { index: sent, value: `chunk_${sent}` } });
63
- sent++;
64
- } else {
65
- clearInterval(interval);
66
- writeResponse(conn, { id, success: true, result: { totalChunks: count } });
67
- }
68
- }, 10);
69
- } else if (method === 'streamError') {
70
- writeResponse(conn, { id, stream: true, data: { index: 0, value: 'before_error' } });
71
- setTimeout(() => {
72
- writeResponse(conn, { id, success: false, error: 'Stream error after chunk' });
73
- }, 20);
74
- } else if (method === 'streamEmpty') {
75
- writeResponse(conn, { id, success: true, result: { totalChunks: 0 } });
76
- } else if (method === 'exit') {
77
- writeResponse(conn, { id, success: true, result: null });
78
- // In socket mode, 'exit' just closes this connection, not the server
79
- setTimeout(() => conn.end(), 50);
80
- } else {
81
- writeResponse(conn, { id, success: false, error: `Unknown method: ${method}` });
82
- }
83
- }
84
-
85
- const server = net.createServer((conn) => {
86
- // Send ready event on each new connection
87
- writeResponse(conn, { event: 'ready', data: { version: '1.0.0' } });
88
-
89
- // Buffer-based newline scanner for incoming data
90
- let buffer = Buffer.alloc(0);
91
- conn.on('data', (chunk) => {
92
- buffer = Buffer.concat([buffer, chunk]);
93
- let idx;
94
- while ((idx = buffer.indexOf(0x0A)) !== -1) {
95
- const lineBuffer = buffer.subarray(0, idx);
96
- buffer = buffer.subarray(idx + 1);
97
- const line = lineBuffer.toString('utf8').trim();
98
- if (line) {
99
- handleLine(line, conn);
100
- }
101
- }
102
- });
103
-
104
- conn.on('error', () => { /* ignore client errors */ });
105
- });
106
-
107
- server.listen(socketPath, () => {
108
- // Signal to parent that the server is ready
109
- process.stdout.write(JSON.stringify({ socketPath, ready: true }) + '\n');
110
- });
111
-
112
- // Handle SIGTERM gracefully
113
- process.on('SIGTERM', () => {
114
- server.close();
115
- try { fs.unlinkSync(socketPath); } catch { /* ignore */ }
116
- process.exit(0);
117
- });
118
-
119
- // Handle SIGINT
120
- process.on('SIGINT', () => {
121
- server.close();
122
- try { fs.unlinkSync(socketPath); } catch { /* ignore */ }
123
- process.exit(0);
124
- });
@@ -1,89 +0,0 @@
1
- import { expect, tap } from '@git.zone/tstest/tapbundle';
2
- import { LineScanner } from '../ts/classes.linescanner.js';
3
-
4
- const noopLogger = { log() {} };
5
-
6
- tap.test('should parse a single complete line', async () => {
7
- const scanner = new LineScanner(1024 * 1024, noopLogger);
8
- const lines: string[] = [];
9
- scanner.push(Buffer.from('{"hello":"world"}\n'), (line) => lines.push(line));
10
- expect(lines.length).toEqual(1);
11
- expect(lines[0]).toEqual('{"hello":"world"}');
12
- });
13
-
14
- tap.test('should parse multiple lines in one chunk', async () => {
15
- const scanner = new LineScanner(1024 * 1024, noopLogger);
16
- const lines: string[] = [];
17
- scanner.push(Buffer.from('{"a":1}\n{"b":2}\n{"c":3}\n'), (line) => lines.push(line));
18
- expect(lines.length).toEqual(3);
19
- expect(lines[0]).toEqual('{"a":1}');
20
- expect(lines[1]).toEqual('{"b":2}');
21
- expect(lines[2]).toEqual('{"c":3}');
22
- });
23
-
24
- tap.test('should handle a line split across chunks', async () => {
25
- const scanner = new LineScanner(1024 * 1024, noopLogger);
26
- const lines: string[] = [];
27
- scanner.push(Buffer.from('{"hel'), (line) => lines.push(line));
28
- expect(lines.length).toEqual(0);
29
- scanner.push(Buffer.from('lo":"world"}\n'), (line) => lines.push(line));
30
- expect(lines.length).toEqual(1);
31
- expect(lines[0]).toEqual('{"hello":"world"}');
32
- });
33
-
34
- tap.test('should drop oversized lines', async () => {
35
- const scanner = new LineScanner(100, noopLogger);
36
- const lines: string[] = [];
37
- // Line is 200 chars + newline, exceeds maxPayloadSize of 100
38
- const oversized = 'x'.repeat(200) + '\n';
39
- scanner.push(Buffer.from(oversized), (line) => lines.push(line));
40
- expect(lines.length).toEqual(0);
41
- });
42
-
43
- tap.test('should clear buffer on OOM (no newline, exceeds max)', async () => {
44
- const scanner = new LineScanner(100, noopLogger);
45
- const lines: string[] = [];
46
- // Push 200 bytes without any newline — exceeds maxPayloadSize
47
- scanner.push(Buffer.from('x'.repeat(200)), (line) => lines.push(line));
48
- expect(lines.length).toEqual(0);
49
- // After clearing, should work normally again
50
- scanner.push(Buffer.from('{"ok":true}\n'), (line) => lines.push(line));
51
- expect(lines.length).toEqual(1);
52
- expect(lines[0]).toEqual('{"ok":true}');
53
- });
54
-
55
- tap.test('should skip empty lines', async () => {
56
- const scanner = new LineScanner(1024 * 1024, noopLogger);
57
- const lines: string[] = [];
58
- scanner.push(Buffer.from('\n\n{"a":1}\n\n'), (line) => lines.push(line));
59
- expect(lines.length).toEqual(1);
60
- expect(lines[0]).toEqual('{"a":1}');
61
- });
62
-
63
- tap.test('should handle mixed complete and partial lines', async () => {
64
- const scanner = new LineScanner(1024 * 1024, noopLogger);
65
- const lines: string[] = [];
66
- // First chunk: one complete line + start of second line
67
- scanner.push(Buffer.from('{"first":1}\n{"sec'), (line) => lines.push(line));
68
- expect(lines.length).toEqual(1);
69
- // Second chunk: end of second line + complete third line
70
- scanner.push(Buffer.from('ond":2}\n{"third":3}\n'), (line) => lines.push(line));
71
- expect(lines.length).toEqual(3);
72
- expect(lines[1]).toEqual('{"second":2}');
73
- expect(lines[2]).toEqual('{"third":3}');
74
- });
75
-
76
- tap.test('clear should reset the buffer', async () => {
77
- const scanner = new LineScanner(1024 * 1024, noopLogger);
78
- const lines: string[] = [];
79
- // Push partial data
80
- scanner.push(Buffer.from('{"partial":'), (line) => lines.push(line));
81
- // Clear
82
- scanner.clear();
83
- // Now push a complete new line — old partial should not affect it
84
- scanner.push(Buffer.from('{"fresh":true}\n'), (line) => lines.push(line));
85
- expect(lines.length).toEqual(1);
86
- expect(lines[0]).toEqual('{"fresh":true}');
87
- });
88
-
89
- export default tap.start();
@@ -1,98 +0,0 @@
1
- import { expect, tap } from '@git.zone/tstest/tapbundle';
2
- import * as path from 'path';
3
- import * as fs from 'fs';
4
- import { RustBinaryLocator } from '../ts/classes.rustbinarylocator.js';
5
-
6
- const testDir = path.resolve(path.dirname(new URL(import.meta.url).pathname));
7
-
8
- tap.test('should return null when no binary is found', async () => {
9
- const locator = new RustBinaryLocator({
10
- binaryName: 'nonexistent-binary-xyz',
11
- searchSystemPath: false,
12
- });
13
- const result = await locator.findBinary();
14
- expect(result).toBeNull();
15
- });
16
-
17
- tap.test('should use explicit binaryPath when provided', async () => {
18
- const mockBinaryPath = path.join(testDir, 'helpers/mock-rust-binary.mjs');
19
- const locator = new RustBinaryLocator({
20
- binaryName: 'mock-rust-binary',
21
- binaryPath: mockBinaryPath,
22
- searchSystemPath: false,
23
- });
24
- const result = await locator.findBinary();
25
- expect(result).toEqual(mockBinaryPath);
26
- });
27
-
28
- tap.test('should cache the result', async () => {
29
- const mockBinaryPath = path.join(testDir, 'helpers/mock-rust-binary.mjs');
30
- const locator = new RustBinaryLocator({
31
- binaryName: 'mock-rust-binary',
32
- binaryPath: mockBinaryPath,
33
- searchSystemPath: false,
34
- });
35
-
36
- const first = await locator.findBinary();
37
- const second = await locator.findBinary();
38
- expect(first).toEqual(second);
39
- expect(first).toEqual(mockBinaryPath);
40
- });
41
-
42
- tap.test('should clear cache', async () => {
43
- const mockBinaryPath = path.join(testDir, 'helpers/mock-rust-binary.mjs');
44
- const locator = new RustBinaryLocator({
45
- binaryName: 'mock-rust-binary',
46
- binaryPath: mockBinaryPath,
47
- searchSystemPath: false,
48
- });
49
-
50
- const first = await locator.findBinary();
51
- expect(first).toEqual(mockBinaryPath);
52
-
53
- locator.clearCache();
54
- // After clearing, next call should re-search and still find it
55
- const second = await locator.findBinary();
56
- expect(second).toEqual(mockBinaryPath);
57
- });
58
-
59
- tap.test('should fall back to env var when binaryPath not set', async () => {
60
- const mockBinaryPath = path.join(testDir, 'helpers/mock-rust-binary.mjs');
61
- const envVar = 'TEST_SMARTRUST_BINARY_' + Date.now();
62
- process.env[envVar] = mockBinaryPath;
63
-
64
- const locator = new RustBinaryLocator({
65
- binaryName: 'mock-rust-binary',
66
- envVarName: envVar,
67
- searchSystemPath: false,
68
- });
69
-
70
- const result = await locator.findBinary();
71
- expect(result).toEqual(mockBinaryPath);
72
-
73
- delete process.env[envVar];
74
- });
75
-
76
- tap.test('should find binary in local paths', async () => {
77
- const mockBinaryPath = path.join(testDir, 'helpers/mock-rust-binary.mjs');
78
- const locator = new RustBinaryLocator({
79
- binaryName: 'mock-rust-binary',
80
- localPaths: ['/nonexistent/path/binary', mockBinaryPath],
81
- searchSystemPath: false,
82
- });
83
-
84
- const result = await locator.findBinary();
85
- expect(result).toEqual(mockBinaryPath);
86
- });
87
-
88
- tap.test('should find node in system PATH', async () => {
89
- const locator = new RustBinaryLocator({
90
- binaryName: 'node',
91
- searchSystemPath: true,
92
- });
93
-
94
- const result = await locator.findBinary();
95
- expect(result).not.toBeNull();
96
- });
97
-
98
- export default tap.start();