diff --git a/.clinerules b/.clinerules deleted file mode 100644 index 04ec2df..0000000 --- a/.clinerules +++ /dev/null @@ -1,5 +0,0 @@ -# Project Guidelines - -## Documentation Requirements - -- Keep README.md in sync with new capabilities diff --git a/.github/workflows/ci-steps.yml b/.github/workflows/ci-steps.yml index bb106eb..4657318 100644 --- a/.github/workflows/ci-steps.yml +++ b/.github/workflows/ci-steps.yml @@ -75,7 +75,7 @@ jobs: path: | ~/.cache/mise ~/.local/share/mise - key: mise-${{ runner.os }}-${{ inputs.cache_suffix }}-${{ hashFiles('mise.toml', 'template/mise.toml.jinja', 'devbox.json', 'devbox.lock') }} + key: mise-${{ runner.os }}-${{ inputs.cache_suffix }}-${{ hashFiles('mise.toml', 'template/mise.toml.jinja') }} restore-keys: | mise-${{ runner.os }}-${{ inputs.cache_suffix }}- mise-${{ runner.os }}- @@ -89,24 +89,24 @@ jobs: run: | echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV + - name: Run dev-setup.sh + run: | + ./scripts/dev-setup.sh + - name: Setup mise uses: jdx/mise-action@v2 with: install: true cache: true - - name: Setup Devbox - uses: jetify-com/devbox-install-action@v0.11.0 - with: - enable-cache: true - - name: Generate Test Project run: | - devbox run copier copy . ../test-project --vcs-ref HEAD \ + copier copy . ../test-project --vcs-ref HEAD \ --data project_name="Test Project" \ --data project_slug=test-project \ --data project_slug_underscore=test_project \ --data author_name="CI Bot" \ + --data github_username="ci-bot" \ --data include_wasm=${{ inputs.wasm }} \ --data include_python=${{ inputs.python }} \ --data include_go=${{ inputs.go }} \ @@ -116,5 +116,6 @@ jobs: working-directory: ../test-project run: | git init - devbox install - devbox run just setup copyright ci + ./scripts/dev-setup.sh + mise install + just setup copyright ci diff --git a/.gitignore b/.gitignore index a4515dd..4d67604 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -.devbox *.code-workspace diff --git a/README.md b/README.md index d83fbd0..0b90f6c 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ Python extensions, and Go bindings from a single codebase. To use this template, you need to install the following tools: -- **[Devbox](https://www.jetify.com/docs/devbox/):** Sets up your development - environment by installing Rust, wasm‑pack, Node, PNPM, and Mise automatically. +- **[Mise](https://mise.jdx.dev/):** Installs and manages Rust, Node, Python, PNPM, and every other tool used by this template. + If you don't have Mise yet, simply run `scripts/dev-setup.sh` and follow the prompts. - **[Copier](https://copier.readthedocs.io/):** Generates a new project from this template. @@ -50,11 +50,11 @@ git init jj git init --colocate ``` -Enter the Devbox shell: +Install dependencies (Mise will take care of everything): ```bash -devbox install -devbox run direnv allow +./scripts/dev-setup.sh # one-time, installs mise if missing +mise install # installs the toolchain versions specified in mise.toml ``` Set up tools: @@ -77,8 +77,8 @@ just ci ## Development Tools & Workflow -The template provides a comprehensive development environment powered by Devbox -and Mise. No manual tool installation required—everything from Rust nightly to +The template provides a comprehensive development environment powered by Mise. +No manual tool installation required—everything from Rust nightly to WebAssembly toolchains is automatically configured. **Testing & Quality** Comprehensive test suites run across all platforms, with @@ -144,8 +144,7 @@ Your generated project will include: **Development Environment** -- `devbox.json`: Zero-config development environment -- `mise.toml`: Task runner for common operations +- `mise.toml`: Toolchain configuration and common operations - `.envrc`: Automatic environment activation - `.pre-commit-config.yaml`: Git hooks for quality checks @@ -153,19 +152,20 @@ Your generated project will include: ```plain cd ~/workplace && \ - rm -rf ~/workplace/ouchie && \ - copier copy ~/workplace/copier_rust_template ~/workplace/ouchie \ + rm -rf ~/workplace/foobaz && \ + copier copy ~/workplace/copier_rust_template ~/workplace/foobaz \ --data include_wasm=true \ --data include_python=true \ --data include_go=true \ - --data project_name="Ouchie" \ - --data project_slug=ouchie \ - --data project_slug_underscore=ouchie \ + --data project_name="Foobaz" \ + --data project_slug=foobaz \ + --data project_slug_underscore=foobaz \ --data author_name="Local Test" \ --force && \ - cd ~/workplace/ouchie && \ + cd ~/workplace/foobaz && \ git init && \ - devbox install && \ + ./scripts/dev-setup.sh && \ + mise install && \ just setup copyright ci ; \ cd go-wasm && \ just setup test test-go && \ diff --git a/copier.yml b/copier.yml index 8281757..b0bcc61 100644 --- a/copier.yml +++ b/copier.yml @@ -36,6 +36,11 @@ author_name: help: "Enter the author's name." default: "Your Name" +github_username: + type: str + help: "Enter your GitHub username." + default: "your-username" + _exclude: - ".git" - "__skip_wasm__" diff --git a/devbox.json b/devbox.json deleted file mode 100644 index 7d563a8..0000000 --- a/devbox.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.7/.schema/devbox.schema.json", - "packages": [ - "copier@latest", - "mise@latest" - ], - "shell": { - "init_hook": [ - "echo 'Welcome to devbox!' > /dev/null" - ], - "scripts": { - "test": [ - "echo \"Error: no test specified\" && exit 1" - ] - } - } -} diff --git a/devbox.lock b/devbox.lock deleted file mode 100644 index d133f73..0000000 --- a/devbox.lock +++ /dev/null @@ -1,117 +0,0 @@ -{ - "lockfile_version": "1", - "packages": { - "copier@latest": { - "last_modified": "2025-02-03T20:50:02Z", - "resolved": "github:NixOS/nixpkgs/494b2407ef95997176211a8758638205916873a9#copier", - "source": "devbox-search", - "version": "9.4.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/yzy367xiwvi73kmpcx27gcpsfax0c13j-copier-9.4.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/hah6lvv6bd96w5his88yjn7y0pv5ak2p-copier-9.4.1-dist" - } - ], - "store_path": "/nix/store/yzy367xiwvi73kmpcx27gcpsfax0c13j-copier-9.4.1" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/jimrvrcq22vwqzpprfg2fkzgq8jfkxy0-copier-9.4.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/xhvhkkyx41f4s5hwyb64ic834mvdzsdd-copier-9.4.1-dist" - } - ], - "store_path": "/nix/store/jimrvrcq22vwqzpprfg2fkzgq8jfkxy0-copier-9.4.1" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/yxyrrqah4yzd8fv289mcmms8rlbsfgyh-copier-9.4.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/zyfc2a04nh7n4yp4pz5xr7sk2na876fd-copier-9.4.1-dist" - } - ], - "store_path": "/nix/store/yxyrrqah4yzd8fv289mcmms8rlbsfgyh-copier-9.4.1" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/nvgx23q73f8p36jh60n54mgjpi5xblai-copier-9.4.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/42ydxc1xfs9pzriixxrnmdvxlx7fl5kd-copier-9.4.1-dist" - } - ], - "store_path": "/nix/store/nvgx23q73f8p36jh60n54mgjpi5xblai-copier-9.4.1" - } - } - }, - "mise@latest": { - "last_modified": "2025-02-07T11:26:36Z", - "resolved": "github:NixOS/nixpkgs/d98abf5cf5914e5e4e9d57205e3af55ca90ffc1d#mise", - "source": "devbox-search", - "version": "2025.2.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/8fhc7i1i2k5r67v51yj3b78wgzm7qlba-mise-2025.2.0", - "default": true - } - ], - "store_path": "/nix/store/8fhc7i1i2k5r67v51yj3b78wgzm7qlba-mise-2025.2.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/kyvzkvgvaakp796xxk8mi61mbyfr5fiq-mise-2025.2.0", - "default": true - } - ], - "store_path": "/nix/store/kyvzkvgvaakp796xxk8mi61mbyfr5fiq-mise-2025.2.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/5mp0bq3kfmpjyilbhbqjcalj6jk4r6y3-mise-2025.2.0", - "default": true - } - ], - "store_path": "/nix/store/5mp0bq3kfmpjyilbhbqjcalj6jk4r6y3-mise-2025.2.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/lln0ycm6yg5v6h1bz16ydgaqiyijg3vl-mise-2025.2.0", - "default": true - } - ], - "store_path": "/nix/store/lln0ycm6yg5v6h1bz16ydgaqiyijg3vl-mise-2025.2.0" - } - } - } - } -} diff --git a/mise.toml b/mise.toml index 6652a62..43d6650 100644 --- a/mise.toml +++ b/mise.toml @@ -1,2 +1,3 @@ [tools] +copier = "latest" python = "prefix:3.12" diff --git a/scripts/dev-setup.sh b/scripts/dev-setup.sh new file mode 100755 index 0000000..9359901 --- /dev/null +++ b/scripts/dev-setup.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Install mise +if command -v mise >/dev/null 2>&1; then + echo "mise is already installed" +else + echo "mise is not installed" + if command -v brew >/dev/null 2>&1; then + echo "brew is installed" + brew install mise + else + echo "brew is not installed" + curl https://mise.run | sh + fi +fi + +mise settings add idiomatic_version_file_enable_tools rust + +# Need to install rust first +mise use "rust@prefix:1.87" \ No newline at end of file diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..349e75c --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) +ROOT_DIR=$(dirname "$SCRIPT_DIR") +pushd "$ROOT_DIR" +trap 'popd' EXIT + +cd ~/workplace + +rm -rf ~/workplace/foobaz +copier copy ~/workplace/copier_rust_template ~/workplace/foobaz \ + --data include_wasm=true \ + --data include_python=true \ + --data include_go=true \ + --data project_name="Foobaz" \ + --data project_slug=foobaz \ + --data project_slug_underscore=foobaz \ + --data author_name="Local Test" \ + --data github_username="local-test" \ + --force + +cd ~/workplace/foobaz +git init + +./scripts/dev-setup.sh +touch mise.lock +mise trust +mise install + +just setup copyright ci +cd go-wasm +just setup test test-go diff --git a/template/.cargo/config.toml b/template/.cargo/config.toml index 684c866..54fdc20 100644 --- a/template/.cargo/config.toml +++ b/template/.cargo/config.toml @@ -1,3 +1,14 @@ +[target.'cfg(not(build))'.build] +# Prevents unavoidable warnings from build.rs scripts from failing the build +rustflags = ["-D", "warnings"] + +[env] +RUST_BACKTRACE = "1" + +# Nextest configuration +[test] +runner = "cargo nextest" + [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", diff --git a/template/.clippy.toml b/template/.clippy.toml index e1236c6..56835be 100644 --- a/template/.clippy.toml +++ b/template/.clippy.toml @@ -1,3 +1,15 @@ -cognitive-complexity-threshold = 10 -too-many-arguments-threshold = 5 -type-complexity-threshold = 200 +msrv = "1.87.0" + +# ---------- Structural size limits ---------- +cognitive-complexity-threshold = 20 +enum-variant-size-threshold = 128 # bytes +excessive-nesting-threshold = 6 +future-size-threshold = 8192 # bytes; keeps async state small +too-many-arguments-threshold = 6 +too-many-lines-threshold = 100 # per-function and per-method +type-complexity-threshold = 200 + +# ---------- Misc quality-of-life ---------- +disallowed-methods = [ + "std::mem::transmute", +] diff --git a/template/.envrc b/template/.envrc deleted file mode 100644 index 2f05af9..0000000 --- a/template/.envrc +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# Automatically sets up your devbox environment whenever you cd into this -# directory via our direnv integration: - -eval "$(devbox generate direnv --print-envrc)" - -# check out https://www.jetpack.io/devbox/docs/ide_configuration/direnv/ -# for more details diff --git a/template/.github/workflows/ci.yml b/template/.github/workflows/ci.yml index 5389137..514b5e5 100644 --- a/template/.github/workflows/ci.yml +++ b/template/.github/workflows/ci.yml @@ -6,53 +6,120 @@ on: pull_request: branches: [main] -defaults: - run: - shell: bash +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 jobs: + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: jdx/mise-action@v2 + with: + experimental: true + - name: Cache cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-check + - name: Setup environment + run: just setup + - name: Check formatting + run: just check-format + - name: Check clippy + run: just check-clippy + - name: Check dependencies + run: just audit + test: - name: Test + name: Test Suite runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest] - + include: + - {os: ubuntu-latest , rust: stable} + - {os: ubuntu-latest , rust: nightly} + - {os: ubuntu-latest , rust: "1.87.0"} # MSRV + - {os: windows-latest, rust: stable} + - {os: macos-latest , rust: stable} steps: - uses: actions/checkout@v4 - - uses: jdx/mise-action@v2 with: - cache: true - - - name: Setup Devbox - uses: jetify-com/devbox-install-action@v0.11.0 + experimental: true + - name: Cache cargo + uses: actions/cache@v4 with: - enable-cache: true + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.rust }} + - name: Install Rust + run: rustup toolchain install ${{ matrix.rust }} --component rustfmt clippy miri + - name: Setup environment + run: just setup + - name: Run tests + run: just test + - name: Run doc tests + run: just test-doc + - name: Run miri (nightly only) + if: matrix.rust == 'nightly' + run: just test-miri + coverage: + name: Coverage + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: jdx/mise-action@v2 + with: + experimental: true - name: Cache cargo uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: ${{ runner.os }}-cargo- + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-coverage + - name: Setup environment + run: just setup + - name: Generate coverage + run: just coverage + - name: Upload to codecov + uses: codecov/codecov-action@v3 + with: + files: lcov.info + - name: Upload HTML report artifact + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: target/llvm-cov/html/ - - name: Cache pnpm dependencies + cross-compile: + name: Cross Compile + runs-on: ubuntu-latest + strategy: + matrix: + target: [x86_64-unknown-linux-musl, aarch64-unknown-linux-gnu] + steps: + - uses: actions/checkout@v4 + - uses: jdx/mise-action@v2 + with: + experimental: true + - name: Cache cargo uses: actions/cache@v4 with: path: | - ~/.pnpm-store - web/node_modules - key: ${{ runner.os }}-pnpm-${{ hashFiles('web/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-cross-${{ matrix.target }} + - name: Install cross + run: cargo install cross --locked - name: Setup environment - run: | - devbox run -- just setup - - - name: CI - run: devbox run -- just ci + run: just setup + - name: Cross compile and test + run: cross test --release --all-features --target ${{ matrix.target }} diff --git a/template/.gitignore b/template/.gitignore index 9b0a920..5ce0619 100644 --- a/template/.gitignore +++ b/template/.gitignore @@ -20,5 +20,4 @@ Cargo.lock # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ -.devbox .jj diff --git a/template/.pre-commit-config.yaml b/template/.pre-commit-config.yaml index c767827..529abd8 100644 --- a/template/.pre-commit-config.yaml +++ b/template/.pre-commit-config.yaml @@ -22,14 +22,14 @@ repos: hooks: - id: rust-fmt name: Rust formatter - entry: devbox run -- just rust-fmt + entry: just format types: [rust] language: system pass_filenames: false - - id: rust-check - name: Rust checker - entry: devbox run -- just rust-check + - id: rust-check-format + name: Rust format check + entry: just check-format types: [rust] language: system pass_filenames: false @@ -37,7 +37,7 @@ repos: - id: rust-clippy name: Rust clippy - entry: devbox run -- just rust-clippy + entry: just check-clippy types: [rust] language: system pass_filenames: false @@ -45,14 +45,14 @@ repos: - id: web-lint name: Web lint and format - entry: devbox run -- just web-lint + entry: just web-lint types: [javascript, ts, jsx, tsx] language: system pass_filenames: false - id: copyright-check name: Copyright check - entry: devbox run -- just copyright-check + entry: just copyright-check types: [rust, javascript, ts, jsx, tsx] language: system pass_filenames: false diff --git a/template/CHANGELOG.md b/template/CHANGELOG.md new file mode 100644 index 0000000..0b8e45c --- /dev/null +++ b/template/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Initial project structure +- Core library functionality +- CLI interface + +### Changed + +### Deprecated + +### Removed + +### Fixed + +### Security diff --git a/template/CONTRIBUTING.md b/template/CONTRIBUTING.md new file mode 100644 index 0000000..499284f --- /dev/null +++ b/template/CONTRIBUTING.md @@ -0,0 +1,56 @@ +# Contributing + +Thanks for your interest in contributing! + +## Quick Start + +Run `just check-all` before every PR to ensure your changes meet our quality standards. + +## Development Setup + +1. Install dependencies: + + ```bash + ./scripts/dev-setup.sh + mise install + ``` + +2. Set up the project: + + ```bash + just setup + ``` + +3. Run the development workflow: + + ```bash + just dev + ``` + +## Testing + +- Run all tests: `just test` +- Run with coverage: `just coverage` +- Run security audit: `just audit` + +## Code Style + +- Format code: `just format` +- Check formatting: `just check-format` +- Run clippy: `just check-clippy` + +## Submitting Changes + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Run `just check-all` to ensure quality +5. Submit a pull request + +## Code of Conduct + +Please be respectful and follow our community guidelines. + +## Questions? + +Feel free to open an issue for any questions or clarifications. diff --git a/template/Cargo.toml.jinja b/template/Cargo.toml.jinja index ae1e881..dcb06e2 100644 --- a/template/Cargo.toml.jinja +++ b/template/Cargo.toml.jinja @@ -21,3 +21,16 @@ resolver = "2" [profile.release] lto = true + +[workspace.lints.rust] +unsafe_code = "forbid" +missing_docs = "warn" + +[workspace.lints.clippy] +# Lint groups have lower priority than individual lints +all = { level = "warn", priority = -1 } +pedantic = { level = "warn", priority = -1 } +nursery = { level = "warn", priority = -1 } +# Individual lints with higher priority +unwrap_used = "deny" +expect_used = "deny" diff --git a/template/Justfile.jinja b/template/Justfile.jinja index eff40dc..cdbd558 100644 --- a/template/Justfile.jinja +++ b/template/Justfile.jinja @@ -18,11 +18,14 @@ mod go-wasm @default: @just --list +# ============================================================================= +# Setup and Dependencies +# ============================================================================= + setup: #!/usr/bin/env bash set -e - devbox install mise trust mise install @@ -37,12 +40,9 @@ setup: rustup toolchain install nightly rustup target add wasm32-wasip1 - cargo binstall cargo-llvm-cov --secure --no-confirm rustup component add llvm-tools-preview rustup component add rustfmt rustup component add clippy - cargo binstall cargo-nextest --secure --no-confirm - cargo binstall cargo-deny --secure --no-confirm pre-commit install pre-commit install-hooks @@ -61,7 +61,6 @@ mac-setup: fi brew install libiconv llvm - cargo binstall cargo-llvm-cov --secure --no-confirm rustup component add llvm-tools-preview rustup component add llvm-tools-preview --toolchain nightly-aarch64-apple-darwin if ! xcode-select -p >/dev/null 2>&1; then @@ -72,45 +71,84 @@ mac-setup: update-deps: cargo update -# Development tasks -watch: +# ============================================================================= +# Rust Development Tasks +# ============================================================================= + +# Development workflow +rust-dev: rust-format rust-clippy-fix rust-test + +# Watching for changes +rust-watch: cargo watch -x check -x test -# Rust tasks -rust-check: - cargo check --all-targets +# Formatting +rust-check-format: + cargo fmt -- --check + +rust-format: + cargo fmt +# Linting +rust-check-clippy: + cargo clippy --all-targets --all-features -- -D warnings + +rust-clippy-fix: + cargo clippy --all-targets --all-features --fix -- -D warnings + +# Testing rust-test: - cargo nextest run --all-targets --no-fail-fast - cargo test --doc --no-fail-fast + cargo nextest run --all-features + +rust-test-doc: + cargo test --doc -rust-doc: - cargo doc --no-deps --document-private-items +# Miri testing (only on marked tests to avoid long wall-clock hits) +rust-test-miri: + RUSTFLAGS="-Zmiri-strict-provenance" cargo +nightly miri test -- --ignored +# Coverage +rust-coverage: + cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + cargo llvm-cov report --html + +rust-coverage-ci: + cargo llvm-cov --all-features --workspace + # cargo llvm-cov --all-features --workspace --fail-under-lines 80 + +# Security & Dependencies rust-audit: - cargo audit || exit 1 - cargo deny check || exit 1 + cargo audit + cargo deny check + +# MSRV verification +rust-msrv-check: + cargo msrv verify + +# Feature matrix testing +rust-hack-check: + cargo hack test --each-feature --no-dev-deps +# Building rust-build: cargo build -rust-fmt: - cargo fmt --all - -rust-clippy: - cargo clippy --all-targets -- -D warnings +rust-build-release: + cargo build --release +# Cleaning rust-clean: cargo clean -copyright: - mise x -- bash -c 'fd -e rs -e ts -e js -e jsx -e tsx -e go -e py | xargs addlicense -f copyright.tmpl -c "{{ author_name }}" -v -s' +# Run all Rust checks (use in CI and pre-commit) +rust-check-all: rust-check-format rust-check-clippy rust-test rust-coverage-ci rust-audit -copyright-check: - mise x -- bash -c 'fd -e rs -e ts -e js -e jsx -e tsx -e go -e py | xargs addlicense -f copyright.tmpl -c "{{ author_name }}" -v -s -check' +# ============================================================================= +# Cross-Language Tasks (All Languages) +# ============================================================================= -# Combined tasks -check: rust-check rust-fmt rust-clippy rust-audit copyright-check +# Combined linting across all languages +lint-all: rust-check-clippy copyright-check {%- if include_wasm %} just web lint {%- endif %} @@ -122,7 +160,8 @@ check: rust-check rust-fmt rust-clippy rust-audit copyright-check just go-wasm lint {%- endif %} -test: rust-test +# Combined testing across all languages +test-all: rust-test {%- if include_wasm %} just web test {%- endif %} @@ -134,27 +173,8 @@ test: rust-test just go-wasm test {%- endif %} -cov: - #!/usr/bin/env bash - set -e - - if [[ "$OSTYPE" == "darwin"* ]]; then - cargo +nightly llvm-cov nextest - else - cargo llvm-cov nextest - fi - -cov-local: - #!/usr/bin/env bash - set -e - - if [[ "$OSTYPE" == "darwin"* ]]; then - cargo +nightly llvm-cov nextest --no-fail-fast --text --show-missing-lines --mcdc - else - cargo llvm-cov nextest --no-fail-fast --text --show-missing-lines --mcdc - fi - -build: rust-build +# Combined building across all languages +build-all: rust-build rust-build-release {%- if include_wasm %} just web build {%- endif %} @@ -166,7 +186,8 @@ build: rust-build just go-wasm build {%- endif %} -clean: rust-clean +# Combined cleaning across all languages +clean-all: rust-clean {%- if include_wasm %} just web clean {%- endif %} @@ -178,10 +199,77 @@ clean: rust-clean just go-wasm clean {%- endif %} +# ============================================================================= +# Copyright and Legal +# ============================================================================= + +copyright: + mise x -- bash -c 'fd -e rs -e ts -e js -e jsx -e tsx -e go -e py | xargs addlicense -f copyright.tmpl -c "{{ author_name }}" -v -s' + +copyright-check: + mise x -- bash -c 'fd -e rs -e ts -e js -e jsx -e tsx -e go -e py | xargs addlicense -f copyright.tmpl -c "{{ author_name }}" -v -s -check' + +# ============================================================================= +# Development Workflows +# ============================================================================= + {% if include_wasm %} -web-dev: build +# Start web development (builds dependencies first) +web-dev: build-all just web dev {%- endif %} -# CI tasks -ci: build check test cov +# Development workflow for all languages +dev-all: rust-dev + {%- if include_wasm %} + just web dev & + {%- endif %} + {%- if include_python %} + just python dev & + {%- endif %} + {%- if include_go %} + just go dev & + {%- endif %} + wait + +# ============================================================================= +# CI and Release Tasks +# ============================================================================= + +# Full CI pipeline +ci: build-all lint-all test-all + +# Release preparation +release-prep: rust-check-all + git status + @echo "Ready for release if git status is clean" + +# ============================================================================= +# Legacy Aliases (for backwards compatibility) +# ============================================================================= + +# Legacy short aliases - prefer the explicit rust-* versions above +alias format := rust-format +alias clippy := rust-check-clippy +alias test := rust-test +alias build := rust-build +alias clean := rust-clean +alias dev := rust-dev +alias watch := rust-watch +alias audit := rust-audit + +# Legacy combined aliases - prefer the *-all versions above +alias check := lint-all +alias coverage := rust-coverage +alias cov := rust-coverage-ci + +# Legacy coverage with platform-specific handling +cov-local: + #!/usr/bin/env bash + set -e + + if [[ "$OSTYPE" == "darwin"* ]]; then + cargo +nightly llvm-cov nextest --no-fail-fast --text --show-missing-lines --mcdc + else + cargo llvm-cov nextest --no-fail-fast --text --show-missing-lines --mcdc + fi diff --git a/template/README.md.jinja b/template/README.md.jinja index 81878c2..dfab019 100644 --- a/template/README.md.jinja +++ b/template/README.md.jinja @@ -1,10 +1,116 @@ # {{ project_name }} -This project is generated from our multi-crate template. It contains: +

