@tishlang/tish 1.3.0 → 1.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  [Tish](https://github.com/tishlang/tish) is a minimal TypeScript/JavaScript–compatible language: run with an interpreter, use a REPL, or build native binaries and other targets.
4
4
 
5
- This npm package ships the **Tish CLI** for Node.js **22+**. It includes platform-specific native binaries; the `tish` command picks the right one for your OS and CPU.
5
+ This npm package ships the **Tish CLI**. It includes platform-specific native binaries under `platform/`; **`npm install`** runs `postinstall`, which copies the correct binary to `bin/tish`. That file is what runs when you invoke `tish` the CLI itself is native, not Node. Node **22+** is required for install scripts and tooling (e.g. semantic-release in this repo); the `tish` binary has no Node runtime dependency.
6
6
 
7
7
  ## Install
8
8
 
package/bin/.gitkeep ADDED
File without changes
package/bin/tish ADDED
Binary file
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "tishlang"
3
- version = "1.3.0"
3
+ version = "1.3.1"
4
4
  edition = "2021"
5
5
  description = "Tish CLI - run, REPL, compile to native"
6
6
  license-file = { workspace = true }
@@ -77,6 +77,20 @@ pub(crate) enum Commands {
77
77
  },
78
78
  }
79
79
 
80
+ /// `tish script.tish` → insert `run` so it matches `tish run script.tish` (npx / npm UX).
81
+ fn argv_with_implicit_run(mut argv: Vec<String>) -> Vec<String> {
82
+ if argv.len() >= 2 {
83
+ let first = argv[1].as_str();
84
+ const SUBCOMMANDS: &[&str] = &["run", "repl", "build", "dump-ast"];
85
+ let looks_like_file =
86
+ !first.starts_with('-') && !SUBCOMMANDS.iter().any(|&s| s == first);
87
+ if looks_like_file {
88
+ argv.insert(1, "run".to_string());
89
+ }
90
+ }
91
+ argv
92
+ }
93
+
80
94
  fn main() {
81
95
  let no_opt_env = std::env::var_os("TISH_NO_OPTIMIZE")
82
96
  .map(|v| v == "1" || v == "true" || v == "yes")
@@ -93,7 +107,8 @@ fn main() {
93
107
  return;
94
108
  }
95
109
 
96
- let cli = Cli::parse();
110
+ let argv = argv_with_implicit_run(argv);
111
+ let cli = Cli::parse_from(argv);
97
112
  let result = match cli.command {
98
113
  Some(Commands::Run(a)) => run_file(&a.file, &a.backend, &a.features, a.no_optimize || no_opt_env),
99
114
  Some(Commands::Repl(a)) => run_repl(&a.backend, a.no_optimize || no_opt_env),
@@ -577,7 +592,30 @@ fn build_file(
577
592
  mod cli_tests {
578
593
  use clap::Parser;
579
594
 
580
- use super::{Cli, Commands};
595
+ use super::{argv_with_implicit_run, Cli, Commands};
596
+
597
+ #[test]
598
+ fn implicit_run_inserts_run_before_file() {
599
+ let argv = argv_with_implicit_run(vec![
600
+ "tish".to_string(),
601
+ "hello.tish".to_string(),
602
+ ]);
603
+ let cli = Cli::try_parse_from(argv).unwrap();
604
+ match cli.command {
605
+ Some(Commands::Run(a)) => assert_eq!(a.file, "hello.tish"),
606
+ _ => panic!("expected Run"),
607
+ }
608
+ }
609
+
610
+ #[test]
611
+ fn explicit_subcommand_not_treated_as_file() {
612
+ let argv = argv_with_implicit_run(vec![
613
+ "tish".to_string(),
614
+ "repl".to_string(),
615
+ ]);
616
+ let cli = Cli::try_parse_from(argv).unwrap();
617
+ assert!(matches!(cli.command, Some(Commands::Repl(_))));
618
+ }
581
619
 
582
620
  #[test]
583
621
  fn build_js_target_parses() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tishlang/tish",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Tish - minimal TS/JS-compatible language. Run, REPL, build to native or other targets.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {
@@ -11,10 +11,14 @@
11
11
  "access": "public"
12
12
  },
13
13
  "bin": {
14
- "tish": "./bin/tish.js"
14
+ "tish": "./bin/tish"
15
+ },
16
+ "scripts": {
17
+ "postinstall": "node scripts/install-bin.js"
15
18
  },
16
19
  "files": [
17
20
  "bin",
21
+ "scripts/install-bin.js",
18
22
  "platform",
19
23
  "README.md",
20
24
  "LICENSE",
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Copy platform/<os>-<arch>/tish to bin/tish so the npm bin is the native binary.
6
+ * Runs on postinstall and before npm pack in CI.
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ const platformKey = `${process.platform}-${process.arch}`;
13
+ const binaryName = process.platform === 'win32' ? 'tish.exe' : 'tish';
14
+
15
+ const root = path.join(__dirname, '..');
16
+ const src = path.join(root, 'platform', platformKey, binaryName);
17
+ const dest = path.join(root, 'bin', 'tish');
18
+
19
+ if (!fs.existsSync(src)) {
20
+ if (process.env.TISH_NPM_PACK_REQUIRE === '1') {
21
+ console.error(`[tish] No prebuilt binary for this platform: ${platformKey}`);
22
+ console.error(`[tish] Expected: ${src}`);
23
+ process.exit(1);
24
+ }
25
+ console.warn(`[tish] Skipping native bin (not found for ${platformKey}): ${src}`);
26
+ console.warn('[tish] From repo root run: ./npm/scripts/build-binaries.sh — then: node npm/tish/scripts/install-bin.js');
27
+ process.exit(0);
28
+ }
29
+
30
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
31
+ fs.copyFileSync(src, dest);
32
+ try {
33
+ fs.chmodSync(dest, 0o755);
34
+ } catch (_) {
35
+ /* Windows may ignore chmod */
36
+ }
package/bin/tish.js DELETED
@@ -1,32 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const path = require('path');
5
- const fs = require('fs');
6
- const { spawnSync } = require('child_process');
7
-
8
- const platformKey = `${process.platform}-${process.arch}`;
9
- const supported = ['darwin-arm64', 'darwin-x64', 'linux-x64', 'linux-arm64', 'win32-x64'];
10
- const binaryName = process.platform === 'win32' ? 'tish.exe' : 'tish';
11
-
12
- const binPath = path.join(__dirname, '..', 'platform', platformKey, binaryName);
13
- if (!fs.existsSync(binPath)) {
14
- console.error(`[tish] Unsupported or missing binary for platform: ${platformKey}`);
15
- console.error('Supported:', supported.join(', '));
16
- console.error('Build from source: https://github.com/tishlang/tish');
17
- process.exit(1);
18
- }
19
-
20
- // Convenience: "npx @tishlang/tish FILE [args]" → "tish run FILE [args]"
21
- const args = process.argv.slice(2);
22
- const subcommands = ['run', 'repl', 'build', 'dump-ast'];
23
- const first = args[0];
24
- const looksLikeFile = first && !first.startsWith('-') && !subcommands.includes(first);
25
-
26
- const finalArgs = looksLikeFile ? ['run', ...args] : args;
27
-
28
- const result = spawnSync(binPath, finalArgs, {
29
- stdio: 'inherit',
30
- windowsHide: true,
31
- });
32
- process.exit(result.status !== null ? result.status : 1);