feat: remove nativets in favor of bun with native pragma

This commit is contained in:
Ruben Fiszel
2024-07-29 19:19:53 +02:00
parent 298ec15cd5
commit 12ec75551e
22 changed files with 284 additions and 84 deletions
@@ -0,0 +1 @@
-- Add down migration script here
@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TYPE SCRIPT_LANG ADD VALUE IF NOT EXISTS 'bunnative';
+13 -2
View File
@@ -52,7 +52,7 @@ use windmill_common::{
utils::{
not_found_if_none, paginate, query_elems_from_hub, require_admin, Pagination, StripPath,
},
worker::to_raw_value,
worker::{get_annotation, to_raw_value},
HUB_BASE_URL,
};
use windmill_git_sync::{handle_deployment_metadata, DeployedObject};
@@ -585,6 +585,17 @@ async fn create_script_internal<'c>(
} else {
envs
};
let lang = if &ns.language == &ScriptLang::Bun || &ns.language == &ScriptLang::Bunnative {
let anns = get_annotation(&ns.content);
if anns.native_mode {
ScriptLang::Bunnative
} else {
ScriptLang::Bun
}
} else {
ns.language.clone()
};
sqlx::query!(
"INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, \
content, created_by, schema, is_template, extra_perms, lock, language, kind, tag, \
@@ -604,7 +615,7 @@ async fn create_script_internal<'c>(
ns.is_template.unwrap_or(false),
extra_perms,
lock,
ns.language.clone() as ScriptLang,
lang as ScriptLang,
ns.kind.unwrap_or(ScriptKind::Script) as ScriptKind,
ns.tag,
ns.draft_only,
+1 -1
View File
@@ -2498,7 +2498,7 @@ async fn tarball_workspace(
ScriptLang::Mssql => "ms.sql",
ScriptLang::Graphql => "gql",
ScriptLang::Nativets => "fetch.ts",
ScriptLang::Bun => {
ScriptLang::Bun | ScriptLang::Bunnative => {
if default_ts.as_ref().is_some_and(|x| x == "bun") {
"ts"
} else {
+2
View File
@@ -34,6 +34,7 @@ pub enum ScriptLang {
Powershell,
Postgresql,
Bun,
Bunnative,
Mysql,
Bigquery,
Snowflake,
@@ -46,6 +47,7 @@ impl ScriptLang {
pub fn as_str(&self) -> &'static str {
match self {
ScriptLang::Bun => "bun",
ScriptLang::Bunnative => "bunnative",
ScriptLang::Nativets => "nativets",
ScriptLang::Deno => "deno",
ScriptLang::Python3 => "python3",
+8 -3
View File
@@ -3702,10 +3702,15 @@ pub async fn push<'c, 'd, R: rsmq_async::RsmqConnection + Send + 'c>(
language
.as_ref()
.map(|x| {
if per_workspace {
format!("{}-{}", x.as_str(), workspace_id)
let tag_lang = if x == &ScriptLang::Bunnative {
ScriptLang::Nativets.as_str()
} else {
x.as_str().to_string()
x.as_str()
};
if per_workspace {
format!("{}-{}", tag_lang, workspace_id)
} else {
tag_lang.to_string()
}
})
.unwrap_or_else(default)
+78 -31
View File
@@ -34,7 +34,9 @@ use windmill_common::variables;
use windmill_common::{
error::{self, Result},
get_latest_hash_for_path,
jobs::QueuedJob,
scripts::ScriptLang,
worker::{exists_in_cache, get_annotation, save_cache},
DB,
};
@@ -577,7 +579,8 @@ pub async fn prebundle_script(
worker_name: &str,
token: &str,
) -> Result<()> {
let (local_path, remote_path) = compute_bundle_local_and_remote_path(inner_content, &lockfile);
let (local_path, remote_path) =
compute_bundle_local_and_remote_path(inner_content, &lockfile, script_path, db, w_id).await;
if exists_in_cache(&local_path, &remote_path).await {
return Ok(());
}
@@ -622,18 +625,48 @@ pub async fn prebundle_script(
pub const BUN_BUNDLE_OBJECT_STORE_PREFIX: &str = "bun_bundle/";
fn compute_bundle_local_and_remote_path(
async fn get_script_import_updated_at(db: &DB, w_id: &str, script_path: &str) -> Result<String> {
let script_hash = get_latest_hash_for_path(&mut db.begin().await?, w_id, script_path).await?;
let last_updated_at = sqlx::query_scalar!(
"SELECT created_at FROM script WHERE workspace_id = $1 AND hash = $2",
w_id,
script_hash.0 .0
)
.fetch_one(db)
.await?;
Ok(last_updated_at.to_string())
}
async fn compute_bundle_local_and_remote_path(
inner_content: &str,
requirements_o: &Option<String>,
script_path: &str,
db: &DB,
w_id: &str,
) -> (String, String) {
let hash = windmill_common::utils::calculate_hash(&format!(
let mut input_src = format!(
"{}{}",
inner_content,
requirements_o
.as_ref()
.map(|x| x.to_string())
.unwrap_or_default()
));
);
let relative_imports = crate::worker_lockfiles::extract_relative_imports(
&inner_content,
script_path,
&Some(ScriptLang::Bun),
);
for path in relative_imports.unwrap_or_default() {
if let Ok(updated_at) = get_script_import_updated_at(db, w_id, &path).await {
input_src.push_str(&path);
input_src.push_str(&updated_at.to_string());
}
}
let hash = windmill_common::utils::calculate_hash(&input_src);
let local_path = format!("{BUN_BUNDLE_CACHE_DIR}/{hash}");
let remote_path = format!("{BUN_BUNDLE_OBJECT_STORE_PREFIX}{hash}");
(local_path, remote_path)
@@ -657,10 +690,17 @@ pub async fn handle_bun_job(
) -> error::Result<Box<RawValue>> {
let mut annotation = windmill_common::worker::get_annotation(inner_content);
let (mut bundle_cache, cache_logs, local_path, remote_path) =
let (mut has_bundle_cache, cache_logs, local_path, remote_path) =
if requirements_o.is_some() && !annotation.nobundling && codebase.is_none() {
let (local_path, remote_path) =
compute_bundle_local_and_remote_path(inner_content, &requirements_o);
let (local_path, remote_path) = compute_bundle_local_and_remote_path(
inner_content,
&requirements_o,
job.script_path(),
db,
&job.workspace_id,
)
.await;
let (cache, logs) =
windmill_common::worker::load_cache(&local_path, &remote_path).await;
(cache, logs, local_path, remote_path)
@@ -668,9 +708,9 @@ pub async fn handle_bun_job(
(false, "".to_string(), "".to_string(), "".to_string())
};
if !codebase.is_some() && !bundle_cache {
if !codebase.is_some() && !has_bundle_cache {
let _ = write_file(job_dir, "main.ts", inner_content).await?;
} else {
} else if !annotation.native_mode {
let _ = write_file(job_dir, "package.json", r#"{ "type": "module" }"#).await?;
};
@@ -690,7 +730,7 @@ pub async fn handle_bun_job(
}
let mut gbuntar_name = None;
if bundle_cache {
if has_bundle_cache {
let target = format!("{job_dir}/main.js");
std::os::unix::fs::symlink(&local_path, &target).map_err(|e| {
error::Error::ExecutionErr(format!(
@@ -807,7 +847,7 @@ pub async fn handle_bun_job(
let mut init_logs = if annotation.native_mode {
"\n\n--- NATIVE CODE EXECUTION ---\n".to_string()
} else if bundle_cache {
} else if has_bundle_cache {
if annotation.nodejs_mode {
"\n\n--- NODE BUNDLE SNAPSHOT EXECUTION ---\n".to_string()
} else {
@@ -832,11 +872,14 @@ pub async fn handle_bun_job(
);
}
if bundle_cache {
if has_bundle_cache {
init_logs = format!("\n{}{}", cache_logs, init_logs);
}
let write_wrapper_f = async {
if !has_bundle_cache && annotation.native_mode {
return Ok(()) as error::Result<()>;
}
// let mut start = Instant::now();
let args =
windmill_parser_ts::parse_deno_signature(inner_content, true, main_override.clone())?
@@ -859,7 +902,7 @@ pub async fn handle_bun_job(
// we cannot use Bun.read and Bun.write because it results in an EBADF error on cloud
let main_name = main_override.unwrap_or("main".to_string());
let main_import = if codebase.is_some() || bundle_cache {
let main_import = if codebase.is_some() || has_bundle_cache {
"./main.js"
} else {
"./main.ts"
@@ -904,6 +947,9 @@ try {{
};
let reserved_variables_args_out_f = async {
if annotation.native_mode {
return Ok(HashMap::new()) as error::Result<HashMap<String, String>>;
}
let args_and_out_f = async {
create_args_and_out_file(&client, job, job_dir, db).await?;
Ok(()) as Result<()>
@@ -917,7 +963,7 @@ try {{
Ok(reserved_variables) as error::Result<HashMap<String, String>>
};
let build_cache = !bundle_cache
let build_cache = !has_bundle_cache
&& !annotation.nobundling
&& !codebase.is_some()
&& (requirements_o.is_some() || annotation.native_mode);
@@ -939,7 +985,7 @@ try {{
.await?;
Ok(())
} else if !codebase.is_some() && !bundle_cache {
} else if !codebase.is_some() && !has_bundle_cache {
build_loader(
job_dir,
base_internal_url,
@@ -963,7 +1009,7 @@ try {{
write_wrapper_f,
write_loader_f
)?;
if !codebase.is_some() && !bundle_cache {
if !codebase.is_some() && !has_bundle_cache {
if build_cache {
generate_bun_bundle(
job_dir,
@@ -977,7 +1023,6 @@ try {{
&common_bun_proc_envs,
)
.await?;
if !local_path.is_empty() {
match save_cache(&local_path, &remote_path, &format!("{job_dir}/main.js")).await {
Err(e) => {
@@ -992,19 +1037,21 @@ try {{
}
}
}
let ex_wrapper = read_file_content(&format!("{job_dir}/wrapper.mjs")).await?;
write_file(
job_dir,
"wrapper.mjs",
&ex_wrapper.replace(
"import * as Main from \"./main.ts\"",
"import * as Main from \"./main.js\"",
),
)
.await?;
write_file(job_dir, "package.json", r#"{ "type": "module" }"#).await?;
if !annotation.native_mode {
let ex_wrapper = read_file_content(&format!("{job_dir}/wrapper.mjs")).await?;
write_file(
job_dir,
"wrapper.mjs",
&ex_wrapper.replace(
"import * as Main from \"./main.ts\"",
"import * as Main from \"./main.js\"",
),
)
.await?;
write_file(job_dir, "package.json", r#"{ "type": "module" }"#).await?;
}
fs::remove_file(format!("{job_dir}/main.ts"))?;
bundle_cache = true;
has_bundle_cache = true;
} else if annotation.nodejs_mode {
generate_wrapper_mjs(
job_dir,
@@ -1100,7 +1147,7 @@ try {{
&NODE_PATH,
"/tmp/nodejs/wrapper.mjs",
]
} else if codebase.is_some() || bundle_cache {
} else if codebase.is_some() || has_bundle_cache {
vec![
"--config",
"run.config.proto",
@@ -1154,7 +1201,7 @@ try {{
let script_path = format!("{job_dir}/wrapper.mjs");
let mut bun_cmd = Command::new(&*BUN_PATH);
let args = if codebase.is_some() || bundle_cache {
let args = if codebase.is_some() || has_bundle_cache {
vec!["run", &script_path]
} else {
vec![
+1 -1
View File
@@ -3023,7 +3023,7 @@ mount {{
)
.await
}
Some(ScriptLang::Bun) => {
Some(ScriptLang::Bun) | Some(ScriptLang::Bunnative) => {
handle_bun_job(
requirements_o,
codebase,
+54 -12
View File
@@ -12,7 +12,7 @@ use windmill_common::flows::{FlowModule, FlowModuleValue};
use windmill_common::get_latest_deployed_hash_for_path;
use windmill_common::jobs::JobPayload;
use windmill_common::scripts::ScriptHash;
use windmill_common::worker::{to_raw_value, to_raw_value_owned};
use windmill_common::worker::{get_annotation, to_raw_value, to_raw_value_owned};
use windmill_common::{
error::{self, to_anyhow},
flows::FlowValue,
@@ -187,14 +187,16 @@ fn parse_bun_relative_imports(raw_code: &str, script_path: &str) -> error::Resul
Ok(relative_imports)
}
fn extract_relative_imports(
pub fn extract_relative_imports(
raw_code: &str,
script_path: &str,
language: &Option<ScriptLang>,
) -> Option<Vec<String>> {
match language {
Some(ScriptLang::Python3) => parse_relative_imports(&raw_code, script_path).ok(),
Some(ScriptLang::Bun) => parse_bun_relative_imports(&raw_code, script_path).ok(),
Some(ScriptLang::Bun) | Some(ScriptLang::Bunnative) => {
parse_bun_relative_imports(&raw_code, script_path).ok()
}
_ => None,
}
}
@@ -286,7 +288,7 @@ pub async fn handle_dependency_job<R: rsmq_async::RsmqConnection + Send + Sync +
let hash = job.script_hash.unwrap_or(ScriptHash(0));
let w_id = &job.workspace_id;
sqlx::query!(
"UPDATE script SET lock = $1 WHERE hash = $2 AND workspace_id = $3",
"UPDATE script SET lock = $1, created_at = now() WHERE hash = $2 AND workspace_id = $3",
&content,
&hash.0,
w_id
@@ -700,7 +702,7 @@ async fn lock_modules<'c>(
lock,
path,
content,
language,
mut language,
input_transforms,
tag,
custom_concurrency_key,
@@ -852,8 +854,11 @@ async fn lock_modules<'c>(
}
} else {
if lock.as_ref().is_some_and(|x| !x.trim().is_empty()) {
new_flow_modules.push(e);
continue;
let skip_creating_new_lock = skip_creating_new_lock(&language, &content);
if skip_creating_new_lock {
new_flow_modules.push(e);
continue;
}
}
}
@@ -911,6 +916,14 @@ async fn lock_modules<'c>(
append_logs(&job.id, &job.workspace_id, logs, db).await;
}
if language == ScriptLang::Bun || language == ScriptLang::Bunnative {
let anns = get_annotation(&content);
if anns.native_mode && language == ScriptLang::Bun {
language = ScriptLang::Bunnative;
} else if !anns.native_mode && language == ScriptLang::Bunnative {
language = ScriptLang::Bun;
};
}
e.value = windmill_common::worker::to_raw_value(&FlowModuleValue::RawScript {
lock: Some(new_lock),
path,
@@ -952,6 +965,18 @@ async fn lock_modules<'c>(
Ok((new_flow_modules, tx, modified_ids))
}
fn skip_creating_new_lock(language: &ScriptLang, content: &str) -> bool {
if language == &ScriptLang::Bun || language == &ScriptLang::Bunnative {
let anns = get_annotation(&content);
if anns.native_mode && language == &ScriptLang::Bun {
return false;
} else if !anns.native_mode && language == &ScriptLang::Bunnative {
return false;
};
}
true
}
#[async_recursion]
async fn lock_modules_app(
value: Value,
@@ -985,10 +1010,12 @@ async fn lock_modules_app(
if v.get("lock")
.is_some_and(|x| !x.as_str().unwrap().trim().is_empty())
{
logs.push_str(
"Found already locked inline script. Skipping lock...\n",
);
return Ok(Value::Object(m.clone()));
if skip_creating_new_lock(&language, &content) {
logs.push_str(
"Found already locked inline script. Skipping lock...\n",
);
return Ok(Value::Object(m.clone()));
}
}
logs.push_str("Found lockable inline script. Generating lock...\n");
let new_lock = capture_dependency_job(
@@ -1012,6 +1039,21 @@ async fn lock_modules_app(
match new_lock {
Ok(new_lock) => {
append_logs(&job.id, &job.workspace_id, logs, db).await;
let anns = get_annotation(&content);
let nlang = if anns.native_mode && language == ScriptLang::Bun {
Some(ScriptLang::Bunnative)
} else if !anns.native_mode && language == ScriptLang::Bunnative
{
Some(ScriptLang::Bun)
} else {
None
};
if let Some(nlang) = nlang {
v.insert(
"language".to_string(),
serde_json::Value::String(nlang.as_str().to_string()),
);
}
v.insert(
"lock".to_string(),
serde_json::Value::String(new_lock),
@@ -1293,7 +1335,7 @@ async fn capture_dependency_job(
)
.await
}
ScriptLang::Bun => {
ScriptLang::Bun | ScriptLang::Bunnative => {
let npm_mode = npm_mode
.unwrap_or_else(|| windmill_common::worker::get_annotation(job_raw_code).npm_mode);
if !raw_deps {
@@ -11,7 +11,9 @@
function computeLangs(defaultScripts: WorkspaceDefaultScripts | undefined) {
const allLangs = Object.keys(defaultScriptLanguages)
if (!defaultScripts || defaultScripts.order == undefined) return allLangs
return defaultScripts.order?.concat(allLangs.filter((l) => !defaultScripts.order?.includes(l)))
return defaultScripts.order
?.concat(allLangs.filter((l) => !defaultScripts.order?.includes(l)))
.filter((x) => x != 'nativets')
}
async function changePosition(i: number, up: boolean) {
+5 -3
View File
@@ -111,7 +111,7 @@
export let useWebsockets: boolean = true
export let listenEmptyChanges = false
export let small = false
export let scriptLang: Preview['language']
export let scriptLang: Preview['language'] | 'bunnative'
export let disabled: boolean = false
const rHash = randomHash()
@@ -127,7 +127,9 @@
let initialPath: string | undefined = path
$: path != initialPath && (scriptLang == 'deno' || scriptLang == 'bun') && handlePathChange()
$: path != initialPath &&
(scriptLang == 'deno' || scriptLang == 'bun' || scriptLang == 'bunnative') &&
handlePathChange()
let websockets: WebSocket[] = []
let languageClients: MonacoLanguageClient[] = []
@@ -1147,7 +1149,7 @@
const hostname = getHostname()
// const stdLib = { content: libStdContent, filePath: 'es6.d.ts' }
if (scriptLang == 'bun') {
if (scriptLang == 'bun' || scriptLang == 'bunnative') {
// const processLib = { content: processStdContent, filePath: 'process.d.ts' }
// const domLib = { content: domContent, filePath: 'dom.d.ts' }
// languages.typescript.typescriptDefaults.setExtraLibs([stdLib, domLib, processLib])
+2 -1
View File
@@ -58,7 +58,8 @@
export let iconOnly: boolean = false
export let validCode: boolean = true
export let kind: 'script' | 'trigger' | 'approval' = 'script'
export let template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' = 'script'
export let template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' | 'bunnative' =
'script'
export let collabMode = false
export let collabLive = false
export let collabUsers: { name: string }[] = []
@@ -57,7 +57,12 @@
import MetadataGen from './copilot/MetadataGen.svelte'
import ScriptSchedules from './ScriptSchedules.svelte'
import { writable } from 'svelte/store'
import { type ScriptSchedule, loadScriptSchedule, defaultScriptLanguages } from '$lib/scripts'
import {
type ScriptSchedule,
loadScriptSchedule,
defaultScriptLanguages,
processLangs
} from '$lib/scripts'
import DefaultScripts from './DefaultScripts.svelte'
import { createEventDispatcher } from 'svelte'
import CustomPopover from './CustomPopover.svelte'
@@ -65,7 +70,7 @@
export let script: NewScript
export let initialPath: string = ''
export let template: 'docker' | 'script' = 'script'
export let template: 'docker' | 'bunnative' | 'script' = 'script'
export let initialArgs: Record<string, any> = {}
export let lockedLanguage = false
export let showMeta: boolean = false
@@ -114,11 +119,14 @@
editor?.setCode(code)
}
$: langs = ($defaultScripts?.order ?? Object.keys(defaultScriptLanguages))
$: langs = processLangs(
script.language,
$defaultScripts?.order ?? Object.keys(defaultScriptLanguages)
)
.map((l) => [defaultScriptLanguages[l], l])
.filter(
(x) => $defaultScripts?.hidden == undefined || !$defaultScripts.hidden.includes(x[1])
) as [string, SupportedLanguage | 'docker'][]
) as [string, SupportedLanguage | 'docker' | 'bunnative'][]
const scriptKindOptions: {
value: Script['kind']
@@ -176,7 +184,7 @@
function initContent(
language: SupportedLanguage,
kind: Script['kind'] | undefined,
template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell'
template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' | 'bunnative'
) {
scriptEditor?.disableCollaboration()
script.content = initialCode(language, kind, template)
@@ -462,6 +470,16 @@
let deploymentMsg = ''
let msgInput: HTMLInputElement | undefined = undefined
function langToLanguage(lang: SupportedLanguage | 'docker' | 'bunnative'): SupportedLanguage {
if (lang == 'docker') {
return 'bash'
}
if (lang == 'bunnative') {
return 'bun'
}
return lang
}
</script>
<svelte:window on:keydown={onKeyDown} />
@@ -567,9 +585,12 @@
</div>
{/if}
<div class=" grid grid-cols-3 gap-2">
{script.language}
{template}
{#each langs as [label, lang] (lang)}
{@const isPicked =
(lang == script.language && template == 'script') ||
(template == 'bunnative' && lang == 'bunnative') ||
(template == 'docker' && lang == 'docker')}
<Popover
disablePopup={!enterpriseLangs.includes(lang) || !!$enterpriseLicense}
@@ -602,10 +623,12 @@
return
}
template = 'docker'
} else if (lang == 'bunnative') {
template = 'bunnative'
} else {
template = 'script'
}
let language = lang == 'docker' ? 'bash' : lang
let language = langToLanguage(lang)
//
initContent(language, script.kind, template)
script.language = language
@@ -30,7 +30,8 @@
export let path: string | undefined
export let lang: Preview['language']
export let kind: string | undefined = undefined
export let template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' = 'script'
export let template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' | 'bunnative' =
'script'
export let tag: string | undefined
export let initialArgs: Record<string, any> = {}
export let fixedOverflowWidgets = true
@@ -7,7 +7,7 @@
import { inferArgs } from '$lib/infer'
import { initialCode } from '$lib/script_helpers'
import { emptySchema } from '$lib/utils'
import { defaultScriptLanguages, getScriptByPath } from '$lib/scripts'
import { defaultScriptLanguages, getScriptByPath, processLangs } from '$lib/scripts'
import { Building, GitFork, Globe2 } from 'lucide-svelte'
import { createEventDispatcher, getContext } from 'svelte'
@@ -94,7 +94,7 @@
dispatch('new', unusedInlineScript.inlineScript)
}
$: langs = ($defaultScripts?.order ?? Object.keys(defaultScriptLanguages))
$: langs = processLangs(undefined, $defaultScripts?.order ?? Object.keys(defaultScriptLanguages))
.map((l) => [defaultScriptLanguages[l], l])
.filter(
(x) =>
@@ -314,10 +314,12 @@
if (inlineScript) {
inlineScript.content = editor?.getCode() ?? ''
}
runLoading = true
await Promise.all(
$runnableComponents[id]?.cb?.map((f) => f?.(inlineScript, true)) ?? []
)
try {
runLoading = true
await Promise.all(
$runnableComponents[id]?.cb?.map((f) => f?.(inlineScript, true)) ?? []
)
} catch {}
runLoading = false
}}
on:change={async (e) => {
@@ -26,17 +26,19 @@
| 'fetch'
| 'docker'
| 'powershell'
| 'bunnative'
export let width = 30
export let height = 30
export let scale = 1
const languageLabel: Record<Script['language'], String> = {
const languageLabel: Record<Script['language'] | 'bunnative', String> = {
python3: 'Python',
deno: 'TypeScript',
go: 'Go',
bash: 'Bash',
powershell: 'PowerShell',
nativets: 'HTTP',
bunnative: 'HTTP',
graphql: 'GraphQL',
postgresql: 'Postgresql',
bigquery: 'BigQuery',
@@ -48,7 +50,7 @@
}
const langToComponent: Record<
SupportedLanguage | 'pgsql' | 'javascript' | 'fetch' | 'docker' | 'powershell',
SupportedLanguage | 'pgsql' | 'javascript' | 'fetch' | 'docker' | 'powershell' | 'bunnative',
any
> = {
go: GoIcon,
@@ -56,6 +58,7 @@
deno: TypeScriptIcon,
// graphql: TypeScriptIcon,
bun: TypeScriptIcon,
bunnative: RestIcon,
bash: BashIcon,
pgsql: PostgresIcon,
mysql: MySQLIcon,
@@ -14,7 +14,7 @@
import { Check, Code, Zap } from 'lucide-svelte'
import SuspendDrawer from './SuspendDrawer.svelte'
import { defaultScripts } from '$lib/stores'
import { defaultScriptLanguages } from '$lib/scripts'
import { defaultScriptLanguages, processLangs } from '$lib/scripts'
import type { SupportedLanguage } from '$lib/common'
import DefaultScripts from '$lib/components/DefaultScripts.svelte'
@@ -34,7 +34,7 @@
let pick_existing: 'workspace' | 'hub' = 'hub'
let filter = ''
$: langs = ($defaultScripts?.order ?? Object.keys(defaultScriptLanguages))
$: langs = processLangs(undefined, $defaultScripts?.order ?? Object.keys(defaultScriptLanguages))
.map((l) => [defaultScriptLanguages[l], l])
.filter(
(x) => $defaultScripts?.hidden == undefined || !$defaultScripts.hidden.includes(x[1])
@@ -161,7 +161,10 @@
{/if}
<h3 class="pb-2 pt-4 flex gap-x-8 flex-wrap">
<div>
Inline new <span class="text-blue-500 dark:text-blue-400">{kind == 'script' ? 'action' : kind}</span> script
Inline new <span class="text-blue-500 dark:text-blue-400"
>{kind == 'script' ? 'action' : kind}</span
>
script
<Tooltip
documentationLink={kind === 'script'
? 'https://www.windmill.dev/docs/flows/editor_components#flow-actions'
@@ -229,7 +232,9 @@
</div>
<h3 class="mb-2 mt-6"
>Use pre-made <span class="text-blue-500 dark:text-blue-400">{kind == 'script' ? 'action' : kind}</span> script</h3
>Use pre-made <span class="text-blue-500 dark:text-blue-400"
>{kind == 'script' ? 'action' : kind}</span
> script</h3
>
{#if pick_existing == 'hub'}
<PickHubScript bind:filter {kind} on:pick>
+2
View File
@@ -42,6 +42,8 @@ export function langToExt(lang: string): string {
switch (lang) {
case 'javascript':
return 'ts'
case 'bunnative':
return 'ts'
case 'json':
return 'json'
case 'sql':
+2 -2
View File
@@ -43,7 +43,7 @@ export function parseDeps(code: string): string[] {
}
export async function inferArgs(
language: SupportedLanguage | undefined,
language: SupportedLanguage | 'bunnative' | undefined,
code: string,
schema: Schema
): Promise<boolean | null> {
@@ -67,7 +67,7 @@ export async function inferArgs(
inferedSchema = JSON.parse(parse_deno(code))
} else if (language == 'nativets') {
inferedSchema = JSON.parse(parse_deno(code))
} else if (language == 'bun') {
} else if (language == 'bun' || language == 'bunnative') {
inferedSchema = JSON.parse(parse_deno(code))
} else if (language == 'postgresql') {
inferedSchema = JSON.parse(parse_sql(code))
+41 -5
View File
@@ -25,6 +25,22 @@ export async function main(example_input: number = 3) {
}
`
export const BUNNATIVE_INIT_CODE = `//native
// native scripts are bun scripts that are executed on native workers and can be parallelized
// only fetch is allowed, but imports will work as long as they also use only fetch and the standard lib
//import * as wmill from "windmill-client"
export async function main(example_input: number = 3) {
// "3" is the default value of example_input, it can be overriden with code or using the UI
const res = await fetch(\`https://jsonplaceholder.typicode.com/todos/\${example_input}\`, {
headers: { "Content-Type": "application/json" },
});
return res.json();
}
`
export const NATIVETS_INIT_CODE_CLEAR = `// Fetch-only script, no imports allowed (except windmill) but benefits from a dedicated highly efficient runtime
//import * as wmill from './windmill.ts'
@@ -459,9 +475,18 @@ export function isInitialCode(content: string): boolean {
}
export function initialCode(
language: SupportedLanguage | undefined,
language: SupportedLanguage | 'bunnative' | undefined,
kind: Script['kind'] | undefined,
subkind: 'pgsql' | 'mysql' | 'flow' | 'script' | 'fetch' | 'docker' | 'powershell' | undefined
subkind:
| 'pgsql'
| 'mysql'
| 'flow'
| 'script'
| 'fetch'
| 'docker'
| 'powershell'
| 'bunnative'
| undefined
): string {
if (!kind) {
kind = 'script'
@@ -524,8 +549,10 @@ export function initialCode(
return GRAPHQL_INIT_CODE
} else if (language == 'php') {
return PHP_INIT_CODE
} else if (language == 'bun') {
if (kind === 'approval') {
} else if (language == 'bun' || language == 'bunnative') {
if (language == 'bunnative' || subkind === 'bunnative') {
return BUNNATIVE_INIT_CODE
} else if (kind === 'approval') {
return BUN_INIT_CODE_APPROVAL
} else if (kind === 'failure') {
return BUN_FAILURE_MODULE_CODE
@@ -549,7 +576,16 @@ export function initialCode(
export function getResetCode(
language: SupportedLanguage | undefined,
kind: Script['kind'] | undefined,
subkind: 'pgsql' | 'mysql' | 'flow' | 'script' | 'fetch' | 'docker' | 'powershell' | undefined
subkind:
| 'pgsql'
| 'mysql'
| 'flow'
| 'script'
| 'fetch'
| 'docker'
| 'powershell'
| 'bunnative'
| undefined
) {
if (language === 'deno') {
return DENO_INIT_CODE_CLEAR
+16 -3
View File
@@ -4,10 +4,10 @@ import type { Schema, SupportedLanguage } from './common'
import { FlowService, type Script, ScriptService, ScheduleService } from './gen'
import { workspaceStore } from './stores'
export function scriptLangToEditorLang(lang: Script['language'] | undefined) {
export function scriptLangToEditorLang(lang: Script['language'] | 'bunnative' | undefined) {
if (lang == 'deno') {
return 'typescript'
} else if (lang == 'bun') {
} else if (lang == 'bun' || lang == 'bunnative') {
return 'typescript'
} else if (lang == 'nativets') {
return 'typescript'
@@ -92,13 +92,14 @@ export function scriptPathToHref(path: string, hubBaseUrl: string): string {
}
}
const scriptLanguagesArray: [SupportedLanguage | 'docker', string][] = [
const scriptLanguagesArray: [SupportedLanguage | 'docker' | 'bunnative', string][] = [
['bun', 'TypeScript (Bun)'],
['python3', 'Python'],
['deno', 'TypeScript (Deno)'],
['bash', 'Bash'],
['go', 'Go'],
['nativets', 'REST'],
['bunnative', 'REST'],
['postgresql', 'PostgreSQL'],
['mysql', 'MySQL'],
['bigquery', 'BigQuery'],
@@ -109,6 +110,18 @@ const scriptLanguagesArray: [SupportedLanguage | 'docker', string][] = [
['php', 'PHP'],
['docker', 'Docker']
]
export function processLangs(selected: string | undefined, langs: string[]): string[] {
if (selected === 'nativets') {
return langs
} else {
let ls = langs.filter((lang) => lang !== 'nativets')
if (!ls.includes('bunnative')) {
ls.push('bunnative')
}
return ls
}
}
export const defaultScriptLanguages = Object.fromEntries(scriptLanguagesArray)
export async function getScriptByPath(path: string): Promise<{