+ + CI Status + + + Coverage + + MSRV + + Crates.io + + + Documentation + + + License + +

-• A CLI binary crate -• A core library crate +{{ project_name }} is a multi-platform Rust project with: -You can build and run the CLI using Cargo commands from the workspace root. +- 🦀 **Core Library**: Shared functionality in `{{ project_slug }}-core` +- 🖥️ **CLI Tool**: Command-line interface in `{{ project_slug }}-cli` +{%- if include_wasm %} +- 🌐 **WebAssembly**: Browser-compatible WASM bindings +- 🎨 **Web Frontend**: TypeScript/React web interface +{%- endif %} +{%- if include_python %} +- 🐍 **Python Bindings**: Native Python extension module +{%- endif %} +{%- if include_go %} +- 🦫 **Go Bindings**: CGO-based Go library bindings +{%- endif %} -Happy coding! +## Quick Start + +### Prerequisites + +- **[Mise](https://mise.jdx.dev/)**: Manages all tools and dependencies +- **Git**: For version control + +### Installation + +1. **Clone and setup**: + ```bash + git clone https://github.com/{{ github_username }}/{{ project_slug }}.git + cd {{ project_slug }} + ./scripts/dev-setup.sh # Installs mise if needed + mise install # Installs all tools + ``` + +2. **Initialize the project**: + ```bash + just setup # Sets up development environment + just copyright # Adds copyright headers + ``` + +3. **Build and test**: + ```bash + just check-all # Run all quality checks + just build # Build all components + just test # Run test suite + ``` + +## Development + +### Available Commands + +- `just check-all` - Run all checks (formatting, linting, tests, coverage, audit) +- `just dev` - Development workflow (format, fix clippy issues, test) +- `just format` - Format code with rustfmt +- `just test` - Run test suite with nextest +- `just coverage` - Generate code coverage report +- `just audit` - Security and dependency audit +- `just release-prep` - Prepare for release + +### Project Structure + +``` +{{ project_slug }}/ +├── core/ # Core library ({{ project_slug }}-core) +├── cli/ # Command-line tool ({{ project_slug }}-cli) +{%- if include_wasm %} +├── wasm/ # WebAssembly bindings +├── web/ # Web frontend (TypeScript) +{%- endif %} +{%- if include_python %} +├── python/ # Python bindings +{%- endif %} +{%- if include_go %} +├── go/ # Go bindings +├── go-wasm/ # Go WebAssembly bindings +{%- endif %} +├── scripts/ # Development scripts +└── Justfile # Task runner configuration +``` + +## Contributing + +We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. + +### Development Workflow + +1. Fork the repository +2. Create a feature branch: `git checkout -b feature/amazing-feature` +3. Make your changes +4. Run quality checks: `just check-all` +5. Commit your changes: `git commit -m 'Add amazing feature'` +6. Push to the branch: `git push origin feature/amazing-feature` +7. Open a Pull Request + +## License + +This project is licensed under the Mozilla Public License 2.0 - see the [LICENSE](LICENSE) file for details. diff --git a/template/cli/Cargo.toml.jinja b/template/cli/Cargo.toml.jinja index bffcf98..3183934 100644 --- a/template/cli/Cargo.toml.jinja +++ b/template/cli/Cargo.toml.jinja @@ -2,8 +2,31 @@ name = "{{ project_slug }}-cli" version = "0.1.0" edition = "2021" +rust-version = "1.87.0" +authors = ["{{ author_name }}"] license = "MPL-2.0" +description = "Command-line interface for {{ project_name }}" +homepage = "https://github.com/{{ github_username }}/{{ project_slug }}" +repository = "https://github.com/{{ github_username }}/{{ project_slug }}" +documentation = "https://docs.rs/{{ project_slug }}-cli" +readme = "../README.md" +keywords = ["{{ project_slug }}", "cli"] +categories = ["command-line-utilities"] + +[dependencies] +{{ project_slug }}-core = { path = "../core" } [[bin]] name = "{{ project_slug }}-cli" path = "src/main.rs" + +[lints.rust] +unsafe_code = "forbid" +missing_docs = "warn" + +[lints.clippy] +all = "warn" +pedantic = "warn" +nursery = "warn" +unwrap_used = "deny" +expect_used = "deny" diff --git a/template/cli/src/main.rs.jinja b/template/cli/src/main.rs.jinja index 0d85d19..83a51c9 100644 --- a/template/cli/src/main.rs.jinja +++ b/template/cli/src/main.rs.jinja @@ -1,3 +1,12 @@ +// Copyright 2025 {{ author_name }} +// +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. +// +// SPDX-License-Identifier: MPL-2.0 + +//! Command-line interface for {{ project_name }}. + fn main() { println!("Welcome to {{ project_name }} CLI!"); } diff --git a/template/core/Cargo.toml.jinja b/template/core/Cargo.toml.jinja index f3bc4d3..b231aed 100644 --- a/template/core/Cargo.toml.jinja +++ b/template/core/Cargo.toml.jinja @@ -2,7 +2,16 @@ name = "{{ project_slug }}-core" version = "0.1.0" edition = "2021" +rust-version = "1.87.0" +authors = ["{{ author_name }}"] license = "MPL-2.0" +description = "Core library for {{ project_name }}" +homepage = "https://github.com/{{ github_username }}/{{ project_slug }}" +repository = "https://github.com/{{ github_username }}/{{ project_slug }}" +documentation = "https://docs.rs/{{ project_slug }}-core" +readme = "../README.md" +keywords = ["{{ project_slug }}", "core"] +categories = ["development-tools"] [dependencies] ariadne = "0.5.0" @@ -12,3 +21,14 @@ thiserror = "2.0" [lib] path = "src/lib.rs" crate-type = ["rlib", "cdylib"] + +[lints.rust] +unsafe_code = "forbid" +missing_docs = "warn" + +[lints.clippy] +all = "warn" +pedantic = "warn" +nursery = "warn" +unwrap_used = "deny" +expect_used = "deny" diff --git a/template/core/src/lib.rs.jinja b/template/core/src/lib.rs.jinja index 6df1e37..ef1c864 100644 --- a/template/core/src/lib.rs.jinja +++ b/template/core/src/lib.rs.jinja @@ -1,26 +1,54 @@ -// Copyright 2025 Local Test +// Copyright 2025 {{ author_name }} // // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. // If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 +//! Core library for {{ project_name }}. +//! +//! This library provides the core functionality for parsing and processing +//! arithmetic expressions. + use chumsky::prelude::*; use thiserror::Error; /// Our custom error type for parsing failures. #[derive(Error, Debug)] pub enum ParseError { + /// A generic parsing error with a descriptive message. #[error("Parse error: {0}")] Generic(String), } /// A simple arithmetic expression parser that accepts expressions like "1+2+3" /// and computes their sum. +/// +/// # Errors +/// +/// Returns a `ParseError` if: +/// - The input contains non-numeric characters (except '+') +/// - The input has invalid syntax (e.g., "1+" or "+2") +/// - The input is empty or contains only whitespace +/// +/// # Examples +/// +/// ``` +/// use {{ project_slug_underscore }}_core::parse; +/// +/// # fn main() -> Result<(), Box> { +/// assert_eq!(parse("1+2+3")?, "6"); +/// assert_eq!(parse("10+20+30")?, "60"); +/// # Ok(()) +/// # } +/// ``` pub fn parse(input: &str) -> Result { // The parser for an integer. let number = text::int::>(10) - .map(|s: String| s.parse::().unwrap()) + .try_map(|s: String, span| { + s.parse::() + .map_err(|e| Simple::custom(span, format!("Invalid number: {e}"))) + }) .padded() .labelled("number"); @@ -54,9 +82,20 @@ mod tests { #[test] fn test_parse() { - assert_eq!(parse("1+2+3").unwrap(), "6"); - assert_eq!(parse("10+20+30").unwrap(), "60"); - assert_eq!(parse("100+200+300").unwrap(), "600"); + match parse("1+2+3") { + Ok(result) => assert_eq!(result, "6"), + Err(e) => panic!("Expected successful parse of '1+2+3', got error: {e}"), + } + + match parse("10+20+30") { + Ok(result) => assert_eq!(result, "60"), + Err(e) => panic!("Expected successful parse of '10+20+30', got error: {e}"), + } + + match parse("100+200+300") { + Ok(result) => assert_eq!(result, "600"), + Err(e) => panic!("Expected successful parse of '100+200+300', got error: {e}"), + } } #[test] @@ -70,7 +109,7 @@ mod tests { ); } else { println!("Expected an error, but got a result"); - println!("Result: {:?}", res); + println!("Result: {res:?}"); panic!("Expected an error, but got a result"); } } diff --git a/template/deny.toml b/template/deny.toml index 594e2a6..41a5554 100644 --- a/template/deny.toml +++ b/template/deny.toml @@ -1,2 +1,38 @@ +[graph] +all-features = true + +[advisories] +# advisory DB configuration +db-path = "~/.cargo/advisory-db" +db-urls = ["https://github.com/rustsec/advisory-db"] + +# choose how to treat unmaintained advisories: all|workspace|transitive|none +unmaintained = "workspace" + +# what to do on yanked crates: deny|warn|allow +yanked = "deny" + [licenses] -allow = ["Apache-2.0", "MIT", "MPL-2.0", "Unicode-3.0"] +# only these SPDX licenses are permitted (everything else is denied by default) +allow = [ + "MIT", + "Apache-2.0", + "MPL-2.0", + "Unicode-DFS-2016", +] + +# (optional) lint if an allowed license isn't actually used: +# unused-allowed-license = "warn" + +# (optional) override AskAlono's confidence threshold: +# confidence-threshold = 0.8 + +[bans] +# duplicate-version policy: warn | deny | allow +multiple-versions = "warn" + +# wildcard dependencies: allow | deny +wildcards = "allow" + +# graph coloring when dumping dotgraphs: none | all +highlight = "all" diff --git a/template/devbox.json b/template/devbox.json deleted file mode 100644 index 35fbeb4..0000000 --- a/template/devbox.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.7/.schema/devbox.schema.json", - "packages": [ - "bash@latest", - "cargo-audit@latest", - "cargo-deny@latest", - "cargo-watch@latest", - "mise@latest", - "pnpm@latest", - "rust-cbindgen@latest", - "wabt@latest", - "wasm-bindgen-cli@latest", - "wasm-pack@latest" - ], - "env": { - "COREPACK_ENABLE_DOWNLOAD_PROMPT": "0", - "LIBRARY_PATH": "$LIBRARY_PATH:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib:/opt/homebrew/opt/libiconv/lib", - "MACOSX_DEPLOYMENT_TARGET": "11.0", - "RUST_BACKTRACE": "1", - "RUSTFLAGS": "-D warnings" - }, - "shell": { - "init_hook": [ - "mise trust", - "mise install" - ] - } -} diff --git a/template/devbox.lock b/template/devbox.lock deleted file mode 100644 index 4b7f4fc..0000000 --- a/template/devbox.lock +++ /dev/null @@ -1,1065 +0,0 @@ -{ - "lockfile_version": "1", - "packages": { - "addlicense@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#addlicense", - "source": "devbox-search", - "version": "1.1.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/mpkwfrp1lvszm651kc40vv99npyfg0c4-addlicense-1.1.1", - "default": true - } - ], - "store_path": "/nix/store/mpkwfrp1lvszm651kc40vv99npyfg0c4-addlicense-1.1.1" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/dn584k3spxjac7y3ig7zcnhis66rs9j9-addlicense-1.1.1", - "default": true - } - ], - "store_path": "/nix/store/dn584k3spxjac7y3ig7zcnhis66rs9j9-addlicense-1.1.1" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/dgw2wjx4rkjqlp85njd309dhgjqfj9mq-addlicense-1.1.1", - "default": true - } - ], - "store_path": "/nix/store/dgw2wjx4rkjqlp85njd309dhgjqfj9mq-addlicense-1.1.1" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/433nyszq6q672km01a9af3gr4brv94sz-addlicense-1.1.1", - "default": true - } - ], - "store_path": "/nix/store/433nyszq6q672km01a9af3gr4brv94sz-addlicense-1.1.1" - } - } - }, - "bash@latest": { - "last_modified": "2025-01-29T07:48:22Z", - "resolved": "github:NixOS/nixpkgs/9a5db3142ce450045840cc8d832b13b8a2018e0c#bash", - "source": "devbox-search", - "version": "5.2p37", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/iv1k5wr7hbxm51qmdn6l2inq7rd2vfhk-bash-5.2p37", - "default": true - }, - { - "name": "man", - "path": "/nix/store/5wykqrk1bjvy5nwzgz9dwjjx223cgxbi-bash-5.2p37-man", - "default": true - }, - { - "name": "dev", - "path": "/nix/store/y1gbmyh6g72pwwmq8bfy3xqccf41c9kp-bash-5.2p37-dev" - }, - { - "name": "doc", - "path": "/nix/store/4pymjfaz3c52sjm8gbbrjh8hjp132hbp-bash-5.2p37-doc" - }, - { - "name": "info", - "path": "/nix/store/lkkrvm3ff638gj6kyq661g5wdmi18ix1-bash-5.2p37-info" - } - ], - "store_path": "/nix/store/iv1k5wr7hbxm51qmdn6l2inq7rd2vfhk-bash-5.2p37" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/xgvqbslsa5km8q1bkhlhdr3r5kxblvn6-bash-5.2p37", - "default": true - }, - { - "name": "man", - "path": "/nix/store/air7z6nlsymq83pb0b3zkgpwgbz0xfk7-bash-5.2p37-man", - "default": true - }, - { - "name": "info", - "path": "/nix/store/hj9pwsa7k44hp7cdaqiwwgj1d8cbwqhq-bash-5.2p37-info" - }, - { - "name": "debug", - "path": "/nix/store/0cjhc09c1950x79543wn4q44blyqxm2v-bash-5.2p37-debug" - }, - { - "name": "dev", - "path": "/nix/store/yabpm2m2zlrw0n31wlzpkasa9xwimvif-bash-5.2p37-dev" - }, - { - "name": "doc", - "path": "/nix/store/9ak22h5rx84n4psrf983a5wx1vz6sgqh-bash-5.2p37-doc" - } - ], - "store_path": "/nix/store/xgvqbslsa5km8q1bkhlhdr3r5kxblvn6-bash-5.2p37" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/igfwnnvi05rz0mxdwh058v6n2h49zxi3-bash-5.2p37", - "default": true - }, - { - "name": "man", - "path": "/nix/store/djrihaw45f70x2b2az99drz896g33jsc-bash-5.2p37-man", - "default": true - }, - { - "name": "dev", - "path": "/nix/store/lpz39521cvyi7panxlp61gbq8qsz93ab-bash-5.2p37-dev" - }, - { - "name": "doc", - "path": "/nix/store/wk6dpd9phm9vvd9drlwsj6gydcc0lg2x-bash-5.2p37-doc" - }, - { - "name": "info", - "path": "/nix/store/24kgy563fhz3f5ya3l9iqb17yxj4ya6v-bash-5.2p37-info" - } - ], - "store_path": "/nix/store/igfwnnvi05rz0mxdwh058v6n2h49zxi3-bash-5.2p37" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/4fvc5fm8bszmkydng1ivrvr5cbvr1g60-bash-5.2p37", - "default": true - }, - { - "name": "man", - "path": "/nix/store/fms780awxnslj7rk1wbiv5d89xp2zab4-bash-5.2p37-man", - "default": true - }, - { - "name": "debug", - "path": "/nix/store/mp6lxkvalsypqqk1mhzl3n5n42hm5ic4-bash-5.2p37-debug" - }, - { - "name": "dev", - "path": "/nix/store/rrb1378zih3wygygg6j4h1nqz76ap940-bash-5.2p37-dev" - }, - { - "name": "doc", - "path": "/nix/store/1jwrr261bfms7kcsy8ip3l3vvbvrkl3c-bash-5.2p37-doc" - }, - { - "name": "info", - "path": "/nix/store/nb1bi8pj2i8xdpnmmxd3xrf2rmm4yzjd-bash-5.2p37-info" - } - ], - "store_path": "/nix/store/4fvc5fm8bszmkydng1ivrvr5cbvr1g60-bash-5.2p37" - } - } - }, - "cargo-audit@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#cargo-audit", - "source": "devbox-search", - "version": "0.21.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/g3j8vhq78ilx3z8xbyz6v8fq5616ks18-cargo-audit-0.21.0", - "default": true - } - ], - "store_path": "/nix/store/g3j8vhq78ilx3z8xbyz6v8fq5616ks18-cargo-audit-0.21.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/icv89n81s6gwlbnx0yaymmpinzrjfgsw-cargo-audit-0.21.0", - "default": true - } - ], - "store_path": "/nix/store/icv89n81s6gwlbnx0yaymmpinzrjfgsw-cargo-audit-0.21.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/n9y7m209hni7f9zifyzkml2i99zf3i75-cargo-audit-0.21.0", - "default": true - } - ], - "store_path": "/nix/store/n9y7m209hni7f9zifyzkml2i99zf3i75-cargo-audit-0.21.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/v8vbpgmkcxfi6bad5c4yzckm6awhp60j-cargo-audit-0.21.0", - "default": true - } - ], - "store_path": "/nix/store/v8vbpgmkcxfi6bad5c4yzckm6awhp60j-cargo-audit-0.21.0" - } - } - }, - "cargo-binstall@latest": { - "last_modified": "2025-01-25T23:17:58Z", - "resolved": "github:NixOS/nixpkgs/b582bb5b0d7af253b05d58314b85ab8ec46b8d19#cargo-binstall", - "source": "devbox-search", - "version": "1.10.22", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/5jlq2j60k2mlgjg21zpr4bg7nxjif39s-cargo-binstall-1.10.22", - "default": true - } - ], - "store_path": "/nix/store/5jlq2j60k2mlgjg21zpr4bg7nxjif39s-cargo-binstall-1.10.22" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/fp3kdp5z0w1k66c4df6w8dvdpbi16qq7-cargo-binstall-1.10.22", - "default": true - } - ], - "store_path": "/nix/store/fp3kdp5z0w1k66c4df6w8dvdpbi16qq7-cargo-binstall-1.10.22" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/wfzgwccv89s483jbpg0a4rlnkwfrc6ql-cargo-binstall-1.10.22", - "default": true - } - ], - "store_path": "/nix/store/wfzgwccv89s483jbpg0a4rlnkwfrc6ql-cargo-binstall-1.10.22" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/6qjh7af81x1833rbnzf68n074q8267g6-cargo-binstall-1.10.22", - "default": true - } - ], - "store_path": "/nix/store/6qjh7af81x1833rbnzf68n074q8267g6-cargo-binstall-1.10.22" - } - } - }, - "cargo-deny@latest": { - "last_modified": "2025-01-22T23:44:18Z", - "resolved": "github:NixOS/nixpkgs/1800f90db02ce58f3733498b8052d5d62bf44c2f#cargo-deny", - "source": "devbox-search", - "version": "0.16.4", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/ajqxngj26m7c8iqhbx6731hvgl7sa719-cargo-deny-0.16.4", - "default": true - } - ], - "store_path": "/nix/store/ajqxngj26m7c8iqhbx6731hvgl7sa719-cargo-deny-0.16.4" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/c5qdfj599i8c8w2f8aj5kkbpbng7swfx-cargo-deny-0.16.4", - "default": true - } - ], - "store_path": "/nix/store/c5qdfj599i8c8w2f8aj5kkbpbng7swfx-cargo-deny-0.16.4" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/6i89ad78sy56svkpv9m1svip247rj2h3-cargo-deny-0.16.4", - "default": true - } - ], - "store_path": "/nix/store/6i89ad78sy56svkpv9m1svip247rj2h3-cargo-deny-0.16.4" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/iybz72v4yczl4szj319xsvg8mf12zpxr-cargo-deny-0.16.4", - "default": true - } - ], - "store_path": "/nix/store/iybz72v4yczl4szj319xsvg8mf12zpxr-cargo-deny-0.16.4" - } - } - }, - "cargo-watch@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#cargo-watch", - "source": "devbox-search", - "version": "8.5.3", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/3yzx1fmppdkmlaqyyw15v6cbahhg6b64-cargo-watch-8.5.3", - "default": true - } - ], - "store_path": "/nix/store/3yzx1fmppdkmlaqyyw15v6cbahhg6b64-cargo-watch-8.5.3" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/0bgvg7nnkrgs0x23jlv3pwz1v27l17l8-cargo-watch-8.5.3", - "default": true - } - ], - "store_path": "/nix/store/0bgvg7nnkrgs0x23jlv3pwz1v27l17l8-cargo-watch-8.5.3" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/k4r7xb1j909dk4zalby8rbm61k9gg41i-cargo-watch-8.5.3", - "default": true - } - ], - "store_path": "/nix/store/k4r7xb1j909dk4zalby8rbm61k9gg41i-cargo-watch-8.5.3" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/q1pw27krsxg8hzh3xpkrwf1lwzm6kipp-cargo-watch-8.5.3", - "default": true - } - ], - "store_path": "/nix/store/q1pw27krsxg8hzh3xpkrwf1lwzm6kipp-cargo-watch-8.5.3" - } - } - }, - "direnv@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#direnv", - "source": "devbox-search", - "version": "2.35.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/q00mwz61l0kz3ikjafm8v42df79vw70m-direnv-2.35.0", - "default": true - } - ], - "store_path": "/nix/store/q00mwz61l0kz3ikjafm8v42df79vw70m-direnv-2.35.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/5qjaj63mcpkbgg9dd7kq326d3zv1nfsq-direnv-2.35.0", - "default": true - } - ], - "store_path": "/nix/store/5qjaj63mcpkbgg9dd7kq326d3zv1nfsq-direnv-2.35.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/7w42jcbp3gl8mswmqkfpm54znbb58116-direnv-2.35.0", - "default": true - } - ], - "store_path": "/nix/store/7w42jcbp3gl8mswmqkfpm54znbb58116-direnv-2.35.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/5acgdhnifp5hsvhw2w34jhs5xqjgv0v3-direnv-2.35.0", - "default": true - } - ], - "store_path": "/nix/store/5acgdhnifp5hsvhw2w34jhs5xqjgv0v3-direnv-2.35.0" - } - } - }, - "fd@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#fd", - "source": "devbox-search", - "version": "10.2.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/ckay1nnlygljjn938c94xjc0669qn83r-fd-10.2.0", - "default": true - } - ], - "store_path": "/nix/store/ckay1nnlygljjn938c94xjc0669qn83r-fd-10.2.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/2v2sycna6fjq8rpl1plp4pfyzg1jd7b3-fd-10.2.0", - "default": true - } - ], - "store_path": "/nix/store/2v2sycna6fjq8rpl1plp4pfyzg1jd7b3-fd-10.2.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/jq45fqh31n5yrx551pg9fln104l1p2hv-fd-10.2.0", - "default": true - } - ], - "store_path": "/nix/store/jq45fqh31n5yrx551pg9fln104l1p2hv-fd-10.2.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/4p0c62vy7jw06ygmffhjhgwn11g0bila-fd-10.2.0", - "default": true - } - ], - "store_path": "/nix/store/4p0c62vy7jw06ygmffhjhgwn11g0bila-fd-10.2.0" - } - } - }, - "golangci-lint@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#golangci-lint", - "source": "devbox-search", - "version": "1.63.4", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/p81vg4szd85xb1m5r17fn6h2cd433xv9-golangci-lint-1.63.4", - "default": true - } - ], - "store_path": "/nix/store/p81vg4szd85xb1m5r17fn6h2cd433xv9-golangci-lint-1.63.4" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/45k8x4b0ygqwpf7di7rcglxsz8ykxz9z-golangci-lint-1.63.4", - "default": true - } - ], - "store_path": "/nix/store/45k8x4b0ygqwpf7di7rcglxsz8ykxz9z-golangci-lint-1.63.4" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/2xslqh1iyjbhwyynxw09ygfaxzfhmakp-golangci-lint-1.63.4", - "default": true - } - ], - "store_path": "/nix/store/2xslqh1iyjbhwyynxw09ygfaxzfhmakp-golangci-lint-1.63.4" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/71a493qsawf2gsh3s31zsbrw5pg8psmc-golangci-lint-1.63.4", - "default": true - } - ], - "store_path": "/nix/store/71a493qsawf2gsh3s31zsbrw5pg8psmc-golangci-lint-1.63.4" - } - } - }, - "jq@latest": { - "last_modified": "2025-02-08T12:54:32Z", - "resolved": "github:NixOS/nixpkgs/fa35a3c8e17a3de613240fea68f876e5b4896aec#jq", - "source": "devbox-search", - "version": "1.7.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "bin", - "path": "/nix/store/lmlmb3a5kzza0si8xfghr7x17vg8bzxb-jq-1.7.1-bin", - "default": true - }, - { - "name": "man", - "path": "/nix/store/afygplc4dm1ry7ww3702wafvy8bs9sxc-jq-1.7.1-man", - "default": true - }, - { - "name": "dev", - "path": "/nix/store/89q76wghz9xj2myglfwpv0n6yc19c8i6-jq-1.7.1-dev" - }, - { - "name": "doc", - "path": "/nix/store/dw2717n906kj3xp090fg9cqvcm747jic-jq-1.7.1-doc" - }, - { - "name": "out", - "path": "/nix/store/jm1bv0cha32k9967sv0z40kqgn5slz4i-jq-1.7.1" - } - ], - "store_path": "/nix/store/lmlmb3a5kzza0si8xfghr7x17vg8bzxb-jq-1.7.1-bin" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "bin", - "path": "/nix/store/vwpm32inl7g5w4p1hqkhjlj1wv0ic67y-jq-1.7.1-bin", - "default": true - }, - { - "name": "man", - "path": "/nix/store/m546xg6bwy8i785z5a7nx1ca3k9isd93-jq-1.7.1-man", - "default": true - }, - { - "name": "dev", - "path": "/nix/store/fn8f3hh3k8z3xxkl6al6qx78577w4hdx-jq-1.7.1-dev" - }, - { - "name": "doc", - "path": "/nix/store/jzcllz8ry9hnlpq954ik9fi215iir24l-jq-1.7.1-doc" - }, - { - "name": "out", - "path": "/nix/store/msmdzk125aal9mj8d0gd7r4sygh0mg4m-jq-1.7.1" - } - ], - "store_path": "/nix/store/vwpm32inl7g5w4p1hqkhjlj1wv0ic67y-jq-1.7.1-bin" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "bin", - "path": "/nix/store/j7hzqr3vfjghlm3wfy8va9b6abwhdkpf-jq-1.7.1-bin", - "default": true - }, - { - "name": "man", - "path": "/nix/store/1yr3pl2mrbb09i203bi1qppbzp4dvp7w-jq-1.7.1-man", - "default": true - }, - { - "name": "dev", - "path": "/nix/store/5sqag6l82rxxl24vj688vmqrqk4kg45z-jq-1.7.1-dev" - }, - { - "name": "doc", - "path": "/nix/store/bg150ikzp69zfjb1klcckzpjy88djnag-jq-1.7.1-doc" - }, - { - "name": "out", - "path": "/nix/store/jw6m3k9r4a7mvzcxr66fxib0s4182i9d-jq-1.7.1" - } - ], - "store_path": "/nix/store/j7hzqr3vfjghlm3wfy8va9b6abwhdkpf-jq-1.7.1-bin" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "bin", - "path": "/nix/store/n4xfh00cw7vnwnrlx9asp545z82pazgc-jq-1.7.1-bin", - "default": true - }, - { - "name": "man", - "path": "/nix/store/fj5sc6yb8v39min7kavc0i24nwmlsyki-jq-1.7.1-man", - "default": true - }, - { - "name": "out", - "path": "/nix/store/4b9rswbcgqiqidglpz6nrwlsfkhi7v22-jq-1.7.1" - }, - { - "name": "dev", - "path": "/nix/store/lcjisy815hp4agl57xqh2w6mic1v8jlf-jq-1.7.1-dev" - }, - { - "name": "doc", - "path": "/nix/store/41ir7g8plmi9257c4g8ag94jl9vhkp4l-jq-1.7.1-doc" - } - ], - "store_path": "/nix/store/n4xfh00cw7vnwnrlx9asp545z82pazgc-jq-1.7.1-bin" - } - } - }, - "just@latest": { - "last_modified": "2025-01-29T07:48:22Z", - "resolved": "github:NixOS/nixpkgs/9a5db3142ce450045840cc8d832b13b8a2018e0c#just", - "source": "devbox-search", - "version": "1.39.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/p0008v5xghjbvinj1cb0drlpa3ljgwps-just-1.39.0", - "default": true - }, - { - "name": "man", - "path": "/nix/store/pw81j3fwbq1agy0ai1cqzqffjbjffjm2-just-1.39.0-man", - "default": true - }, - { - "name": "doc", - "path": "/nix/store/vysi0rsapljs8nm13qd1q1m8x0rd1p70-just-1.39.0-doc" - } - ], - "store_path": "/nix/store/p0008v5xghjbvinj1cb0drlpa3ljgwps-just-1.39.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/k9586qna4zpwhnsn76x2p7g6nm0vhgbv-just-1.39.0", - "default": true - }, - { - "name": "man", - "path": "/nix/store/ji62wi00zgj4vrpwywkdl8kwykv19i6n-just-1.39.0-man", - "default": true - }, - { - "name": "doc", - "path": "/nix/store/3i3dk8bjyz4q9wawm1dkv1vk0sl7gbzj-just-1.39.0-doc" - } - ], - "store_path": "/nix/store/k9586qna4zpwhnsn76x2p7g6nm0vhgbv-just-1.39.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/s4w13zxwnly9z9j499fypx7kx7iffzfq-just-1.39.0", - "default": true - }, - { - "name": "man", - "path": "/nix/store/06ppryxxfnzklbxka8ycz8cabbklscpr-just-1.39.0-man", - "default": true - }, - { - "name": "doc", - "path": "/nix/store/rlv196k7vyi2g9gb0g0dbg34xh27nppg-just-1.39.0-doc" - } - ], - "store_path": "/nix/store/s4w13zxwnly9z9j499fypx7kx7iffzfq-just-1.39.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/vnyj5n5pgljwmwb9a4938hhry4w4fylk-just-1.39.0", - "default": true - }, - { - "name": "man", - "path": "/nix/store/fsn8pwjpszqywx364njl1bx6zk5rgrhd-just-1.39.0-man", - "default": true - }, - { - "name": "doc", - "path": "/nix/store/bnxwbxb6mlyi0x8xfgh05j82w5z2szaw-just-1.39.0-doc" - } - ], - "store_path": "/nix/store/vnyj5n5pgljwmwb9a4938hhry4w4fylk-just-1.39.0" - } - } - }, - "mise@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#mise", - "source": "devbox-search", - "version": "2025.1.6", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/gl3i47g0098sgc3784l7s7776712whqk-mise-2025.1.6", - "default": true - } - ], - "store_path": "/nix/store/gl3i47g0098sgc3784l7s7776712whqk-mise-2025.1.6" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/5pzvsfql8wmgajinnja561fg69bi99dm-mise-2025.1.6", - "default": true - } - ], - "store_path": "/nix/store/5pzvsfql8wmgajinnja561fg69bi99dm-mise-2025.1.6" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/2cyfrdgvql7zcfkjsnc9kgsiynwz8amp-mise-2025.1.6", - "default": true - } - ], - "store_path": "/nix/store/2cyfrdgvql7zcfkjsnc9kgsiynwz8amp-mise-2025.1.6" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/lf4b7s9hlvzw2ais2621qvmkw56ww9bz-mise-2025.1.6", - "default": true - } - ], - "store_path": "/nix/store/lf4b7s9hlvzw2ais2621qvmkw56ww9bz-mise-2025.1.6" - } - } - }, - "pnpm@latest": { - "last_modified": "2025-02-07T11:26:36Z", - "resolved": "github:NixOS/nixpkgs/d98abf5cf5914e5e4e9d57205e3af55ca90ffc1d#pnpm", - "source": "devbox-search", - "version": "10.2.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/f69kr305skrj3zf7fn96fcw3mr87dh59-pnpm-10.2.1", - "default": true - } - ], - "store_path": "/nix/store/f69kr305skrj3zf7fn96fcw3mr87dh59-pnpm-10.2.1" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/qww560lnjwb20ln7gjwq9ylb2sjkbbf5-pnpm-10.2.1", - "default": true - } - ], - "store_path": "/nix/store/qww560lnjwb20ln7gjwq9ylb2sjkbbf5-pnpm-10.2.1" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/xcy99hb5djnijhpm4ql1iyif7lldjw4l-pnpm-10.2.1", - "default": true - } - ], - "store_path": "/nix/store/xcy99hb5djnijhpm4ql1iyif7lldjw4l-pnpm-10.2.1" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/zk7vgm4h5d5sv3wsxmwknixnc1dhmm80-pnpm-10.2.1", - "default": true - } - ], - "store_path": "/nix/store/zk7vgm4h5d5sv3wsxmwknixnc1dhmm80-pnpm-10.2.1" - } - } - }, - "pre-commit@latest": { - "last_modified": "2025-01-31T04:26:24Z", - "resolved": "github:NixOS/nixpkgs/9189ac18287c599860e878e905da550aa6dec1cd#pre-commit", - "source": "devbox-search", - "version": "4.0.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/0wmqj4m2pz3kkqcsnvc0pzsyjqqx0zn3-pre-commit-4.0.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/68mri4rclghlcvvf1bldxfjl357qxzxn-pre-commit-4.0.1-dist" - } - ], - "store_path": "/nix/store/0wmqj4m2pz3kkqcsnvc0pzsyjqqx0zn3-pre-commit-4.0.1" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/659xf9l2275gyw92ra5x5r6vhsfnamx6-pre-commit-4.0.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/91pf595x4pvlrh4qyp43sf2arnn6s63i-pre-commit-4.0.1-dist" - } - ], - "store_path": "/nix/store/659xf9l2275gyw92ra5x5r6vhsfnamx6-pre-commit-4.0.1" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/0l7d2aj7j6hqc3wjln57dr2w0b1va8gk-pre-commit-4.0.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/y62pjir7a9qjxxg1aclxpr63hn7gvlbd-pre-commit-4.0.1-dist" - } - ], - "store_path": "/nix/store/0l7d2aj7j6hqc3wjln57dr2w0b1va8gk-pre-commit-4.0.1" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/mysa4nbqz7i266qnrxng859gz436szjr-pre-commit-4.0.1", - "default": true - }, - { - "name": "dist", - "path": "/nix/store/0c5q7fb7rqy75yqhv44cy6g23ybwaa98-pre-commit-4.0.1-dist" - } - ], - "store_path": "/nix/store/mysa4nbqz7i266qnrxng859gz436szjr-pre-commit-4.0.1" - } - } - }, - "rust-cbindgen@latest": { - "last_modified": "2025-02-07T11:26:36Z", - "resolved": "github:NixOS/nixpkgs/d98abf5cf5914e5e4e9d57205e3af55ca90ffc1d#rust-cbindgen", - "source": "devbox-search", - "version": "0.28.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/k2d8hd05fxsiwls6x2bppahg79563x90-rust-cbindgen-0.28.0", - "default": true - } - ], - "store_path": "/nix/store/k2d8hd05fxsiwls6x2bppahg79563x90-rust-cbindgen-0.28.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/99k7mbqfab68ggzslhfcasdx6rzc1wxx-rust-cbindgen-0.28.0", - "default": true - } - ], - "store_path": "/nix/store/99k7mbqfab68ggzslhfcasdx6rzc1wxx-rust-cbindgen-0.28.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/2hakjjfbjw717vz729d3g7gmp122qcrz-rust-cbindgen-0.28.0", - "default": true - } - ], - "store_path": "/nix/store/2hakjjfbjw717vz729d3g7gmp122qcrz-rust-cbindgen-0.28.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/p3xwjvwwh33c81c6iq7y369lckyk5x0i-rust-cbindgen-0.28.0", - "default": true - } - ], - "store_path": "/nix/store/p3xwjvwwh33c81c6iq7y369lckyk5x0i-rust-cbindgen-0.28.0" - } - } - }, - "uv@latest": { - "last_modified": "2025-02-07T11:26:36Z", - "resolved": "github:NixOS/nixpkgs/d98abf5cf5914e5e4e9d57205e3af55ca90ffc1d#uv", - "source": "devbox-search", - "version": "0.5.29", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/2f9zdf7sxsva89p3fzxry5m9p6ivax05-uv-0.5.29", - "default": true - } - ], - "store_path": "/nix/store/2f9zdf7sxsva89p3fzxry5m9p6ivax05-uv-0.5.29" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/0imbdi62wdayj9ljk4ihjr83g8jwhsh8-uv-0.5.29", - "default": true - } - ], - "store_path": "/nix/store/0imbdi62wdayj9ljk4ihjr83g8jwhsh8-uv-0.5.29" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/2cj7x75haqxnn9ixcq6cglj14i4j5w4y-uv-0.5.29", - "default": true - } - ], - "store_path": "/nix/store/2cj7x75haqxnn9ixcq6cglj14i4j5w4y-uv-0.5.29" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/sjvnlrxn0145v7kqcx99ys5n27agy5cz-uv-0.5.29", - "default": true - } - ], - "store_path": "/nix/store/sjvnlrxn0145v7kqcx99ys5n27agy5cz-uv-0.5.29" - } - } - }, - "wasm-bindgen-cli@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#wasm-bindgen-cli", - "source": "devbox-search", - "version": "0.2.100", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/rdiwxzp0b0iisdr60d44zi31lip5k5qr-wasm-bindgen-cli-0.2.100", - "default": true - } - ], - "store_path": "/nix/store/rdiwxzp0b0iisdr60d44zi31lip5k5qr-wasm-bindgen-cli-0.2.100" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/vd9dswj4jhgaxaimif66klszwx28i69g-wasm-bindgen-cli-0.2.100", - "default": true - } - ], - "store_path": "/nix/store/vd9dswj4jhgaxaimif66klszwx28i69g-wasm-bindgen-cli-0.2.100" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/l77mpcd8wrlhfnv0n8z1cpxqcfvd56d3-wasm-bindgen-cli-0.2.100", - "default": true - } - ], - "store_path": "/nix/store/l77mpcd8wrlhfnv0n8z1cpxqcfvd56d3-wasm-bindgen-cli-0.2.100" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/4nll8fdpzziq7glr6swbix4w32pkdxiq-wasm-bindgen-cli-0.2.100", - "default": true - } - ], - "store_path": "/nix/store/4nll8fdpzziq7glr6swbix4w32pkdxiq-wasm-bindgen-cli-0.2.100" - } - } - }, - "wasm-pack@latest": { - "last_modified": "2025-01-19T08:16:51Z", - "resolved": "github:NixOS/nixpkgs/50165c4f7eb48ce82bd063e1fb8047a0f515f8ce#wasm-pack", - "source": "devbox-search", - "version": "0.13.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/kh6q4zgcj7sdn8jyciwg328lh391azci-wasm-pack-0.13.1", - "default": true - } - ], - "store_path": "/nix/store/kh6q4zgcj7sdn8jyciwg328lh391azci-wasm-pack-0.13.1" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/a7fhfbsxvlrdxr16jz6c5v896bkhyvm3-wasm-pack-0.13.1", - "default": true - } - ], - "store_path": "/nix/store/a7fhfbsxvlrdxr16jz6c5v896bkhyvm3-wasm-pack-0.13.1" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/3qgxq8li64m1f4bwzzpfk6717g9biamm-wasm-pack-0.13.1", - "default": true - } - ], - "store_path": "/nix/store/3qgxq8li64m1f4bwzzpfk6717g9biamm-wasm-pack-0.13.1" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/wvp89h4j0znccyj2kpmp2w3110z2lmvi-wasm-pack-0.13.1", - "default": true - } - ], - "store_path": "/nix/store/wvp89h4j0znccyj2kpmp2w3110z2lmvi-wasm-pack-0.13.1" - } - } - } - } -} diff --git a/template/mise.lock b/template/mise.lock new file mode 100644 index 0000000..d10681c --- /dev/null +++ b/template/mise.lock @@ -0,0 +1,99 @@ +[tools.cargo-binstall] +version = "1.12.7" +backend = "aqua:cargo-bins/cargo-binstall" + +[tools."cargo:cargo-audit"] +version = "0.21.2" +backend = "cargo:cargo-audit" + +[tools."cargo:cargo-deny"] +version = "0.18.2" +backend = "cargo:cargo-deny" + +[tools."cargo:cargo-hack"] +version = "0.6.36" +backend = "cargo:cargo-hack" + +[tools."cargo:cargo-llvm-cov"] +version = "0.6.16" +backend = "cargo:cargo-llvm-cov" + +[tools."cargo:cargo-msrv"] +version = "0.18.4" +backend = "cargo:cargo-msrv" + +[tools."cargo:cargo-nextest"] +version = "0.9.98" +backend = "cargo:cargo-nextest" + +[tools."cargo:cargo-outdated"] +version = "0.17.0" +backend = "cargo:cargo-outdated" + +[tools."cargo:cargo-watch"] +version = "8.5.3" +backend = "cargo:cargo-watch" + +[tools."cargo:cbindgen"] +version = "0.29.0" +backend = "cargo:cbindgen" + +[tools."cargo:wasm-bindgen-cli"] +version = "0.2.100" +backend = "cargo:wasm-bindgen-cli" + +[tools."cargo:wasm-pack"] +version = "0.13.1" +backend = "cargo:wasm-pack" + +[tools.fd] +version = "10.2.0" +backend = "aqua:sharkdp/fd" + +[tools.go] +version = "1.24.4" +backend = "core:go" + +[tools."go:github.com/google/addlicense"] +version = "1.1.1" +backend = "go:github.com/google/addlicense" + +[tools.golangci-lint] +version = "2.1.6" +backend = "aqua:golangci/golangci-lint" + +[tools.jq] +version = "1.8.0" +backend = "aqua:jqlang/jq" + +[tools.just] +version = "1.40.0" +backend = "ubi:casey/just" + +[tools.node] +version = "22.16.0" +backend = "core:node" + +[tools.pnpm] +version = "10.11.1" +backend = "aqua:pnpm/pnpm" + +[tools.pre-commit] +version = "4.1.0" +backend = "aqua:pre-commit/pre-commit" + +[tools.python] +version = "3.12.11" +backend = "core:python" + +[tools.rust] +version = "1.87.0" +backend = "core:rust" + +[tools."ubi:https://github.com/WebAssembly/wabt/releases/tag/1.0.37"] +version = "latest" +backend = "ubi:https://github.com/WebAssembly/wabt/releases/tag/1.0.37" + +[tools.uv] +version = "0.7.9" +backend = "aqua:astral-sh/uv" diff --git a/template/mise.toml b/template/mise.toml new file mode 100644 index 0000000..748b4a3 --- /dev/null +++ b/template/mise.toml @@ -0,0 +1,38 @@ +[tools] +"cargo:cargo-audit" = "latest" +"cargo:cargo-deny" = "latest" +"cargo:cargo-hack" = "latest" +"cargo:cargo-llvm-cov" = "latest" +"cargo:cargo-msrv" = "latest" +"cargo:cargo-nextest" = "latest" +"cargo:cargo-outdated" = "latest" +"cargo:cargo-watch" = "latest" +"cargo:cbindgen" = "latest" +"cargo:wasm-bindgen-cli" = "latest" +"cargo:wasm-pack" = "latest" +"go:github.com/google/addlicense" = "latest" +"ubi:https://github.com/WebAssembly/wabt/releases/tag/1.0.37" = "latest" + +# Build tools +cargo-binstall = "latest" +fd = "latest" +go = "prefix:1.24" +golangci-lint = "latest" +jq = "latest" +just = "latest" +node = "lts" +pnpm = "latest" +pre-commit = "latest" +python = "prefix:3.12" +rust = "prefix:1.87" +uv = "latest" + +[env] +COREPACK_ENABLE_DOWNLOAD_PROMPT = "1" +LIBRARY_PATH = "$LIBRARY_PATH:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib:/opt/homebrew/opt/libiconv/lib" +MACOSX_DEPLOYMENT_TARGET = "11.0" +RUST_BACKTRACE = "1" +RUSTFLAGS = "-D warnings" + +[settings] +experimental = true diff --git a/template/mise.toml.jinja b/template/mise.toml.jinja deleted file mode 100644 index d6b9b87..0000000 --- a/template/mise.toml.jinja +++ /dev/null @@ -1,17 +0,0 @@ -[tools] -"go:github.com/google/addlicense" = "latest" -cargo-binstall = "latest" -direnv = "latest" -fd = "latest" -go = "prefix:1.24" -golangci-lint = "latest" -jq = "latest" -just = "latest" -node = "lts" -pre-commit = "latest" -python = "prefix:3.12" -rust = "prefix:1.85" -uv = "latest" - -[settings] -experimental = true diff --git a/template/nextest.toml b/template/nextest.toml new file mode 100644 index 0000000..81c9a51 --- /dev/null +++ b/template/nextest.toml @@ -0,0 +1,13 @@ +[profile.default] +# Run tests in parallel +test-threads = "num-cpus" +# Retry flaky tests +retries = 1 +# Fail fast on first error +fail-fast = false + +[profile.ci] +# More conservative settings for CI - 3 is the sweet-spot for flaky network/filesystem tests +test-threads = 4 +retries = 3 +fail-fast = true \ No newline at end of file diff --git a/template/rust-toolchain.toml b/template/rust-toolchain.toml new file mode 100644 index 0000000..b4e9521 --- /dev/null +++ b/template/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.87.0" +components = ["rustfmt", "clippy", "miri", "rust-src"] \ No newline at end of file diff --git a/template/rustfmt.toml b/template/rustfmt.toml index de2278a..7b4b5d8 100644 --- a/template/rustfmt.toml +++ b/template/rustfmt.toml @@ -1,16 +1,3 @@ -max_width = 100 # Set maximum line width to 100 characters. -hard_tabs = false # Use spaces for indentation. -tab_spaces = 4 # 4 spaces per indentation level. -newline_style = "Unix" # Use Unix-style line endings. -use_small_heuristics = "Default" # Enable default heuristics for layout decisions. - -# Function and method formatting: -fn_params_layout = "Tall" # Format function arguments on separate lines when needed. -chain_width = 100 # Allow chains (e.g. method chains) to extend up to 100 characters. - -# Struct and literal formatting: -struct_lit_width = 100 # Maximum width for struct literals. -struct_variant_width = 100 # Maximum width for enum variants with struct-like syntax. - -# Import formatting: -reorder_imports = true # Automatically reorder imports alphabetically. +max_width = 120 +edition = "2021" +newline_style = "Unix" diff --git a/template/scripts/dev-setup.sh b/template/scripts/dev-setup.sh new file mode 100755 index 0000000..35b87e1 --- /dev/null +++ b/template/scripts/dev-setup.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Install mise +if command -v mise >/dev/null 2>&1; then + echo "mise is already installed" +else + echo "mise is not installed" + if command -v brew >/dev/null 2>&1; then + echo "brew is installed" + brew install mise + else + echo "brew is not installed" + curl https://mise.run | sh + fi +fi diff --git "a/template/{{\"go\" if include_go else \"__skip_go__\"}}/Justfile.jinja" "b/template/{{\"go\" if include_go else \"__skip_go__\"}}/Justfile.jinja" index 0a9a1cf..a100ebb 100644 --- "a/template/{{\"go\" if include_go else \"__skip_go__\"}}/Justfile.jinja" +++ "b/template/{{\"go\" if include_go else \"__skip_go__\"}}/Justfile.jinja" @@ -33,7 +33,7 @@ generate-bindings: # Build the project build: generate-bindings #!/usr/bin/env bash - set -e + set -euxo pipefail eval "$(just _setup-env)" go build ./... @@ -41,7 +41,7 @@ build: generate-bindings # Run tests test: generate-bindings #!/usr/bin/env bash - set -e + set -euxo pipefail eval "$(just _setup-env)" go test ./... @@ -49,7 +49,7 @@ test: generate-bindings # Run linter lint: #!/usr/bin/env bash - set -e + set -euxo pipefail eval "$(just _setup-env)" golangci-lint run ./... diff --git "a/template/{{\"go\" if include_go else \"__skip_go__\"}}/go/binding.go.jinja" "b/template/{{\"go\" if include_go else \"__skip_go__\"}}/go/binding.go.jinja" index 479917e..839c97e 100644 --- "a/template/{{\"go\" if include_go else \"__skip_go__\"}}/go/binding.go.jinja" +++ "b/template/{{\"go\" if include_go else \"__skip_go__\"}}/go/binding.go.jinja" @@ -3,7 +3,7 @@ package binding /* #cgo CFLAGS: -I${SRCDIR}/.. -#cgo LDFLAGS: -L${SRCDIR}/../../target/debug -l{{ project_slug_underscore}}_go +#cgo LDFLAGS: -L${SRCDIR}/../../target/debug -l{{ project_slug_underscore }}_go #include "binding.h" #include diff --git "a/template/{{\"go-wasm\" if include_go else \"__skip_go_wasm__\"}}/go/binding.go.jinja" "b/template/{{\"go-wasm\" if include_go else \"__skip_go_wasm__\"}}/go/binding.go.jinja" index d85da64..909e0cc 100644 --- "a/template/{{\"go-wasm\" if include_go else \"__skip_go_wasm__\"}}/go/binding.go.jinja" +++ "b/template/{{\"go-wasm\" if include_go else \"__skip_go_wasm__\"}}/go/binding.go.jinja" @@ -6,6 +6,7 @@ import ( _ "embed" "errors" "fmt" + "log" "sync" "sync/atomic" "time" @@ -127,7 +128,12 @@ func Parse(ctx context.Context, input string) (*Expression, error) { if err != nil { return nil, fmt.Errorf("failed to instantiate WASM module: %w", err) } - defer module.Close(ctx) // Clean up this instance when done + defer func() { + if closeErr := module.Close(ctx); closeErr != nil { + // Log cleanup error - this shouldn't normally happen but good to know if it does + log.Printf("warning: failed to close WASM module: %v\n", closeErr) + } + }() // Get the needed export functions allocate := module.ExportedFunction("allocate") @@ -274,7 +280,12 @@ func GetWasmTimestamp(ctx context.Context) (time.Time, error) { if err != nil { return time.Time{}, fmt.Errorf("failed to instantiate WASM module: %w", err) } - defer module.Close(ctx) + defer func() { + if closeErr := module.Close(ctx); closeErr != nil { + // Log cleanup error - this shouldn't normally happen but good to know if it does + log.Printf("warning: failed to close WASM module: %v\n", closeErr) + } + }() // Call the get_timestamp_ms function getTimestamp := module.ExportedFunction("get_timestamp_ms")