opencode-cloud 1.0.10 → 3.1.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
@@ -1,192 +1,57 @@
1
- # opencode-cloud
1
+ # opencode-cloud Node.js CLI
2
2
 
3
- [![CI](https://github.com/pRizz/opencode-cloud/actions/workflows/ci.yml/badge.svg)](https://github.com/pRizz/opencode-cloud/actions/workflows/ci.yml)
4
- [![crates.io](https://img.shields.io/crates/v/opencode-cloud.svg)](https://crates.io/crates/opencode-cloud)
5
- [![npm](https://img.shields.io/npm/v/opencode-cloud.svg)](https://www.npmjs.com/package/opencode-cloud)
6
- [![docs.rs](https://docs.rs/opencode-cloud/badge.svg)](https://docs.rs/opencode-cloud)
7
- [![MSRV](https://img.shields.io/badge/MSRV-1.85-blue.svg)](https://blog.rust-lang.org/2025/02/20/Rust-1.85.0.html)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
3
+ Cross-platform CLI for opencode-cloud with prebuilt binaries for major platforms.
9
4
 
10
- A production-ready toolkit for deploying [opencode](https://github.com/anomalyco/opencode) as a persistent cloud service.
11
-
12
- ## Quick install (cargo)
5
+ ## Installation
13
6
 
14
7
  ```bash
15
- cargo install opencode-cloud
16
- opencode-cloud --version
8
+ npm install -g opencode-cloud
9
+ # or
10
+ npx opencode-cloud --version
17
11
  ```
18
12
 
19
- ## Features
13
+ No Rust toolchain required — npm automatically downloads the correct binary for your platform.
20
14
 
21
- - Cross-platform CLI (`opencode-cloud` / `occ`)
22
- - Docker container management
23
- - Service lifecycle commands (start, stop, status, logs)
24
- - Platform service integration (systemd/launchd)
25
- - XDG-compliant configuration
26
- - Singleton enforcement (one instance per host)
15
+ ## Supported Platforms
27
16
 
28
- ## Requirements
17
+ | Platform | Architecture | Package |
18
+ |----------|--------------|---------|
19
+ | macOS | Apple Silicon (arm64) | @opencode-cloud/cli-node-darwin-arm64 |
20
+ | macOS | Intel (x64) | @opencode-cloud/cli-node-darwin-x64 |
21
+ | Linux | x64 (glibc) | @opencode-cloud/cli-node-linux-x64 |
22
+ | Linux | ARM64 (glibc) | @opencode-cloud/cli-node-linux-arm64 |
23
+ | Linux | x64 (musl/Alpine) | @opencode-cloud/cli-node-linux-x64-musl |
24
+ | Linux | ARM64 (musl/Alpine) | @opencode-cloud/cli-node-linux-arm64-musl |
29
25
 
30
- ### For npm installation
26
+ Windows support planned for a future release.
31
27
 
32
- - **Node.js 20+**
33
- - **Rust 1.82+** (for compiling native bindings)
34
- - Install via [rustup](https://rustup.rs): `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
35
-
36
- ### For cargo installation
37
-
38
- - **Rust 1.82+**
39
-
40
- ## Installation
28
+ ## How it works
41
29
 
42
- ### Via npm (compiles from source)
30
+ 1. When you install `opencode-cloud`, npm downloads a platform-specific package based on your OS and architecture
31
+ 2. The main package finds the binary from the platform package
32
+ 3. All CLI invocations spawn the Rust binary with transparent passthrough (stdio: inherit)
33
+ 4. Exit codes, colors, and TTY detection are preserved
43
34
 
44
- ```bash
45
- npx opencode-cloud --version
46
- ```
47
-
48
- Or install globally:
49
-
50
- ```bash
51
- npm install -g opencode-cloud
52
- occ --version
53
- ```
35
+ ## Development
54
36
 
55
- ### Via cargo
37
+ When developing locally, place the Rust binary in the Node package `bin/` directory:
56
38
 
57
39
  ```bash
58
- cargo install opencode-cloud
59
- opencode-cloud --version
40
+ cargo build --release
41
+ cp target/release/occ packages/cli-node/bin/
60
42
  ```
61
43
 
62
- ### From source
63
-
64
- ```bash
65
- git clone https://github.com/pRizz/opencode-cloud.git
66
- cd opencode-cloud
67
- just build
68
- cargo run -p opencode-cloud -- --version
69
- ```
44
+ Then run via `just run` or `node packages/cli-node/dist/index.js <args>`. The wrapper resolves the binary from `bin/` when platform packages are not used.
70
45
 
71
46
  ## Usage
72
47
 
73
48
  ```bash
74
- # Show version
75
- occ --version
76
-
77
- # Start the service (builds image on first run)
78
49
  occ start
79
-
80
- # Start on a custom port
81
- occ start --port 8080
82
-
83
- # Start and open browser
84
- occ start --open
85
-
86
- # Check service status
87
50
  occ status
88
-
89
- # View logs
90
- occ logs
91
-
92
- # Follow logs in real-time
93
- occ logs -f
94
-
95
- # Stop the service
96
51
  occ stop
97
-
98
- # Restart the service
99
- occ restart
100
-
101
- # Install as a system service (starts on login/boot)
102
- occ install
103
-
104
- # Uninstall the system service
105
- occ uninstall
106
-
107
- # View configuration
108
- occ config show
109
- ```
110
-
111
- ### Rebuilding the Docker Image
112
-
113
- When developing locally or after updating opencode-cloud, you may need to rebuild the Docker image to pick up changes in the embedded Dockerfile:
114
-
115
- ```bash
116
- # Rebuild using Docker cache (fast - only rebuilds changed layers)
117
- occ start --cached-rebuild
118
-
119
- # Rebuild from scratch without cache (slow - for troubleshooting)
120
- occ start --full-rebuild
121
- ```
122
-
123
- **`--cached-rebuild`** (recommended for most cases):
124
- - Uses Docker layer cache for fast rebuilds
125
- - Only rebuilds layers that changed (e.g., if only the CMD changed, it's nearly instant)
126
- - Stops and removes any existing container before rebuilding
127
-
128
- **`--full-rebuild`** (for troubleshooting):
129
- - Ignores Docker cache and rebuilds everything from scratch
130
- - Takes 10-15 minutes but guarantees a completely fresh image
131
- - Use when cached rebuild doesn't fix issues
132
-
133
- **When to rebuild:**
134
- - After pulling updates to opencode-cloud → use `--cached-rebuild`
135
- - When modifying the Dockerfile during development → use `--cached-rebuild`
136
- - When the container fails to start due to image issues → try `--cached-rebuild` first, then `--full-rebuild`
137
- - When you want a completely fresh environment → use `--full-rebuild`
138
-
139
- ## Configuration
140
-
141
- Configuration is stored at:
142
- - Linux/macOS: `~/.config/opencode-cloud/config.json`
143
-
144
- Data (PID files, etc.) is stored at:
145
- - Linux/macOS: `~/.local/share/opencode-cloud/`
146
-
147
- ## Development
148
-
149
- ```bash
150
- # Install dependencies
151
- pnpm install
152
-
153
- # Configure git hooks (once after cloning)
154
- git config core.hooksPath .githooks
155
-
156
- # Build everything
157
- just build
158
-
159
- # Compile and run occ (arguments automatically get passed to the binary)
160
- just run --version
161
-
162
- # Run tests
163
- just test
164
-
165
- # Format and lint
166
- just fmt
167
- just lint
168
52
  ```
169
53
 
170
- > **Note:** The git hooks automatically sync `README.md` to npm package directories on commit.
171
-
172
- ## Architecture
173
-
174
- This is a monorepo with:
175
- - `packages/core` - Rust core library with NAPI-RS bindings
176
- - `packages/cli-rust` - Rust CLI binary
177
- - `packages/cli-node` - Node.js CLI wrapper (calls into core via NAPI)
178
-
179
- The npm package compiles the Rust core on install (no prebuilt binaries).
180
-
181
- ### Cargo.toml Sync Requirement
182
-
183
- The `packages/core/Cargo.toml` file must use **explicit values** rather than `workspace = true` references. This is because when users install the npm package, they only get `packages/core/` without the workspace root `Cargo.toml`, so workspace inheritance would fail.
184
-
185
- When updating package metadata (version, edition, rust-version, etc.), keep both files in sync:
186
- - `Cargo.toml` (workspace root)
187
- - `packages/core/Cargo.toml`
188
-
189
- Use `scripts/set-all-versions.sh <version>` to update versions across all files automatically.
54
+ All commands are identical between the npm and cargo installations.
190
55
 
191
56
  ## License
192
57
 
package/bin/.gitkeep ADDED
File without changes
@@ -0,0 +1,8 @@
1
+ /**
2
+ * CLI Parity Tests
3
+ *
4
+ * Verifies the Node CLI wrapper can successfully invoke all commands from the Rust CLI.
5
+ * Commands are discovered dynamically from `occ --help` to avoid hardcoded lists.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=cli-parity.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-parity.test.d.ts","sourceRoot":"","sources":["../src/cli-parity.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * CLI Parity Tests
3
+ *
4
+ * Verifies the Node CLI wrapper can successfully invoke all commands from the Rust CLI.
5
+ * Commands are discovered dynamically from `occ --help` to avoid hardcoded lists.
6
+ */
7
+ import { execSync } from 'child_process';
8
+ import { describe, it, expect, beforeAll } from 'vitest';
9
+ import { join, resolve } from 'path';
10
+ import { existsSync } from 'fs';
11
+ // Path to the Rust binary (built from workspace)
12
+ const RUST_BINARY_PATH = resolve(__dirname, '../../../target/debug/opencode-cloud');
13
+ // Path where Node CLI expects to find the binary
14
+ const NODE_BIN_DIR = resolve(__dirname, '../bin');
15
+ const NODE_BIN_PATH = join(NODE_BIN_DIR, 'occ');
16
+ // Path to the Node CLI wrapper (built TypeScript)
17
+ const NODE_CLI_PATH = resolve(__dirname, '../dist/index.js');
18
+ /**
19
+ * Parse commands from `occ --help` output
20
+ */
21
+ function discoverCommands() {
22
+ const helpOutput = execSync(`${RUST_BINARY_PATH} --help`, {
23
+ encoding: 'utf-8',
24
+ });
25
+ const lines = helpOutput.split('\n');
26
+ const commandsSection = lines.findIndex((line) => line.trim() === 'Commands:');
27
+ if (commandsSection === -1) {
28
+ throw new Error('Failed to find Commands: section in help output');
29
+ }
30
+ const commands = [];
31
+ // Parse lines after "Commands:" until we hit "Options:"
32
+ for (let i = commandsSection + 1; i < lines.length; i++) {
33
+ const line = lines[i];
34
+ // Stop at Options: section
35
+ if (line.trim() === 'Options:') {
36
+ break;
37
+ }
38
+ // Extract command name (first word after leading whitespace)
39
+ const match = line.match(/^\s+([a-z-]+)\s+/);
40
+ if (match) {
41
+ commands.push(match[1]);
42
+ }
43
+ }
44
+ return commands;
45
+ }
46
+ describe('CLI Parity', () => {
47
+ let commands;
48
+ beforeAll(() => {
49
+ // Ensure Rust binary exists
50
+ if (!existsSync(RUST_BINARY_PATH)) {
51
+ throw new Error(`Rust binary not found at ${RUST_BINARY_PATH}. Run: cargo build -p opencode-cloud`);
52
+ }
53
+ // Ensure Node CLI wrapper is built
54
+ if (!existsSync(NODE_CLI_PATH)) {
55
+ throw new Error(`Node CLI not built at ${NODE_CLI_PATH}. Run: pnpm -C packages/cli-node build`);
56
+ }
57
+ // Copy Rust binary to Node bin directory for passthrough
58
+ execSync(`mkdir -p ${NODE_BIN_DIR}`);
59
+ execSync(`cp ${RUST_BINARY_PATH} ${NODE_BIN_PATH}`);
60
+ // Discover commands dynamically
61
+ commands = discoverCommands();
62
+ });
63
+ it('should discover at least 10 commands', () => {
64
+ expect(commands.length).toBeGreaterThanOrEqual(10);
65
+ });
66
+ it.each([
67
+ 'start',
68
+ 'stop',
69
+ 'restart',
70
+ 'status',
71
+ 'logs',
72
+ 'install',
73
+ 'uninstall',
74
+ 'config',
75
+ 'setup',
76
+ 'user',
77
+ 'mount',
78
+ 'update',
79
+ 'cockpit',
80
+ 'host',
81
+ ])('should discover %s command', (command) => {
82
+ expect(commands).toContain(command);
83
+ });
84
+ describe('Command Passthrough', () => {
85
+ it('should pass --version through Node CLI', () => {
86
+ const output = execSync(`node ${NODE_CLI_PATH} --version`, {
87
+ encoding: 'utf-8',
88
+ }).trim();
89
+ expect(output).toMatch(/^opencode-cloud \d+\.\d+\.\d+$/);
90
+ });
91
+ it('should pass --help through Node CLI', () => {
92
+ const output = execSync(`node ${NODE_CLI_PATH} --help`, {
93
+ encoding: 'utf-8',
94
+ });
95
+ expect(output).toContain('Usage:');
96
+ expect(output).toContain('Commands:');
97
+ expect(output).toContain('Options:');
98
+ });
99
+ it.each([
100
+ 'start --help',
101
+ 'stop --help',
102
+ 'restart --help',
103
+ 'status --help',
104
+ 'logs --help',
105
+ 'install --help',
106
+ 'uninstall --help',
107
+ 'config --help',
108
+ 'setup --help',
109
+ 'user --help',
110
+ 'mount --help',
111
+ 'update --help',
112
+ 'cockpit --help',
113
+ 'host --help',
114
+ ])('should pass "%s" through Node CLI', (commandWithArgs) => {
115
+ const output = execSync(`node ${NODE_CLI_PATH} ${commandWithArgs}`, {
116
+ encoding: 'utf-8',
117
+ });
118
+ // All help outputs should contain "Usage:" and describe the command
119
+ expect(output).toContain('Usage:');
120
+ });
121
+ });
122
+ });
123
+ //# sourceMappingURL=cli-parity.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-parity.test.js","sourceRoot":"","sources":["../src/cli-parity.test.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,8 @@
2
2
  /**
3
3
  * opencode-cloud Node.js CLI
4
4
  *
5
- * DEPRECATED: This package is deprecated. Please install via cargo instead.
5
+ * Resolves the platform-specific binary from optionalDependencies,
6
+ * with fallback to local bin/ for development.
6
7
  */
7
8
  export {};
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;GAIG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
package/dist/index.js CHANGED
@@ -2,24 +2,105 @@
2
2
  /**
3
3
  * opencode-cloud Node.js CLI
4
4
  *
5
- * DEPRECATED: This package is deprecated. Please install via cargo instead.
5
+ * Resolves the platform-specific binary from optionalDependencies,
6
+ * with fallback to local bin/ for development.
6
7
  */
7
- const RED = "\x1b[31m";
8
- const YELLOW = "\x1b[33m";
9
- const CYAN = "\x1b[36m";
10
- const RESET = "\x1b[0m";
11
- const BOLD = "\x1b[1m";
12
- console.error(`
13
- ${YELLOW}${BOLD}Notice:${RESET} The npm package for opencode-cloud is deprecated.
14
-
15
- Please install via cargo instead:
16
-
17
- ${CYAN}cargo install opencode-cloud${RESET}
18
-
19
- This provides a native binary with better performance and full feature support.
20
-
21
- ${RED}Requires:${RESET} Rust 1.85+ (install from https://rustup.rs)
22
- `);
23
- process.exit(1);
24
- export {};
8
+ import { spawn, execSync } from 'child_process';
9
+ import { existsSync } from 'fs';
10
+ import { fileURLToPath } from 'url';
11
+ import { dirname, join } from 'path';
12
+ import { createRequire } from 'module';
13
+ const require = createRequire(import.meta.url);
14
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
15
+ /**
16
+ * Detect if running on musl libc (Alpine Linux)
17
+ */
18
+ function isMusl() {
19
+ if (existsSync('/etc/alpine-release')) {
20
+ return true;
21
+ }
22
+ try {
23
+ const out = execSync('ldd --version 2>&1', { encoding: 'utf-8' });
24
+ return out.includes('musl');
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * Get the platform package name for the current environment
32
+ */
33
+ function getPlatformPackage() {
34
+ const { platform, arch } = process;
35
+ if (platform === 'darwin') {
36
+ return arch === 'arm64'
37
+ ? '@opencode-cloud/cli-node-darwin-arm64'
38
+ : '@opencode-cloud/cli-node-darwin-x64';
39
+ }
40
+ if (platform === 'linux') {
41
+ const musl = isMusl();
42
+ if (arch === 'x64') {
43
+ return musl
44
+ ? '@opencode-cloud/cli-node-linux-x64-musl'
45
+ : '@opencode-cloud/cli-node-linux-x64';
46
+ }
47
+ if (arch === 'arm64') {
48
+ return musl
49
+ ? '@opencode-cloud/cli-node-linux-arm64-musl'
50
+ : '@opencode-cloud/cli-node-linux-arm64';
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ /**
56
+ * Resolve path to the occ binary
57
+ */
58
+ function resolveBinaryPath() {
59
+ const platformPkg = getPlatformPackage();
60
+ if (platformPkg) {
61
+ try {
62
+ const pkg = require(platformPkg);
63
+ if (pkg.binaryPath && existsSync(pkg.binaryPath)) {
64
+ return pkg.binaryPath;
65
+ }
66
+ }
67
+ catch {
68
+ // Package not installed, try fallback
69
+ }
70
+ }
71
+ const localBinary = join(scriptDir, '..', 'bin', 'occ');
72
+ if (existsSync(localBinary)) {
73
+ return localBinary;
74
+ }
75
+ return null;
76
+ }
77
+ const binaryPath = resolveBinaryPath();
78
+ if (!binaryPath) {
79
+ const platformPkg = getPlatformPackage();
80
+ console.error('Error: Could not find opencode-cloud binary\n');
81
+ console.error(`Platform: ${process.platform} (${process.arch})`);
82
+ if (platformPkg) {
83
+ console.error(`Expected package: ${platformPkg}\n`);
84
+ console.error('This may indicate a failed npm install. Try:');
85
+ console.error(' npm install opencode-cloud\n');
86
+ }
87
+ else {
88
+ console.error('\nYour platform is not supported with prebuilt binaries.');
89
+ console.error('Install the Rust CLI directly:');
90
+ console.error(' cargo install opencode-cloud\n');
91
+ }
92
+ process.exit(1);
93
+ }
94
+ const child = spawn(binaryPath, process.argv.slice(2), {
95
+ stdio: 'inherit',
96
+ });
97
+ child.on('close', (code) => {
98
+ process.exit(code ?? 1);
99
+ });
100
+ child.on('error', (err) => {
101
+ console.error(`Error: Failed to spawn binary at ${binaryPath}`);
102
+ console.error(`Error: ${err.message}\n`);
103
+ console.error('Try reinstalling: npm install opencode-cloud');
104
+ process.exit(1);
105
+ });
25
106
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH,MAAM,GAAG,GAAG,UAAU,CAAC;AACvB,MAAM,MAAM,GAAG,UAAU,CAAC;AAC1B,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,IAAI,GAAG,SAAS,CAAC;AAEvB,OAAO,CAAC,KAAK,CAAC;EACZ,MAAM,GAAG,IAAI,UAAU,KAAK;;;;IAI1B,IAAI,+BAA+B,KAAK;;;;EAI1C,GAAG,YAAY,KAAK;CACrB,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opencode-cloud",
3
- "version": "1.0.10",
4
- "description": "CLI for managing opencode as a persistent cloud service",
3
+ "version": "3.1.1",
4
+ "description": "Cross-platform CLI for opencode-cloud (includes prebuilt binaries)",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "pRizz",
@@ -26,6 +26,10 @@
26
26
  "opencode-cloud": "./dist/index.js",
27
27
  "occ": "./dist/index.js"
28
28
  },
29
+ "files": [
30
+ "dist",
31
+ "bin"
32
+ ],
29
33
  "engines": {
30
34
  "node": ">=20.0.0"
31
35
  },
@@ -37,15 +41,23 @@
37
41
  "x64",
38
42
  "arm64"
39
43
  ],
40
- "dependencies": {
41
- "@opencode-cloud/core": "1.0.10"
44
+ "optionalDependencies": {
45
+ "@opencode-cloud/cli-node-darwin-arm64": "3.0.0",
46
+ "@opencode-cloud/cli-node-linux-arm64": "3.0.0",
47
+ "@opencode-cloud/cli-node-darwin-x64": "3.0.0",
48
+ "@opencode-cloud/cli-node-linux-x64": "3.0.0",
49
+ "@opencode-cloud/cli-node-linux-arm64-musl": "3.0.0",
50
+ "@opencode-cloud/cli-node-linux-x64-musl": "3.0.0"
42
51
  },
43
52
  "devDependencies": {
44
53
  "typescript": "^5.7.3",
45
- "@types/node": "^22.10.7"
54
+ "@types/node": "^22.10.7",
55
+ "vitest": "^3.0.0"
46
56
  },
47
57
  "scripts": {
48
58
  "build": "tsc || (echo \"Error: TypeScript compiler (tsc) not found. Install dev dependencies or run npm i -D typescript before building.\" && exit 1)",
49
- "start": "node dist/index.js"
59
+ "start": "node dist/index.js",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest"
50
62
  }
51
63
  }
package/src/index.ts DELETED
@@ -1,26 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * opencode-cloud Node.js CLI
4
- *
5
- * DEPRECATED: This package is deprecated. Please install via cargo instead.
6
- */
7
-
8
- const RED = "\x1b[31m";
9
- const YELLOW = "\x1b[33m";
10
- const CYAN = "\x1b[36m";
11
- const RESET = "\x1b[0m";
12
- const BOLD = "\x1b[1m";
13
-
14
- console.error(`
15
- ${YELLOW}${BOLD}Notice:${RESET} The npm package for opencode-cloud is deprecated.
16
-
17
- Please install via cargo instead:
18
-
19
- ${CYAN}cargo install opencode-cloud${RESET}
20
-
21
- This provides a native binary with better performance and full feature support.
22
-
23
- ${RED}Requires:${RESET} Rust 1.85+ (install from https://rustup.rs)
24
- `);
25
-
26
- process.exit(1);
package/tsconfig.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "outDir": "./dist",
7
- "rootDir": "./src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "declaration": true,
13
- "declarationMap": true,
14
- "sourceMap": true
15
- },
16
- "include": ["src/**/*"],
17
- "exclude": ["node_modules", "dist"]
18
- }