feat: add script bootstrap and script generate-metadata CLI commands (#3007)

* feat: add script bootstrap and script generate-metadata CLI commands

* Address PR comments on code
This commit is contained in:
Guillaume Bouvignies
2024-01-16 18:25:51 +01:00
committed by GitHub
parent 9fffe4f6f5
commit b9bee403f1
17 changed files with 1726 additions and 117 deletions
+20 -20
View File
@@ -3752,9 +3752,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.67"
version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
dependencies = [
"wasm-bindgen",
]
@@ -9044,9 +9044,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.90"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -9054,9 +9054,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.90"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [
"bumpalo",
"log",
@@ -9069,9 +9069,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.40"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461"
checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
dependencies = [
"cfg-if",
"js-sys",
@@ -9081,9 +9081,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.90"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -9091,9 +9091,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.90"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
@@ -9104,15 +9104,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.90"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.40"
version = "0.3.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c"
checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403"
dependencies = [
"console_error_panic_hook",
"js-sys",
@@ -9124,9 +9124,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.40"
version = "0.3.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928"
checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89"
dependencies = [
"proc-macro2",
"quote",
@@ -9157,9 +9157,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.67"
version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed"
checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f"
dependencies = [
"js-sys",
"wasm-bindgen",
+1 -1
View File
@@ -189,7 +189,7 @@ rsmq_async = { version = "5.1.5" }
gosyn = "0.2.6"
bytes = "1.4.0"
gethostname = "0.4.3"
wasm-bindgen = "0.2"
wasm-bindgen = "=0.2.89"
serde-wasm-bindgen = "0.4"
wasm-bindgen-test = "0.3.0"
convert_case = "0.6.0"
@@ -0,0 +1,4 @@
#!/bin/bash
set -eou pipefail
deno task wasmbuild --out ../../../cli/wasm/
@@ -0,0 +1,5 @@
{
"tasks": {
"wasmbuild": "deno run -A https://deno.land/x/wasmbuild@0.15.4/main.ts"
}
}
+115 -49
View File
@@ -1,6 +1,6 @@
openapi: 3.0.3
info:
version: 1.242.0
version: 1.244.2
title: Windmill API
contact:
name: Windmill Team
@@ -2530,13 +2530,10 @@ paths:
type: string
expires_in:
type: integer
owner:
type: string
client:
type: string
required:
- expires_in
- owner
- client
responses:
'200':
@@ -3358,32 +3355,32 @@ paths:
id:
type: string
value:
oneOf: &ref_204
oneOf: &ref_206
- type: object
properties: &ref_188
properties: &ref_190
input_transforms:
type: object
additionalProperties:
oneOf: &ref_26
- type: object
properties: &ref_184
properties: &ref_186
value: {}
type:
type: string
enum:
- javascript
required: &ref_185
required: &ref_187
- expr
- type
- type: object
properties: &ref_186
properties: &ref_188
expr:
type: string
type:
type: string
enum:
- javascript
required: &ref_187
required: &ref_189
- expr
- type
discriminator: &ref_27
@@ -3423,13 +3420,13 @@ paths:
type: number
concurrency_time_window_s:
type: number
required: &ref_189
required: &ref_191
- type
- content
- language
- input_transforms
- type: object
properties: &ref_190
properties: &ref_192
input_transforms:
type: object
additionalProperties:
@@ -3443,12 +3440,12 @@ paths:
type: string
enum:
- script
required: &ref_191
required: &ref_193
- type
- path
- input_transforms
- type: object
properties: &ref_192
properties: &ref_194
input_transforms:
type: object
additionalProperties:
@@ -3460,12 +3457,12 @@ paths:
type: string
enum:
- flow
required: &ref_193
required: &ref_195
- type
- path
- input_transforms
- type: object
properties: &ref_194
properties: &ref_196
modules:
type: array
items:
@@ -3487,13 +3484,13 @@ paths:
type: boolean
parallelism:
type: integer
required: &ref_195
required: &ref_197
- modules
- iterator
- skip_failures
- type
- type: object
properties: &ref_196
properties: &ref_198
branches:
type: array
items:
@@ -3524,12 +3521,12 @@ paths:
type: string
enum:
- branchone
required: &ref_197
required: &ref_199
- branches
- default
- type
- type: object
properties: &ref_198
properties: &ref_200
branches:
type: array
items:
@@ -3554,28 +3551,28 @@ paths:
- branchall
parallel:
type: boolean
required: &ref_199
- branches
- type
- type: object
properties: &ref_200
type:
type: string
enum:
- identity
flow:
type: boolean
required: &ref_201
- branches
- type
- type: object
properties: &ref_202
type:
type: string
enum:
- graphql
- identity
flow:
type: boolean
required: &ref_203
- type
discriminator: &ref_205
- type: object
properties: &ref_204
type:
type: string
enum:
- graphql
required: &ref_205
- type
discriminator: &ref_207
propertyName: type
mapping:
rawscript: '#/components/schemas/RawScript'
@@ -6746,6 +6743,71 @@ paths:
schema:
type: string
format: uuid
/w/{workspace}/jobs/run/dependencies:
post:
summary: run a one-off dependencies job
operationId: runRawScriptDependencies
tags:
- job
parameters:
- name: workspace
in: path
required: true
schema: *ref_0
requestBody:
description: raw script content
required: true
content:
application/json:
schema:
type: object
properties:
raw_scripts:
type: array
items:
type: object
properties: &ref_184
content:
type: string
path:
type: string
language:
type: string
enum:
- python3
- deno
- go
- bash
- powershell
- postgresql
- mysql
- bigquery
- snowflake
- mssql
- graphql
- nativets
- bun
required: &ref_185
- content
- path
- language
entrypoint:
type: string
required:
- entrypoint
- raw_scripts
responses:
'201':
description: dependency job result
content:
application/json:
schema:
type: object
properties:
lock:
type: string
required:
- lock
/w/{workspace}/jobs/run/preview_flow:
post:
summary: run flow preview
@@ -11224,56 +11286,60 @@ components:
type: object
properties: *ref_182
required: *ref_183
StaticTransform:
RawScriptForDependencies:
type: object
properties: *ref_184
required: *ref_185
JavascriptTransform:
StaticTransform:
type: object
properties: *ref_186
required: *ref_187
JavascriptTransform:
type: object
properties: *ref_188
required: *ref_189
InputTransform:
oneOf: *ref_26
discriminator: *ref_27
RawScript:
type: object
properties: *ref_188
required: *ref_189
PathScript:
type: object
properties: *ref_190
required: *ref_191
PathFlow:
PathScript:
type: object
properties: *ref_192
required: *ref_193
PathFlow:
type: object
properties: *ref_194
required: *ref_195
FlowModule:
type: object
properties: *ref_28
required: *ref_29
ForloopFlow:
type: object
properties: *ref_194
required: *ref_195
BranchOne:
type: object
properties: *ref_196
required: *ref_197
BranchAll:
BranchOne:
type: object
properties: *ref_198
required: *ref_199
Identity:
BranchAll:
type: object
properties: *ref_200
required: *ref_201
Graphql:
Identity:
type: object
properties: *ref_202
required: *ref_203
Graphql:
type: object
properties: *ref_204
required: *ref_205
FlowModuleValue:
oneOf: *ref_204
discriminator: *ref_205
oneOf: *ref_206
discriminator: *ref_207
Retry:
type: object
properties: *ref_78
+69
View File
@@ -4617,6 +4617,45 @@ paths:
type: string
format: uuid
/w/{workspace}/jobs/run/dependencies:
post:
summary: run a one-off dependencies job
operationId: runRawScriptDependencies
tags:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
requestBody:
description: raw script content
required: true
content:
application/json:
schema:
type: object
properties:
raw_scripts:
type: array
items:
$ref: "#/components/schemas/RawScriptForDependencies"
entrypoint:
type: string
required:
- entrypoint
- raw_scripts
responses:
"201":
description: dependency job result
content:
application/json:
schema:
type: object
properties:
lock:
type: string
required:
- lock
/w/{workspace}/jobs/run/preview_flow:
post:
summary: run flow preview
@@ -9313,3 +9352,33 @@ components:
required:
- timestamp
- value
RawScriptForDependencies:
type: object
properties:
content:
type: string
path:
type: string
language:
type: string
enum:
[
python3,
deno,
go,
bash,
powershell,
postgresql,
mysql,
bigquery,
snowflake,
mssql,
graphql,
nativets,
bun,
]
required:
- content
- path
- language
+83 -6
View File
@@ -152,6 +152,7 @@ pub fn workspaced_service() -> Router {
"/result_by_id/:job_id/:node_id",
get(get_result_by_id).layer(cors.clone()),
)
.route("/run/dependencies", post(run_dependencies_job))
}
pub fn global_service() -> Router {
@@ -1945,10 +1946,10 @@ pub struct WindmillCompositeResult {
windmill_content_type: Option<String>,
result: Option<Box<RawValue>>,
}
async fn run_wait_result<T>(
async fn run_wait_result(
db: &DB,
uuid: Uuid,
Path((w_id, _)): Path<(String, T)>,
w_id: String,
node_id_for_empty_return: Option<String>,
) -> error::Result<Response> {
let mut result;
@@ -2183,7 +2184,7 @@ pub async fn run_wait_result_job_by_path_get(
.await?;
tx.commit().await?;
let wait_result = run_wait_result(&db, uuid, Path((w_id, script_path)), None).await;
let wait_result = run_wait_result(&db, uuid, w_id, None).await;
if delete_after_use.unwrap_or(false) {
delete_job_metadata_after_use(&db, uuid).await?;
}
@@ -2302,7 +2303,7 @@ async fn run_wait_result_script_by_path_internal(
.await?;
tx.commit().await?;
let wait_result = run_wait_result(&db, uuid, Path((w_id, script_path)), None).await;
let wait_result = run_wait_result(&db, uuid, w_id, None).await;
if delete_after_use.unwrap_or(false) {
delete_job_metadata_after_use(&db, uuid).await?;
}
@@ -2377,7 +2378,7 @@ pub async fn run_wait_result_script_by_hash(
.await?;
tx.commit().await?;
let wait_result = run_wait_result(&db, uuid, Path((w_id, script_hash)), None).await;
let wait_result = run_wait_result(&db, uuid, w_id, None).await;
if delete_after_use.unwrap_or(false) {
delete_job_metadata_after_use(&db, uuid).await?;
}
@@ -2459,7 +2460,7 @@ async fn run_wait_result_flow_by_path_internal(
.await?;
tx.commit().await?;
run_wait_result(&db, uuid, Path((w_id, flow_path)), early_return).await
run_wait_result(&db, uuid, w_id, early_return).await
}
async fn run_preview_job(
@@ -2527,6 +2528,82 @@ async fn run_preview_job(
Ok((StatusCode::CREATED, uuid.to_string()))
}
#[derive(Deserialize)]
pub struct RunDependenciesRequest {
pub raw_scripts: Vec<RawScriptForDependencies>,
pub entrypoint: String,
}
#[derive(Deserialize, Clone)]
pub struct RawScriptForDependencies {
pub script_path: String,
pub raw_code: String,
pub language: ScriptLang,
}
#[derive(Serialize)]
pub struct RunDependenciesResponse {
pub dependencies: String,
}
pub async fn run_dependencies_job(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Extension(rsmq): Extension<Option<rsmq_async::MultiplexedRsmq>>,
Path(w_id): Path<String>,
Json(req): Json<RunDependenciesRequest>,
) -> error::Result<Response> {
check_scopes(&authed, || format!("runscript"))?;
if authed.is_operator {
return Err(error::Error::NotAuthorized(
"Operators cannot run dependencies jobs for security reasons".to_string(),
));
}
if req.raw_scripts.len() != 1 || req.raw_scripts[0].script_path != req.entrypoint {
return Err(error::Error::InternalErr(
"For now only a single raw script can be passed to this endpoint, and the entrypoint should be set to the script path".to_string(),
));
}
let raw_script = req.raw_scripts[0].clone();
let script_path = raw_script.script_path;
let raw_code = raw_script.raw_code;
let language = raw_script.language;
let (uuid, tx) = push(
&db,
PushIsolationLevel::IsolatedRoot(db.clone(), rsmq),
&w_id,
JobPayload::RawScriptDependencies {
script_path: script_path,
content: raw_code,
language: language,
},
PushArgs::empty(),
&authed.username,
&authed.email,
username_to_permissioned_as(&authed.username),
None,
None,
None,
None,
None,
false,
false,
None,
true,
None,
None,
None,
None,
)
.await?;
tx.commit().await?;
let wait_result = run_wait_result(&db, uuid, w_id, None).await;
wait_result
}
#[derive(Deserialize)]
struct BatchInfo {
kind: String,
+5
View File
@@ -294,6 +294,11 @@ pub enum JobPayload {
path: String,
version: i64,
},
RawScriptDependencies {
script_path: String,
content: String,
language: ScriptLang,
},
Flow {
path: String,
dedicated_worker: Option<bool>,
+14
View File
@@ -2516,6 +2516,20 @@ pub async fn push<'c, T: Serialize + Send + Sync, R: rsmq_async::RsmqConnection
dedicated_worker,
None,
),
JobPayload::RawScriptDependencies { script_path, content, language } => (
None,
Some(script_path),
Some((content, None)),
JobKind::Dependencies,
None,
None,
Some(language),
None,
None,
None,
None,
None,
),
JobPayload::FlowDependencies { path, dedicated_worker } => {
let value_json = fetch_scalar_isolated!(
sqlx::query_scalar!(
+19 -8
View File
@@ -3173,14 +3173,18 @@ async fn handle_dependency_job<R: rsmq_async::RsmqConnection + Send + Sync + Clo
token: &str,
rsmq: Option<R>,
) -> error::Result<Box<RawValue>> {
let raw_code = sqlx::query_scalar!(
"SELECT content FROM script WHERE hash = $1 AND workspace_id = $2",
&job.script_hash.unwrap_or(ScriptHash(0)).0,
&job.workspace_id
)
.fetch_optional(db)
.await?
.unwrap_or_else(|| "No script found at this hash".to_string());
let raw_code = match job.raw_code {
Some(ref code) => code.to_owned(),
None => sqlx::query_scalar!(
"SELECT content FROM script WHERE hash = $1 AND workspace_id = $2",
&job.script_hash.unwrap_or(ScriptHash(0)).0,
&job.workspace_id
)
.fetch_optional(db)
.await?
.unwrap_or_else(|| "No script found at this hash".to_string()),
};
let script_path = job.script_path();
let content = capture_dependency_job(
&job.id,
@@ -3205,6 +3209,13 @@ async fn handle_dependency_job<R: rsmq_async::RsmqConnection + Send + Sync + Clo
.await;
match content {
Ok(content) => {
if job.script_hash.is_none() {
// it a one-off raw script dependency job, no need to update the db
return Ok(to_raw_value_owned(
json!({ "success": "Successful lock file generation", "lock": content }),
));
}
let hash = job.script_hash.unwrap_or(ScriptHash(0));
let w_id = &job.workspace_id;
sqlx::query!(
+24
View File
@@ -0,0 +1,24 @@
export interface SchemaProperty {
type: string | undefined
description?: string
pattern?: string
default?: any
enum?: string[]
contentEncoding?: 'base64' | 'binary'
format?: string
items?: {
type?: 'string' | 'number' | 'bytes' | 'object'
contentEncoding?: 'base64'
enum?: string[]
}
min?: number
max?: number
currency?: string
currencyLocale?: string
multiselect?: boolean
customErrorMessage?: string
properties?: { [name: string]: SchemaProperty }
required?: string[]
showExpr?: string
}
+35
View File
@@ -0,0 +1,35 @@
import { SchemaProperty } from "./common.ts";
export interface FlowDefinition {
summary: string,
description: string,
value: {
modules: any[]
},
schema: {
$schema: string,
type: string,
order: string[],
properties: { [name: string]: SchemaProperty},
required: string[]
}
ws_error_handler_muted: false
}
export function defaultFlowDefinition(): FlowDefinition {
return {
summary: '',
description: '',
value: {
modules: []
},
schema: {
$schema: 'https://json-schema.org/draft/2020-12/schema',
type: 'object',
order: [],
properties: {},
required: []
},
ws_error_handler_muted: false,
}
}
+83
View File
@@ -0,0 +1,83 @@
import { SchemaProperty } from "./common.ts";
export interface ScriptMetadata {
summary: string,
description: string,
lock: string[],
is_template: boolean,
kind: string,
schema: {
$schema: string,
type: string,
properties: { [name: string]: SchemaProperty},
required: string[]
}
}
export function defaultScriptMetadata(): ScriptMetadata {
return {
summary: '',
description: '',
lock: [],
is_template: false,
kind: 'script',
schema: {
$schema: 'https://json-schema.org/draft/2020-12/schema',
type: 'object',
properties: {},
required: []
}
}
}
export const scriptBootstrapCode = {
python3: `def main():
return "Hello world"
`,
nativets: `export async function main() {
return "Hello world";
}
`,
bun: `export async function main() {
return "Hello world";
}
`,
deno: `export async function main() {
return "Hello world";
}
`,
go: `package inner
func main() (interface{}, error) {
return "Hello world", nil
}
`,
mysql: `SELECT 'Hello world' AS message
`,
bigquery: `SELECT 'Hello world' AS message
`,
snowflake: `SELECT 'Hello world' AS message
`,
mssql: `SELECT 'Hello world' AS message
`,
graphql: `query() {
demo() {}
}`,
postgresql: `SELECT 'Hello world' AS message
`,
bash: `echo "Hello world"
`,
powershell: `Write-Output "Hello world"`,
}
+33 -2
View File
@@ -1,6 +1,6 @@
// deno-lint-ignore-file no-explicit-any
import { GlobalOptions, isSuperset } from "./types.ts";
import { SEP, log } from "./deps.ts";
import { SEP, log, yamlStringify } from "./deps.ts";
import {
colors,
Command,
@@ -13,6 +13,7 @@ import {
} from "./deps.ts";
import { requireLogin, resolveWorkspace, validatePath } from "./context.ts";
import { resolve, track_job } from "./script.ts";
import { defaultFlowDefinition } from "./bootstrap/flow_bootstrap.ts";
export interface FlowFile {
summary: string;
@@ -193,6 +194,31 @@ async function run(
log.info(jobInfo.result ?? {});
}
export function bootstrap(opts: GlobalOptions & {summary: string, description: string}, flowPath: string) {
if (!validatePath(flowPath)) {
return;
}
const flowDirFullPath = `${flowPath}.flow`
Deno.mkdirSync(flowDirFullPath, { recursive: false });
const newFlowDefinition = defaultFlowDefinition();
if (opts.summary !== undefined) {
newFlowDefinition.summary = opts.summary;
}
if (opts.description !== undefined) {
newFlowDefinition.description = opts.description;
}
const newFlowDefinitionYaml = yamlStringify(newFlowDefinition as Record<string, any>);
const flowYamlPath = `${flowDirFullPath}/flow.yaml`;
Deno.writeTextFile(
flowYamlPath,
newFlowDefinitionYaml,
{ createNew: true });
}
const command = new Command()
.description("flow related commands")
.option("--show-archived", "Enable archived scripts in output")
@@ -213,6 +239,11 @@ const command = new Command()
"-s --silent",
"Do not ouput anything other then the final output. Useful for scripting."
)
.action(run as any);
.action(run as any)
.command("bootstrap", "create a new empty flow")
.arguments("<flow_path:string>")
.option("--summary <summary:string>", "script summary")
.option("--description <description:string>", "script description")
.action(bootstrap as any);
export default command;
+384 -31
View File
@@ -13,8 +13,13 @@ import {
Table,
writeAllSync,
yamlParse,
yamlStringify,
} from "./deps.ts";
import { deepEqual } from "./utils.ts";
import { defaultScriptMetadata, scriptBootstrapCode } from "./bootstrap/script_bootstrap.ts";
import { instantiate as instantiateWasm, parse_bash, parse_bigquery, parse_deno, parse_go, parse_graphql, parse_mssql, parse_mysql, parse_powershell, parse_python, parse_snowflake, parse_sql } from "./wasm/windmill_parser_wasm.generated.js"
import { Workspace } from "./workspace.ts";
import { SchemaProperty } from "./bootstrap/common.ts";
export interface ScriptFile {
parent_hash?: string;
@@ -63,6 +68,29 @@ export async function handleScriptMetadata(
}
}
async function parseMetadataFile(scriptPath: string): Promise<{isJson: boolean, payload: any} | undefined> {
let metadataFilePath = scriptPath + ".script.json";
try {
await Deno.stat(metadataFilePath);
return {
payload: JSON.parse(await Deno.readTextFile(metadataFilePath)),
isJson: true,
}
} catch {
try {
metadataFilePath = scriptPath + ".script.yaml";
await Deno.stat(metadataFilePath);
return {
payload: yamlParse(await Deno.readTextFile(metadataFilePath)),
isJson: false,
}
} catch {
// no meta file
}
}
return undefined;
}
export async function handleFile(
path: string,
workspace: string,
@@ -88,21 +116,7 @@ export async function handleFile(
const remotePath = path
.substring(0, path.indexOf("."))
.replaceAll("\\", "/");
const metaPath = remotePath + ".script.json";
let typed = undefined;
try {
await Deno.stat(metaPath);
typed = JSON.parse(await Deno.readTextFile(metaPath));
} catch {
const metaPath = remotePath + ".script.yaml";
try {
await Deno.stat(metaPath);
typed = yamlParse(await Deno.readTextFile(metaPath));
} catch {
// no meta file
}
}
const typed = (await parseMetadataFile(path))?.payload;
const language = inferContentTypeFromFilePath(path);
let remote = undefined;
@@ -256,22 +270,45 @@ export async function findContentFile(filePath: string) {
return validCandidates[0];
}
type ScriptLanguage = "python3" | "deno" | "bun" | "nativets" | "go" | "bash" | "powershell" | "postgresql" | "mysql" | "bigquery" | "snowflake" | "mssql" | "graphql";
export function filePathExtensionFromContentType(language: ScriptLanguage): string {
if (language === "python3") {
return ".py";
} else if (language === "nativets") {
return ".fetch.ts";
} else if (language === "bun") {
return ".bun.ts";
} else if (language === "deno") {
return ".ts";
} else if (language === "go") {
return ".go";
} else if (language === "mysql") {
return ".my.sql";
} else if (language === "bigquery") {
return ".bq.sql";
} else if (language === "snowflake") {
return ".sf.sql";
} else if (language === "mssql") {
return ".ms.sql";
} else if (language === "postgresql") {
return ".pg.sql";
} else if (language === "graphql") {
return ".gql";
} else if (language === "bash") {
return ".sh";
} else if (language === "powershell") {
return ".ps1";
} else {
throw new Error(
"Invalid language: " + language
);
}
}
export function inferContentTypeFromFilePath(
contentPath: string
):
| "python3"
| "deno"
| "bun"
| "nativets"
| "go"
| "bash"
| "powershell"
| "postgresql"
| "mysql"
| "bigquery"
| "snowflake"
| "mssql"
| "graphql" {
): ScriptLanguage {
if (contentPath.endsWith(".py")) {
return "python3";
} else if (contentPath.endsWith("fetch.ts")) {
@@ -305,6 +342,189 @@ export function inferContentTypeFromFilePath(
}
}
////////////////////////////////////////////////////////////////////////////////////////////
// below functions copied from Windmill's FE inferArgs function. TODO: refactor //
////////////////////////////////////////////////////////////////////////////////////////////
export function inferSchema(language: ScriptLanguage, content: string, currentSchema: any) {
let inferedSchema: any;
if (language === "python3") {
inferedSchema = JSON.parse(parse_python(content));
} else if (language === "nativets") {
inferedSchema = JSON.parse(parse_deno(content));
} else if (language === "bun") {
inferedSchema = JSON.parse(parse_deno(content));
} else if (language === "deno") {
inferedSchema = JSON.parse(parse_deno(content));
} else if (language === "go") {
inferedSchema = JSON.parse(parse_go(content));
} else if (language === "mysql") {
inferedSchema = JSON.parse(parse_mysql(content));
inferedSchema.args = [
{ name: 'database', typ: { resource: 'mysql' } },
...inferedSchema.args
]
} else if (language === "bigquery") {
inferedSchema = JSON.parse(parse_bigquery(content));
inferedSchema.args = [
{ name: 'database', typ: { resource: 'bigquery' } },
...inferedSchema.args
]
} else if (language === "snowflake") {
inferedSchema = JSON.parse(parse_snowflake(content));
inferedSchema.args = [
{ name: 'database', typ: { resource: 'snowflake' } },
...inferedSchema.args
]
} else if (language === "mssql") {
inferedSchema = JSON.parse(parse_mssql(content));
inferedSchema.args = [
{ name: 'database', typ: { resource: 'ms_sql_server' } },
...inferedSchema.args
]
} else if (language === "postgresql") {
inferedSchema = JSON.parse(parse_sql(content));
inferedSchema.args = [
{ name: 'database', typ: { resource: 'postgresql' } },
...inferedSchema.args
]
} else if (language === "graphql") {
inferedSchema = JSON.parse(parse_graphql(content));
inferedSchema.args = [
{ name: 'api', typ: { resource: 'graphql' } },
...inferedSchema.args
]
} else if (language === "bash") {
inferedSchema = JSON.parse(parse_bash(content));
} else if (language === "powershell") {
inferedSchema = JSON.parse(parse_powershell(content));
} else {
throw new Error(
"Invalid language: " + language
);
}
if (inferedSchema.type == 'Invalid') {
throw new Error(`Script invalid, it cannot be parsed to infer schema. Error was: ${inferedSchema.error}`)
}
currentSchema.required = []
const oldProperties = JSON.parse(JSON.stringify(currentSchema.properties))
currentSchema.properties = {}
for (const arg of inferedSchema.args) {
if (!(arg.name in oldProperties)) {
currentSchema.properties[arg.name] = { description: '', type: '' }
} else {
currentSchema.properties[arg.name] = oldProperties[arg.name]
}
currentSchema.properties[arg.name] = sortObject(currentSchema.properties[arg.name])
argSigToJsonSchemaType(arg.typ, currentSchema.properties[arg.name])
currentSchema.properties[arg.name].default = arg.default
if (!arg.has_default && !currentSchema.required.includes(arg.name)) {
currentSchema.required.push(arg.name)
}
}
return currentSchema;
}
function sortObject(obj: any): any {
return Object.keys(obj)
.sort()
.reduce((acc, key) => ({
...acc, [key]: obj[key]
}), {})
}
function argSigToJsonSchemaType(
typ:
| string
| { resource: string | null }
| { list: string | { str: any } | { object: { key: string; typ: any }[] } | null }
| { str: string[] | null }
| { object: { key: string; typ: any }[] },
oldS: SchemaProperty
): void {
const newS: SchemaProperty = { type: '' }
if (typ === 'int') {
newS.type = 'integer'
} else if (typ === 'float') {
newS.type = 'number'
} else if (typ === 'bool') {
newS.type = 'boolean'
} else if (typ === 'email') {
newS.type = 'string'
newS.format = 'email'
} else if (typ === 'sql') {
newS.type = 'string'
newS.format = 'sql'
} else if (typ === 'yaml') {
newS.type = 'string'
newS.format = 'yaml'
} else if (typ === 'bytes') {
newS.type = 'string'
newS.contentEncoding = 'base64'
} else if (typ === 'datetime') {
newS.type = 'string'
newS.format = 'date-time'
} else if (typeof typ !== 'string' && `object` in typ) {
newS.type = 'object'
if (typ.object) {
const properties: Record<string, SchemaProperty> = {};
for (const prop of typ.object) {
properties[prop.key] = {type: undefined}
argSigToJsonSchemaType(prop.typ, properties[prop.key])
}
newS.properties = properties
}
} else if (typeof typ !== 'string' && `str` in typ) {
newS.type = 'string'
if (typ.str) {
newS.enum = typ.str
}
} else if (typeof typ !== 'string' && `resource` in typ) {
newS.type = 'object'
newS.format = `resource-${typ.resource}`
} else if (typeof typ !== 'string' && `list` in typ) {
newS.type = 'array'
if (typ.list === 'int' || typ.list === 'float') {
newS.items = { type: 'number' }
} else if (typ.list === 'bytes') {
newS.items = { type: 'string', contentEncoding: 'base64' }
} else if (typ.list == 'string') {
newS.items = { type: 'string' }
} else if (typ.list && typeof typ.list == 'object' && 'str' in typ.list) {
newS.items = { type: 'string', enum: typ.list.str }
} else {
newS.items = { type: 'object' }
}
} else {
newS.type = 'object'
}
if (oldS.type != newS.type) {
for (const prop of Object.getOwnPropertyNames(newS)) {
if (prop != 'description') {
delete oldS[prop]
}
}
} else if (oldS.format == 'date-time' && newS.format != 'date-time') {
delete oldS.format
} else if (oldS.items?.type != newS.items?.type) {
delete oldS.items
}
Object.assign(oldS, newS)
if (oldS.format?.startsWith('resource-') && newS.type != 'object') {
oldS.format = undefined
}
}
////////////////////////////////////////////////////////////////////////////////////////////
// end of refactoring TODO //
////////////////////////////////////////////////////////////////////////////////////////////
async function list(opts: GlobalOptions & { showArchived?: boolean }) {
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
@@ -484,6 +704,129 @@ async function show(opts: GlobalOptions, path: string) {
log.info(s.content);
}
async function bootstrap(opts: GlobalOptions & {summary: string, description: string}, scriptPath: string, language: ScriptLanguage) {
if (!validatePath(scriptPath)) {
return;
}
const scriptInitialCode = scriptBootstrapCode[language];
if (scriptInitialCode === undefined) {
throw new Error("Language unknown");
}
const extension = filePathExtensionFromContentType(language);
const scriptCodeFileFullPath = scriptPath + extension;
const scriptMetadataFileFullPath = scriptPath + ".script.yaml";
try {
await Deno.stat(scriptCodeFileFullPath);
await Deno.stat(scriptMetadataFileFullPath);
throw new Error("File already exists in repository");
} catch {
// file does not exist, we can continue
}
const scriptMetadata = defaultScriptMetadata();
if (opts.summary !== undefined) {
scriptMetadata.summary = opts.summary;
}
if (opts.description !== undefined) {
scriptMetadata.description = opts.description;
}
const scriptInitialMetadataYaml = yamlStringify(scriptMetadata as Record<string, any>);
Deno.writeTextFile(
scriptCodeFileFullPath,
scriptInitialCode,
{ createNew: true });
Deno.writeTextFile(
scriptMetadataFileFullPath,
scriptInitialMetadataYaml,
{ createNew: true });
}
async function generateMetadata(opts: GlobalOptions & {lockOnly: boolean, schemaOnly: boolean}, scriptPath: string) {
if (!validatePath(scriptPath)) {
return;
}
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
const language = inferContentTypeFromFilePath(scriptPath);
// read script metadata file
const remotePath = scriptPath
.substring(0, scriptPath.indexOf("."))
.replaceAll("\\", "/");
const metadataWithType = await parseMetadataFile(remotePath);
if (metadataWithType === undefined) {
throw new Error("Script metadata file does not exist at this path");
}
// read script content
const scriptContent = await Deno.readTextFile(scriptPath);
const metadataParsedContent = metadataWithType?.payload as Record<string, any>;
if (!opts.lockOnly) {
await updateScriptSchema(scriptContent, language, metadataParsedContent);
}
if (!opts.schemaOnly) {
await updateScriptLock(workspace, scriptContent, language, remotePath, metadataParsedContent);
}
let metaPath = remotePath + ".script.yaml";
let newMetadataContent = yamlStringify(metadataParsedContent);
if (metadataWithType.isJson) {
metaPath = remotePath + ".script.json"
newMetadataContent = JSON.stringify(metadataParsedContent);
}
Deno.writeTextFile(
metaPath,
newMetadataContent);
}
async function updateScriptSchema(scriptContent: string, language: ScriptLanguage, metadataContent: Record<string, any>): Promise<void> {
// infer schema from script content and update it inplace
await instantiateWasm();
const newSchema = inferSchema(language, scriptContent, metadataContent.schema);
metadataContent.schema = newSchema;
}
async function updateScriptLock(workspace: Workspace, scriptContent: string, language: ScriptLanguage, remotePath: string, metadataContent: Record<string, any>): Promise<void> {
// generate the script lock running a dependency job in Windmill and update it inplace
// TODO: update this once the client is released
const rawResponse = await fetch(`${workspace.remote}api/w/${workspace.workspaceId}/jobs/run/dependencies`, {
method: "POST",
headers: {
"Cookie": `token=${workspace.token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"raw_scripts": [{
"raw_code": scriptContent,
"language": language,
"script_path": remotePath,
}],
"entrypoint": remotePath,
})
});
try {
const response = await rawResponse.json();
const lock = response.lock;
if (lock === undefined) {
throw new Error(`Failed to generate lockfile. Full response was: ${JSON.stringify(response)}`);
}
metadataContent.lock = lock.split("\n");
} catch {
throw new Error(`Failed to generate lockfile. Status was: ${rawResponse.statusText}`);
}
}
const command = new Command()
.description("script related commands")
.option("--show-archived", "Enable archived scripts in output")
@@ -505,8 +848,18 @@ const command = new Command()
)
.option(
"-s --silent",
"Do not ouput anything other then the final output. Useful for scripting."
"Do not output anything other then the final output. Useful for scripting."
)
.action(run as any);
.action(run as any)
.command("bootstrap", "create a new script")
.arguments("<path:string> <language:string>")
.option("--summary <summary:string>", "script summary")
.option("--description <description:string>", "script description")
.action(bootstrap as any)
.command("generate-metadata", "re-generate the metadata file updating the lock and the script schema")
.arguments("<path:string>")
.option("--lock-only", "re-generate only the lock")
.option("--schema-only", "re-generate only script schema")
.action(generateMetadata as any);
export default command;
+832
View File
@@ -0,0 +1,832 @@
// @generated file from wasmbuild -- do not edit
// deno-lint-ignore-file
// deno-fmt-ignore-file
// source-hash: f38890e80d35ec2affe2a260e12308f96bcbf771
let wasm;
const heap = new Array(128).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) {
return heap[idx];
}
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 132) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
let WASM_VECTOR_LEN = 0;
let cachedUint8Memory0 = null;
function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
const cachedTextEncoder = typeof TextEncoder !== "undefined"
? new TextEncoder("utf-8")
: {
encode: () => {
throw Error("TextEncoder not available");
},
};
const encodeString = function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
};
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length, 1) >>> 0;
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len, 1) >>> 0;
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
function isLikeNone(x) {
return x === undefined || x === null;
}
let cachedInt32Memory0 = null;
function getInt32Memory0() {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachedInt32Memory0;
}
const cachedTextDecoder = typeof TextDecoder !== "undefined"
? new TextDecoder("utf-8", { ignoreBOM: true, fatal: true })
: {
decode: () => {
throw Error("TextDecoder not available");
},
};
if (typeof TextDecoder !== "undefined") cachedTextDecoder.decode();
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
let cachedFloat64Memory0 = null;
function getFloat64Memory0() {
if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) {
cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer);
}
return cachedFloat64Memory0;
}
let cachedBigInt64Memory0 = null;
function getBigInt64Memory0() {
if (
cachedBigInt64Memory0 === null || cachedBigInt64Memory0.byteLength === 0
) {
cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer);
}
return cachedBigInt64Memory0;
}
function debugString(val) {
// primitive types
const type = typeof val;
if (type == "number" || type == "boolean" || val == null) {
return `${val}`;
}
if (type == "string") {
return `"${val}"`;
}
if (type == "symbol") {
const description = val.description;
if (description == null) {
return "Symbol";
} else {
return `Symbol(${description})`;
}
}
if (type == "function") {
const name = val.name;
if (typeof name == "string" && name.length > 0) {
return `Function(${name})`;
} else {
return "Function";
}
}
// objects
if (Array.isArray(val)) {
const length = val.length;
let debug = "[";
if (length > 0) {
debug += debugString(val[0]);
}
for (let i = 1; i < length; i++) {
debug += ", " + debugString(val[i]);
}
debug += "]";
return debug;
}
// Test for built-in
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
let className;
if (builtInMatches.length > 1) {
className = builtInMatches[1];
} else {
// Failed to match the standard '[object ClassName]'
return toString.call(val);
}
if (className == "Object") {
// we're a user defined class or Object
// JSON.stringify avoids problems with cycles, and is generally much
// easier than looping through ownProperties of `val`.
try {
return "Object(" + JSON.stringify(val) + ")";
} catch (_) {
return "Object";
}
}
// errors
if (val instanceof Error) {
return `${val.name}: ${val.message}\n${val.stack}`;
}
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_deno(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_deno(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_outputs(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_outputs(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_ts_imports(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_ts_imports(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_bash(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_bash(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_powershell(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_powershell(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_go(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_go(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_python(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_python(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_sql(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_sql(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_mysql(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_mysql(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_bigquery(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_bigquery(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_snowflake(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_snowflake(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_mssql(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_mssql(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_graphql(code) {
let deferred2_0;
let deferred2_1;
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(
code,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len0 = WASM_VECTOR_LEN;
wasm.parse_graphql(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
deferred2_0 = r0;
deferred2_1 = r1;
return getStringFromWasm0(r0, r1);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
}
}
function handleError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}
const imports = {
__wbindgen_placeholder__: {
__wbindgen_object_drop_ref: function (arg0) {
takeObject(arg0);
},
__wbindgen_string_get: function (arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof obj === "string" ? obj : undefined;
var ptr1 = isLikeNone(ret)
? 0
: passStringToWasm0(
ret,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
},
__wbindgen_error_new: function (arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
},
__wbindgen_boolean_get: function (arg0) {
const v = getObject(arg0);
const ret = typeof v === "boolean" ? (v ? 1 : 0) : 2;
return ret;
},
__wbindgen_is_bigint: function (arg0) {
const ret = typeof (getObject(arg0)) === "bigint";
return ret;
},
__wbindgen_bigint_from_i64: function (arg0) {
const ret = arg0;
return addHeapObject(ret);
},
__wbindgen_jsval_eq: function (arg0, arg1) {
const ret = getObject(arg0) === getObject(arg1);
return ret;
},
__wbindgen_bigint_from_u64: function (arg0) {
const ret = BigInt.asUintN(64, arg0);
return addHeapObject(ret);
},
__wbindgen_number_get: function (arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof obj === "number" ? obj : undefined;
getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret;
getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret);
},
__wbindgen_is_object: function (arg0) {
const val = getObject(arg0);
const ret = typeof val === "object" && val !== null;
return ret;
},
__wbindgen_in: function (arg0, arg1) {
const ret = getObject(arg0) in getObject(arg1);
return ret;
},
__wbg_eval_c330e1bec5b1705c: function (arg0, arg1) {
const ret = eval(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
},
__wbindgen_jsval_loose_eq: function (arg0, arg1) {
const ret = getObject(arg0) == getObject(arg1);
return ret;
},
__wbg_get_f01601b5a68d10e3: function (arg0, arg1) {
const ret = getObject(arg0)[arg1 >>> 0];
return addHeapObject(ret);
},
__wbg_length_1009b1af0c481d7b: function (arg0) {
const ret = getObject(arg0).length;
return ret;
},
__wbindgen_is_function: function (arg0) {
const ret = typeof (getObject(arg0)) === "function";
return ret;
},
__wbg_next_9b877f231f476d01: function (arg0) {
const ret = getObject(arg0).next;
return addHeapObject(ret);
},
__wbg_next_6529ee0cca8d57ed: function () {
return handleError(function (arg0) {
const ret = getObject(arg0).next();
return addHeapObject(ret);
}, arguments);
},
__wbg_done_5fe336b092d60cf2: function (arg0) {
const ret = getObject(arg0).done;
return ret;
},
__wbg_value_0c248a78fdc8e19f: function (arg0) {
const ret = getObject(arg0).value;
return addHeapObject(ret);
},
__wbg_iterator_db7ca081358d4fb2: function () {
const ret = Symbol.iterator;
return addHeapObject(ret);
},
__wbg_get_7b48513de5dc5ea4: function () {
return handleError(function (arg0, arg1) {
const ret = Reflect.get(getObject(arg0), getObject(arg1));
return addHeapObject(ret);
}, arguments);
},
__wbg_call_90c26b09837aba1c: function () {
return handleError(function (arg0, arg1) {
const ret = getObject(arg0).call(getObject(arg1));
return addHeapObject(ret);
}, arguments);
},
__wbg_isArray_74fb723e24f76012: function (arg0) {
const ret = Array.isArray(getObject(arg0));
return ret;
},
__wbg_instanceof_ArrayBuffer_e7d53d51371448e2: function (arg0) {
let result;
try {
result = getObject(arg0) instanceof ArrayBuffer;
} catch (_) {
result = false;
}
const ret = result;
return ret;
},
__wbg_isSafeInteger_f93fde0dca9820f8: function (arg0) {
const ret = Number.isSafeInteger(getObject(arg0));
return ret;
},
__wbg_entries_9e2e2aa45aa5094a: function (arg0) {
const ret = Object.entries(getObject(arg0));
return addHeapObject(ret);
},
__wbg_buffer_a448f833075b71ba: function (arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
},
__wbg_new_8f67e318f15d7254: function (arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
},
__wbg_set_2357bf09366ee480: function (arg0, arg1, arg2) {
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
},
__wbg_length_1d25fa9e4ac21ce7: function (arg0) {
const ret = getObject(arg0).length;
return ret;
},
__wbg_instanceof_Uint8Array_bced6f43aed8c1aa: function (arg0) {
let result;
try {
result = getObject(arg0) instanceof Uint8Array;
} catch (_) {
result = false;
}
const ret = result;
return ret;
},
__wbindgen_bigint_get_as_i64: function (arg0, arg1) {
const v = getObject(arg1);
const ret = typeof v === "bigint" ? v : undefined;
getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? BigInt(0) : ret;
getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret);
},
__wbindgen_debug_string: function (arg0, arg1) {
const ret = debugString(getObject(arg1));
const ptr1 = passStringToWasm0(
ret,
wasm.__wbindgen_malloc,
wasm.__wbindgen_realloc,
);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
},
__wbindgen_throw: function (arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
},
__wbindgen_memory: function () {
const ret = wasm.memory;
return addHeapObject(ret);
},
},
};
import { Loader } from "https://deno.land/x/wasmbuild@0.15.4/loader.ts";
import { cacheToLocalDir } from "https://deno.land/x/wasmbuild@0.15.4/cache.ts";
const loader = new Loader({
imports,
cache: cacheToLocalDir,
});
/**
* Decompression callback
*
* @callback DecompressCallback
* @param {Uint8Array} compressed
* @return {Uint8Array} decompressed
*/
/**
* Options for instantiating a Wasm instance.
* @typedef {Object} InstantiateOptions
* @property {URL=} url - Optional url to the Wasm file to instantiate.
* @property {DecompressCallback=} decompress - Callback to decompress the
* raw Wasm file bytes before instantiating.
*/
/** Instantiates an instance of the Wasm module returning its functions.
* @remarks It is safe to call this multiple times and once successfully
* loaded it will always return a reference to the same object.
* @param {InstantiateOptions=} opts
*/
export async function instantiate(opts) {
return (await instantiateWithInstance(opts)).exports;
}
/** Instantiates an instance of the Wasm module along with its exports.
* @remarks It is safe to call this multiple times and once successfully
* loaded it will always return a reference to the same object.
* @param {InstantiateOptions=} opts
* @returns {Promise<{
* instance: WebAssembly.Instance;
* exports: { parse_deno: typeof parse_deno; parse_outputs: typeof parse_outputs; parse_ts_imports: typeof parse_ts_imports; parse_bash: typeof parse_bash; parse_powershell: typeof parse_powershell; parse_go: typeof parse_go; parse_python: typeof parse_python; parse_sql: typeof parse_sql; parse_mysql: typeof parse_mysql; parse_bigquery: typeof parse_bigquery; parse_snowflake: typeof parse_snowflake; parse_mssql: typeof parse_mssql; parse_graphql: typeof parse_graphql }
* }>}
*/
export async function instantiateWithInstance(opts) {
const { instance } = await loader.load(
opts?.url ?? new URL("windmill_parser_wasm_bg.wasm", import.meta.url),
opts?.decompress,
);
wasm = wasm ?? instance.exports;
cachedInt32Memory0 = cachedInt32Memory0 ?? new Int32Array(wasm.memory.buffer);
cachedUint8Memory0 = cachedUint8Memory0 ?? new Uint8Array(wasm.memory.buffer);
return {
instance,
exports: getWasmInstanceExports(),
};
}
function getWasmInstanceExports() {
return {
parse_deno,
parse_outputs,
parse_ts_imports,
parse_bash,
parse_powershell,
parse_go,
parse_python,
parse_sql,
parse_mysql,
parse_bigquery,
parse_snowflake,
parse_mssql,
parse_graphql,
};
}
/** Gets if the Wasm module has been instantiated. */
export function isInstantiated() {
return loader.instance != null;
}
Binary file not shown.