Skip to content

Repository files navigation

⚠️ Warning: This project is not yet stable and may undergo significant changes before reaching version 1.0.0. We strongly advise against using it in production environments.

DashScript

GitHub Contributor Covenant

TypeScript ergonomics, Rust performance, compiled to native. A typed, TypeScript-flavored language (.ts) that compiles to native binaries via idiomatic Rust (wasm / napi outputs planned). Write TypeScript-flavored code, reuse oxc for parsing, with ds check / ds fmt built on its AST in-process, ds build / ds run caching builds in-project, dependencies declared in a package.json that lowers to Cargo.toml, and type hints for any Rust crate drawn straight from its source.

Packages

Package Version Description
dashscript npm The ds toolchain in one package — translates oxc AST → Rust, package.jsonCargo.toml, bindgen, CLI, editor types.

Quick Start

Install

# one package — provides the `ds` command
$ pnpm add -g dashscript

# or as a standalone binary
$ cargo install dashscript

No separate Rust install. DashScript manages its own pinned Rust toolchain — downloaded on first use like an npm dependency — so pnpm add dashscript is all you need.

Write .ts, compile to a native binary

// main.ts — TypeScript-flavored source
function greet(name: string): string {
  return `Hello, ${name}!`;
}

const message: string = greet("DashScript");
$ ds main.ts                      # run a file directly (like `node a.js`)
$ ds build main.ts                # → dist/<name> — a native binary (default)
$ ds build main.ts --target rust  # → dist/<name>/ — the translated Rust crate

ds main.ts runs a .ts file directly — translate → compile (cached) → run, like node a.js. ds build parses the .ts file with oxc, translates the AST to idiomatic Rust, then compiles it with cargo and ships a native binary in dist/<name> — the way vp pack ships a runnable artifact, not an intermediate project. Pass --target rust to stop at the translated Rust crate instead:

// generated by DashScript (--target rust)
fn greet(name: &str) -> String {
    format!("Hello, {name}!")
}

fn main() {
    let message: String = greet("DashScript");
}

Run

$ ds run <script>    # run a package.json script (like `pnpm run`)

ds run runs a shell command from package.json scripts ("start": "ds main.ts", "test": "cargo test", …) through the system shell, like pnpm run. (ds run is always explicit — running a file is ds <file.ts>.)

Declare dependencies — package.jsonCargo.toml

DashScript projects use a package.json — the one manifest every JS tool already reads. Standard npm fields map straight to cargo: bin (package.json bin → cargo [[bin]]) declares a project's executables, so one project compiles to several binaries; main[lib]; Rust crate deps under dashscript.cargo.dependencies[dependencies] (npm dependencies stay JS deps and never reach Cargo.toml); dashscript.cargo.devDependencies[dev-dependencies]. On ds build, the package is translated into a Cargo.toml:

{
  "name": "my-app",
  "bin": {
    "serve": "serve.ts",
    "migrate": "migrate.ts"
  },
  "dashscript": {
    "target": "bin",
    "cargo": {
      "dependencies": {
        "serde": "1.0",
        "tokio": "1.0"
      }
    }
  }
}

Use a Rust crate with full type hints

# fetch the crate — no .d.ts stub; types come straight from the crate source
$ ds add cargo:serde

ds add cargo:<crate> fetches the crate via cargo and records it in package.json, but generates no .d.ts stub — Rust is statically typed, so the crate's own source (in ~/.cargo) is the complete type truth, read directly by the editor the way rust-analyzer reads its deps. For a local Rust file, ds add <file>.rs runs bindgen to emit a .d.ts declaration beside it. There is no separate ds gen step.

Check & format

A .ts source is parsed with oxc_parser. ds check is the composite — translatability plus a format check, the way vp check lints + checks formatting; ds lint checks translatability alone; ds fmt formats in place. With no argument each runs over every .ts in the project (like vp check / oxlint), and ds check --fix writes the formatting fix instead of just reporting it. All built in-process on the parsed AST (no external oxlint/oxfmt dependency):

$ ds check          # lint + format check, whole project (like `vp check`)
$ ds check --fix    # ...and write formatting fixes
$ ds lint           # translatability check only
$ ds fmt            # format every .ts in place

The emitted Rust is finally verified with cargo check / cargo clippy on the generated project.

Roadmap

DashScript maps a TypeScript-flavored surface to Rust semantics, growing incrementally as real demand drives each mapping — never speculatively.

  • Language coverage — the full Rust type/memory-safety model (ownership, borrowing, lifetimes, traits), with TypeScript as the presentation only. Today: a safe TS→Rust subset (auto clone/borrow/narrowing bridge the gaps).
  • Standard libraries — ES built-ins (Math/String/Array/Object/Number, …), then the node: stdlib (node:crypto, node:zlib, node:fs, …) and Web APIs (fetch, DOM, …).
  • Compatibility — degrade, don't reject — a construct the static translator can't lower runs under an embedded QuickJS engine at the function granularity (inheriting full ECMAScript semantics) instead of failing, so existing TS/JS keeps working without a rewrite. This is also DashScript's path to WinterTC (Ecma TC55) — the Minimum Common Web Platform API shared by Node, Deno, Bun, and Cloudflare Workers: the ECMAScript core via the engine, the Web APIs via Rust crates.
  • More outputswasm and napi targets (Rust compiled to WebAssembly / napi-rs), so .ts ships to the web and Node ecosystems.
  • Developer experienceds test, editor/LSP integration, conformance fixtures.
  • Self-hosting (north star) — rewrite the toolchain in .ts itself, reaching oxc (and any Rust crate) through bindgen.

Development

Prerequisites

  • Node.js 18.x or higher
  • pnpm 9.x or higher (recommended package manager)
  • Rust — managed by DashScript (a pinned toolchain is downloaded on demand); no separate install needed to use DashScript
  • Git for version control

Getting Started

  1. Clone the repository:

    git clone https://github.com/DemoMacro/dashscript.git
    cd dashscript
  2. Install dependencies:

    pnpm install
  3. Build all packages:

    pnpm build

Development Commands

pnpm build                       # Build all packages
cd packages/<pkg> && pnpm build  # Build one package
vp check                         # Lint & format

Contributing

We welcome contributions! See CONTRIBUTING.md for the full contribution workflow, coding standards, and PR checklist.

Support & Community

License

This project is licensed under the MIT License - see the LICENSE file for details.


Built with ❤️ by Demo Macro

About

TypeScript ergonomics, Rust performance, compiled to native.

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages