Files
windmill/frontend/src/lib/editorLangUtils.ts
T
a46aa641f9 feat: add R language support (#8263)
* feat: add R language support

Add R as a new supported scripting language in Windmill, following the
same pattern used for Ruby. Includes:

- Backend: ScriptLang::Rlang enum variant, DB migration, tree-sitter-r
  parser crate with tests, WASM parser binding, R executor with NSJail
  sandboxing, job dispatch and signature parsing
- Frontend: language picker, R icon, syntax highlighting, editor bar
  insertions (Sys.getenv, get_variable, get_resource), schema inference,
  init code template, BETA badge
- CLI: .r extension mapping, sync support, bootstrap template

R scripts use `main <- function(...)` syntax, jsonlite for JSON
serialization, and system curl for the Windmill client helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add R package resolution and installation

Parse library()/require() calls from R scripts to extract dependencies.
Resolve versions from CRAN, cache lockfiles in pip_resolution_cache,
and install packages to a shared R library cache. The run step sets
R_LIBS_USER so installed packages are available to the script.

- Parser: parse_r_requirements() extracts package names from AST
- Executor: resolve() generates lockfile, install() installs from CRAN
- Worker lockfiles: wire up R resolve for dependency jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add nsjail sandboxing for R resolve and install phases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: fix R get_variable/get_resource and add sandbox annotation + e2e tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: fix R arg inference with JS fallback parser and get_variable/get_resource

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix flake

* nsjail

* nits

* fix: R install improvements - suppress verbose output, flat lockfile logging, Dockerfile R support, rlimits

- Suppress renv verbose output during resolve and install (controlled by #verbose annotation)
- Filter renv from install list (already loaded, causes noisy restart message)
- Log compact "resolved N packages" instead of full renv.lock JSON
- Add R (r-base, r-cran-renv) to DockerfileFull and DockerfileFullEe
- Use disable_rl for nsjail install config (R compiles from source)
- Reduce default concurrency from 20 to 5
- Add rlang to openflow.openapi.yaml
- Fix MainArgSignature (no_main_func -> auto_kind) after main merge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* final

* fix: remove accidental R install from multiplayer Dockerfile

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: remove R from Windows build and DockerfileExtra

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: rename R migration to avoid timestamp collision with trigger_filter_logic

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* all

* fix: R install improvements - suppress verbose output, flat lockfile logging, Dockerfile R support, rlimits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add clear error when Rscript binary is missing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: fix type errors in R fallback parser, use format! in wrap(), add R system prompts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: pyranota <pyra@duck.com>
2026-04-01 06:11:37 +00:00

117 lines
1.9 KiB
TypeScript

export function langToExt(lang: string): string {
switch (lang) {
case 'tsx':
return 'tsx'
case 'javascript':
return 'js'
case 'jsx':
return 'js'
case 'bunnative':
return 'ts'
case 'json':
return 'json'
case 'sql':
return 'sql'
case 'yaml':
return 'yaml'
case 'typescript':
return 'ts'
case 'python':
return 'py'
case 'go':
return 'go'
case 'bash':
return 'sh'
case 'powershell':
return 'ps1'
case 'php':
return 'php'
case 'rust':
return 'rs'
case 'deno':
return 'ts'
case 'nativets':
return 'ts'
case 'graphql':
return 'gql'
case 'css':
return 'css'
case 'ansible':
return 'yml'
case 'csharp':
return 'cs'
case 'nu':
return 'nu'
case 'java':
return 'java'
case 'svelte':
return 'svelte'
case 'vue':
return 'vue'
default:
return 'unknown'
}
}
export function extToLang(ext: string) {
switch (ext) {
case 'tsx':
return 'typescript'
case 'ts':
return 'typescript'
case 'js':
return 'javascript'
case 'jsx':
return 'javascript'
case 'json':
return 'json'
case 'sql':
return 'sql'
case 'yaml':
return 'yaml'
case 'py':
return 'python'
case 'go':
return 'go'
case 'sh':
return 'bash'
case 'ps1':
return 'powershell'
case 'php':
return 'php'
case 'rs':
return 'rust'
case 'gql':
return 'graphql'
case 'css':
return 'css'
case 'yml':
return 'ansible'
case 'cs':
return 'csharp'
case 'svelte':
return 'svelte'
case 'vue':
return 'vue'
case 'nu':
return 'nu'
case 'java':
return 'java'
case 'rb':
return 'ruby'
case 'r':
return 'r'
// for related places search: ADD_NEW_LANG
default:
return 'unknown'
}
}
export function createHash() {
return (Math.random() + 1).toString(36).substring(2)
}
export function createLongHash() {
return 'h' + Math.random().toString(36).substring(2) + Math.random().toString(36).substring(2)
}