@superblocksteam/cli 2.0.0-next.44 → 2.0.0-next.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +5 -5
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ $ npm install -g @superblocksteam/cli
|
|
|
14
14
|
$ superblocks COMMAND
|
|
15
15
|
running command...
|
|
16
16
|
$ superblocks (--version)
|
|
17
|
-
@superblocksteam/cli/2.0.0-next.
|
|
17
|
+
@superblocksteam/cli/2.0.0-next.45 linux-x64 node-v20.19.0
|
|
18
18
|
$ superblocks --help [COMMAND]
|
|
19
19
|
USAGE
|
|
20
20
|
$ superblocks COMMAND
|
package/dist/index.js
CHANGED
|
@@ -256986,7 +256986,7 @@ var import_util4 = __toESM(require_dist4(), 1);
|
|
|
256986
256986
|
// ../sdk/package.json
|
|
256987
256987
|
var package_default = {
|
|
256988
256988
|
name: "@superblocksteam/sdk",
|
|
256989
|
-
version: "2.0.0-next.
|
|
256989
|
+
version: "2.0.0-next.45",
|
|
256990
256990
|
type: "module",
|
|
256991
256991
|
description: "Superblocks JS SDK",
|
|
256992
256992
|
homepage: "https://www.superblocks.com",
|
|
@@ -257024,8 +257024,8 @@ var package_default = {
|
|
|
257024
257024
|
"@rollup/wasm-node": "^4.35.0",
|
|
257025
257025
|
"@superblocksteam/bucketeer-sdk": "0.4.1",
|
|
257026
257026
|
"@superblocksteam/shared": "0.9137.0",
|
|
257027
|
-
"@superblocksteam/util": "2.0.0-next.
|
|
257028
|
-
"@superblocksteam/vite-plugin-file-sync": "2.0.0-next.
|
|
257027
|
+
"@superblocksteam/util": "2.0.0-next.45",
|
|
257028
|
+
"@superblocksteam/vite-plugin-file-sync": "2.0.0-next.45",
|
|
257029
257029
|
"@vitejs/plugin-react": "^4.3.4",
|
|
257030
257030
|
axios: "^1.4.0",
|
|
257031
257031
|
chokidar: "^4.0.3",
|
|
@@ -308732,7 +308732,7 @@ async function startVite({ app, httpServer: httpServer2, root: root2, mode, port
|
|
|
308732
308732
|
};
|
|
308733
308733
|
const isCustomBuildEnabled2 = await isCustomComponentsEnabled();
|
|
308734
308734
|
const customFolder = path21.join(root2, "custom");
|
|
308735
|
-
const cdnUrl = "https://assets-cdn.superblocks.com/library/2.0.0-next.
|
|
308735
|
+
const cdnUrl = "https://assets-cdn.superblocks.com/library/2.0.0-next.45";
|
|
308736
308736
|
const env3 = loadEnv(mode, root2, "");
|
|
308737
308737
|
const hmrPort = await getFreePort();
|
|
308738
308738
|
const hmrOptions = {
|
|
@@ -315067,7 +315067,7 @@ var templates = {
|
|
|
315067
315067
|
"shim-loader.mjs": 'import path from "path";\nimport { pathToFileURL } from "url";\n\nconst overrideMap = {\n "@superblocksteam/library": "./dist/superblocks-library-shim/index.js",\n};\n\nexport async function resolve(specifier, context, nextResolve) {\n if (overrideMap[specifier]) {\n const fullPath = path.resolve(overrideMap[specifier]);\n return {\n shortCircuit: true,\n url: pathToFileURL(fullPath).href,\n };\n }\n\n return nextResolve(specifier, context);\n}\n',
|
|
315068
315068
|
"src/do-eval-to-sdk.ts": 'import fs from "fs";\nimport path from "path";\nimport { fileURLToPath } from "url";\n\n// finds all JavaScript files in the `dist/apis-to-transform` directory,\n// imports each module, converts its JSON representation to SDK,\n// and outputs a JSON map with filenames as keys and SDK content as values.\n\nasync function main() {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n const apisDir = path.resolve(__dirname, "./to-sdk");\n\n const files = fs.readdirSync(apisDir);\n\n const jsFiles = files.filter(\n (file) => file.endsWith(".js") && file !== "__template__.js",\n );\n\n const results: Record<string, string> = {};\n\n for (const jsFile of jsFiles) {\n const filePath = path.join(apisDir, jsFile);\n const absolutePath = path.resolve(filePath);\n\n try {\n const fileUrl = new URL(`file://${absolutePath}`);\n const module = await import(fileUrl.href);\n\n const defaultExport = module.default;\n\n if (defaultExport && typeof defaultExport.toSDK === "function") {\n const sdkData = await defaultExport.toSDK();\n\n results[jsFile] = sdkData;\n } else {\n console.warn(`${jsFile}: Default export doesn\'t have a toSDK method`);\n }\n } catch (error) {\n console.error(`Error processing ${jsFile}:`, error);\n }\n }\n\n console.log(JSON.stringify(results, null, 2));\n}\n\nmain().catch((error) => {\n console.error("Error:", error);\n process.exit(1);\n});\n',
|
|
315069
315069
|
"src/do-eval-to-yaml.ts": 'import fs from "fs";\nimport path from "path";\nimport { fileURLToPath } from "url";\nimport yaml from "yaml";\n\n// finds all JavaScript files in the `dist/apis-to-transform` directory,\n// imports each module, converts its JSON representation to YAML,\n// and outputs a JSON map with filenames as keys and YAML content as values.\n\nasync function main() {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n const apisDir = path.resolve(__dirname, "./to-yaml");\n\n const files = fs.readdirSync(apisDir);\n\n const jsFiles = files.filter((file) => file.endsWith(".js"));\n\n const results: Record<string, string> = {};\n\n for (const jsFile of jsFiles) {\n const filePath = path.join(apisDir, jsFile);\n const absolutePath = path.resolve(filePath);\n\n try {\n const fileUrl = new URL(`file://${absolutePath}`);\n const module = await import(fileUrl.href);\n\n const defaultExport = module.default;\n\n if (defaultExport && typeof defaultExport.toJSON === "function") {\n const jsonData = await defaultExport.toJSON();\n\n const yamlContent = yaml.stringify(jsonData);\n\n results[jsFile] = yamlContent;\n } else {\n console.warn(`${jsFile}: Default export doesn\'t have a toJSON method`);\n }\n } catch (error) {\n console.error(`Error processing ${jsFile}:`, error);\n }\n }\n\n console.log(JSON.stringify(results, null, 2));\n}\n\nmain().catch((error) => {\n console.error("Error:", error);\n process.exit(1);\n});\n',
|
|
315070
|
-
"src/superblocks-library-shim/index.ts": '/* eslint-disable */\nimport typescript_eslint_parser from "@typescript-eslint/parser";\nimport { CallExpression, ExpressionStatement, FunctionExpression, Node, parse, Program, UnaryExpression } from "acorn";\nimport { ESLint } from "eslint";\nimport { format } from "prettier";\n\nexport type JsonValue =\n | undefined\n | null\n | number\n | string\n | boolean\n | Array<JsonValue>\n | { [key: string]: JsonValue };\nexport type State = { [key: string]: JsonValue };\nexport type Binding<T> = T | ((state: State) => T);\n\nexport const code = (\n fn: string,\n options: { iife?: boolean } = { iife: false },\n): string => {\n // Parse the function string\n const ast = parse(fn, {\n ecmaVersion: "latest",\n sourceType: "script",\n });\n\n // Find the function declaration/expression\n let functionNode;\n\n // Walk through the AST to find the function\n if (ast.body[0].type === "FunctionDeclaration") {\n // Function declaration: function name() {}\n functionNode = ast.body[0];\n } else if (\n ast.body[0].type === "ExpressionStatement" &&\n (ast.body[0].expression.type === "FunctionExpression" ||\n ast.body[0].expression.type === "ArrowFunctionExpression")\n ) {\n // Function expression: const name = function() {} or const name = () => {}\n functionNode = ast.body[0].expression;\n } else if (\n ast.body[0].type === "VariableDeclaration" &&\n (ast.body[0].declarations[0]?.init?.type === "FunctionExpression" ||\n ast.body[0].declarations[0]?.init?.type === "ArrowFunctionExpression")\n ) {\n // Variable declaration: const name = function() {} or const name = () => {}\n functionNode = ast.body[0].declarations[0]?.init;\n }\n\n if (!functionNode) {\n throw new Error("Could not find a function in the provided string");\n }\n\n // Get the function body\n const body = functionNode.body;\n\n // Extract the source from the original string\n // For arrow functions with an expression body, we return the expression\n if (\n functionNode.type === "ArrowFunctionExpression" &&\n body.type !== "BlockStatement"\n ) {\n // Arrow function with expression body: () => 42\n const expressionCode = fn.substring(fn.indexOf("=>") + 2).trim();\n return options.iife\n ? `(() => ${expressionCode})()`\n : `return ${expressionCode}`;\n }\n\n // For functions with block bodies, extract content between braces\n const start = body.start + 1; // Skip the opening brace\n const end = body.end - 1; // Skip the closing brace\n\n // Get the raw body content\n const rawBodyLines = fn.substring(start, end).split("\\n");\n\n if (rawBodyLines.length <= 1) {\n // Single line body, just trim it\n const bodyCode = rawBodyLines[0].trim();\n\n if (options.iife) {\n const paramStart = fn.indexOf("(");\n const paramEnd = fn.indexOf(")", paramStart);\n const params = fn.substring(paramStart, paramEnd + 1);\n return `(${params} => { ${bodyCode} })()`;\n }\n\n return bodyCode;\n }\n\n // For multi-line bodies, normalize indentation\n // Find the minimum indentation level (ignoring empty lines)\n let minIndent = Infinity;\n for (const line of rawBodyLines) {\n const trimmedLine = line.trimStart();\n if (trimmedLine.length > 0) {\n const indent = line.length - trimmedLine.length;\n minIndent = Math.min(minIndent, indent);\n }\n }\n\n // Remove the common indentation from each line\n const normalizedLines = rawBodyLines.map((line) => {\n if (line.trimStart().length === 0) return "";\n return line.substring(minIndent);\n });\n\n // Join the normalized lines\n const bodyCode = normalizedLines\n .join(" ")\n .replace(/\\s{2,}/g, " ")\n .trim();\n\n if (options.iife) {\n const paramStart = fn.indexOf("(");\n const paramEnd = fn.indexOf(")", paramStart);\n const params = fn.substring(paramStart, paramEnd + 1);\n return `(${params} => { ${bodyCode} })()`;\n }\n\n return bodyCode;\n};\n\nasync function binding(binding: Binding<string>): Promise<string> {\n if (typeof binding === "function") {\n return await toJS(binding);\n }\n\n return binding;\n}\n\ninterface Codec {\n toJSON(): Promise<JsonValue>;\n toSDK(entities: string[]): Promise<string>;\n}\n\nexport abstract class Block implements Codec {\n protected name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n public abstract toJSON(): Promise<JsonValue>;\n public abstract toSDK(entities: string[]): Promise<string>;\n\n public static fromJSON(json: any, entities: string[]): Block {\n if (json?.step) {\n return Integration.fromJSON(json, entities);\n }\n\n if ("conditional" in json) {\n return Conditional.fromJSON(json, entities);\n }\n\n if ("loop" in json) {\n return Loop.fromJSON(json, entities);\n }\n\n if ("parallel" in json) {\n return Parallel.fromJSON(json, entities);\n }\n\n if ("tryCatch" in json) {\n return TryCatch.fromJSON(json, entities);\n }\n\n if ("variables" in json) {\n return Variables.fromJSON(json, entities);\n }\n\n if ("throw" in json) {\n return Throw.fromJSON(json, entities);\n }\n\n if ("return" in json) {\n return Return.fromJSON(json, entities);\n }\n\n throw new Error("mysterious block");\n }\n}\n\nexport abstract class Integration extends Block {\n protected integration: string;\n\n constructor(name: string, integration: string) {\n super(name);\n\n this.integration = integration;\n }\n\n public abstract toJSON(): Promise<JsonValue>;\n public abstract toSDK(entities: string[]): Promise<string>;\n\n public static fromJSON(json: any, entities: string[]): Block {\n if ("javascript" in json?.step) {\n return JavaScript.fromJSON(json, entities);\n }\n\n if ("python" in json?.step) {\n return Python.fromJSON(json, entities);\n }\n\n if ("postgres" in json?.step) {\n return PostgreSQL.fromJSON(json, entities);\n }\n\n if ("databricks" in json?.step) {\n return Databricks.fromJSON(json, entities);\n }\n\n if ("email" in json?.step) {\n return Email.fromJSON(json, entities);\n }\n\n if ("restapi" in json?.step) {\n return RestApi.fromJSON(json, entities);\n }\n\n throw new Error("mysterious integration");\n }\n}\n\nexport class Python extends Integration {\n private fn: string;\n\n constructor(name: string, config: {\n fn: string;\n }) {\n super(name, "python");\n\n this.fn = config.fn;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "python",\n python: {\n body: this.fn,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Python("${this.name}", { fn: ${this.fn} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Python {\n return new Python(json?.name, {\n fn: json?.step?.python?.body,\n });\n }\n}\n\nexport class JavaScript extends Integration {\n private fn: (_: State) => JsonValue;\n\n constructor(\n name: string,\n config: {\n fn: (_: State) => JsonValue;\n },\n ) {\n super(name, "javascript");\n\n this.fn = config.fn;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "javascript",\n javascript: {\n body: await toJSBody(this.fn, { block: false, function: true }),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new JavaScript("${this.name}", { fn: ${signature(code(this.fn.toString()), entities)} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): JavaScript {\n const args = [json?.step?.javascript?.body]\n const references = referenced(json?.step?.javascript?.body, entities)\n\n if (references.length > 0) {\n args.unshift(`{ ${references.join(", ")} }`)\n }\n\n return new JavaScript(json?.name, {\n fn: new Function(...args) as (_: State) => JsonValue,\n });\n }\n}\n\n// TODO(Frank): There is way too much in common between Snowflake and PostgreSQL. Need to add a parent class for these.\nexport class Snowflake extends Integration {\n private statement: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n ) {\n super(name, integration);\n\n this.statement = config.statement;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n snowflake: {\n body: await binding(this.statement),\n usePreparedSql: false,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Snowflake("${this.name}", "${this.integration}", { statement: ${typeof this.statement === "function" ? signatureV2(await toJSBody(this.statement), entities) : `"${this.statement}"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Snowflake {\n return new Snowflake(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.snowflake?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class PostgreSQL extends Integration {\n private statement: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n ) {\n super(name, integration);\n\n this.statement = config.statement;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n postgres: {\n body: await binding(this.statement),\n usePreparedSql: false,\n operation: "run_sql",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new PostgreSQL("${this.name}", "${this.integration}", { statement: ${typeof this.statement === "function" ? signatureV2(await toJSBody(this.statement), entities) : `"${this.statement}"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): PostgreSQL {\n return new PostgreSQL(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.postgres?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class RestApi extends Integration {\n private method: string;\n private url: Binding<string>;\n private headers?: { key: Binding<string>; value: Binding<string> }[];\n private params?: { key: Binding<string>; value: Binding<string> }[];\n private body?: Binding<string>;\n\n constructor(\n name: string,\n config: {\n method: string;\n url?: Binding<string>;\n headers?: { key: Binding<string>; value: Binding<string> }[];\n params?: { key: Binding<string>; value: Binding<string> }[];\n body?: Binding<string>;\n },\n ) {\n super(name, "restapi");\n\n this.method = config.method;\n this.url = config.url;\n this.headers = config.headers;\n this.params = config.params;\n this.body = config.body;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "restapi",\n restapi: {\n httpMethod: this.method,\n ...(this.url ? { path: await binding(this.url) } : {}),\n ...(this.headers ? { headers: await Promise.all(this.headers.map(async (header) => ({ key: await binding(header.key), value: await binding(header.value) }))) } : {}),\n ...(this.params ? { params: await Promise.all(this.params.map(async (param) => ({ key: await binding(param.key), value: await binding(param.value) }))) } : {}),\n ...(this.body ? { body: await binding(this.body) } : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [`method: "${this.method}"`];\n\n if (this.url) {\n parts.push(\n `url: ${\n typeof this.url === "function"\n ? signatureV2(await toJSBody(this.url), entities)\n : `"${this.url}"`\n }`,\n );\n }\n\n if (this.headers) {\n const headers = this.headers\n .map(async (h) =>\n `{ key: ${\n typeof h.key === "function"\n ? signatureV2(await toJSBody(h.key), entities)\n : `"${h.key}"`\n }, value: ${\n typeof h.value === "function"\n ? signatureV2(await toJSBody(h.value), entities)\n : `"${h.value}"`\n } }`,\n )\n .join(", ");\n parts.push(`headers: [${headers}]`);\n }\n\n if (this.params) {\n const params = this.params\n .map(async (p) =>\n `{ key: ${\n typeof p.key === "function"\n ? signatureV2(await toJSBody(p.key), entities)\n : `"${p.key}"`\n }, value: ${\n typeof p.value === "function"\n ? signatureV2(await toJSBody(p.value), entities)\n : `"${p.value}"`\n } }`,\n )\n .join(", ");\n parts.push(`params: [${params}]`);\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === "function"\n ? signatureV2(await toJSBody(this.body), entities)\n : JSON.stringify(this.body)\n }`,\n );\n }\n\n return `new RestApi("${this.name}", { ${parts.join(", ")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): RestApi {\n return new RestApi(json?.name, {\n method: json?.step?.restapi?.httpMethod,\n url: fromBinding(json?.step?.restapi?.path, entities),\n headers: json?.step?.restapi?.headers?.map((header: any) => ({ key: fromBinding(header.key, entities), value: fromBinding(header.value, entities) })),\n params: json?.step?.restapi?.params?.map((param: any) => ({ key: fromBinding(param.key, entities), value: fromBinding(param.value, entities) })),\n body: fromBinding(json?.step?.restapi?.body, entities),\n });\n }\n}\n\nexport class Email extends Integration {\n private subject: Binding<string>;\n private from: Binding<string>; // comma separated list\n private to: Binding<string>; // comma separated list\n private cc?: Binding<string>; // comma separated list\n private bcc?: Binding<string>; // comma separated list\n private body: Binding<string>;\n\n constructor(\n name: string,\n config: {\n from: Binding<string>;\n to: Binding<string>;\n subject: Binding<string>;\n cc?: Binding<string>;\n bcc?: Binding<string>;\n body?: Binding<string>;\n },\n ) {\n super(name, "email");\n\n this.from = config.from;\n this.to = config.to;\n this.subject = config.subject;\n this.cc = config.cc;\n this.bcc = config.bcc;\n this.body = config.body;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "email",\n email: {\n ...(this.from ? { emailFrom: await binding(this.from) } : {}),\n ...(this.to ? { emailTo: await binding(this.to) } : {}),\n ...(this.cc ? { emailCc: await binding(this.cc) } : {}),\n ...(this.bcc ? { emailBcc: await binding(this.bcc) } : {}),\n ...(this.subject ? { emailSubject: await binding(this.subject) } : {}),\n ...(this.body ? { emailBody: await binding(this.body) } : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [];\n\n if (this.from) {\n parts.push(\n `from: ${\n typeof this.from === "function"\n ? signatureV2(code(this.from.toString()), entities)\n : `"${this.from}"`\n }`,\n );\n }\n\n if (this.to) {\n parts.push(\n `to: ${\n typeof this.to === "function"\n ? signatureV2(code(this.to.toString()), entities)\n : `"${this.to}"`\n }`,\n );\n }\n\n if (this.cc) {\n parts.push(\n `cc: ${\n typeof this.cc === "function"\n ? signatureV2(code(this.cc.toString()), entities)\n : `"${this.cc}"`\n }`,\n );\n }\n\n if (this.bcc) {\n parts.push(\n `bcc: ${\n typeof this.bcc === "function"\n ? signatureV2(code(this.bcc.toString()), entities)\n : `"${this.bcc}"`\n }`,\n );\n }\n\n if (this.subject) {\n parts.push(\n `subject: ${\n typeof this.subject === "function"\n ? signatureV2(code(this.subject.toString()), entities)\n : `"${this.subject}"`\n }`,\n );\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === "function"\n ? signatureV2(code(this.body.toString()), entities)\n : `"${this.body}"`\n }`,\n );\n }\n\n return `new Email("${this.name}", { ${parts.join(", ")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Email {\n return new Email(json?.name, {\n from: fromBinding(json?.step?.email?.emailFrom, entities),\n to: fromBinding(json?.step?.email?.emailTo, entities),\n subject: fromBinding(json?.step?.email?.emailSubject, entities),\n body: fromBinding(json?.step?.email?.emailBody, entities),\n cc: json?.step?.email?.emailCc ? fromBinding(json?.step?.email?.emailCc, entities) : undefined,\n bcc: json?.step?.email?.emailBcc ? fromBinding(json?.step?.email?.emailBcc, entities) : undefined,\n });\n }\n}\n\nexport class Databricks extends Integration {\n private statement: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n ) {\n super(name, integration);\n\n this.statement = config.statement;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n databricks: {\n runSql: {\n sqlBody: await binding(this.statement),\n useParameterized: false,\n },\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Databricks("${this.name}", "${this.integration}", { statement: ${typeof this.statement === "function" ? signatureV2(await toJSBody(this.statement), entities) : `"${this.statement}"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Databricks {\n return new Databricks(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.databricks?.runSql?.sqlBody as string,\n entities,\n ),\n });\n }\n}\n\nexport type Condition = {\n when: Binding<boolean>;\n then: Block[];\n};\n\nasync function conditionToSDK(condition: Condition, entities: string[]): Promise<string> {\n return `{ when: ${typeof condition.when === "function" ? signatureV2(await toJSBody(condition.when), entities) : condition.when}, then: [${(await Promise.all(condition.then.map(async (block) => await block.toSDK(entities)))).join(",")}] }`\n}\n\nexport type Conditions = {\n if: Condition;\n elif?: Condition[];\n else?: Block[];\n};\n\nexport class Conditional extends Block {\n public conditions: Conditions;\n\n constructor(name: string, config: Conditions) {\n super(name);\n\n this.conditions = config;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n conditional: {\n if: {\n condition: await toJS<boolean>(this.conditions.if.when),\n blocks: await Promise.all(this.conditions.if.then.map(async (block) => await block.toJSON())),\n },\n ...await (async () =>\n this.conditions.elif\n ? {\n elseIf: await Promise.all(this.conditions.elif.map(async (condition) => ({\n condition: await toJS<boolean>(condition.when),\n blocks: await Promise.all(condition.then.map(async (block) => await block.toJSON())),\n }))),\n }\n : { elseIf: [] })(),\n else: this.conditions.else ? {\n blocks: await Promise.all(this.conditions.else.map(async (block) => await block.toJSON()))\n } : undefined,\n },\n };\n }\n\n public static fromJSON(json: any, entities: string[]): Conditional {\n return new Conditional(json?.name, {\n if: {\n when: fromJS<boolean>(json?.conditional?.if?.condition, entities),\n then: json?.conditional?.if?.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n },\n elif: json?.conditional?.elseIf ? json?.conditional?.elseIf?.map((condition: any) => ({\n when: fromJS<boolean>(condition.condition, entities),\n then: condition.blocks.map((block: any) => Block.fromJSON(block, entities)),\n })) : [],\n else: json?.conditional?.else ? json?.conditional?.else?.blocks?.map((block: any) => Block.fromJSON(block, entities)) : [],\n });\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Conditional("${this.name}", { if: ${await conditionToSDK(this.conditions.if, entities)}, elif: [${this.conditions.elif ? (await Promise.all(this.conditions.elif?.map(async (condition) => await conditionToSDK(condition, entities)))).join(",") : \'\'}], else: ${this.conditions.else ? (await Promise.all(this.conditions.else?.map(async (block) => await block.toSDK(entities)))).join(",") : "undefined"} })`;\n }\n}\n\nexport class Parallel extends Block {\n private over: Binding<JsonValue[]>;\n private blocks: Block[];\n private variables: { item: string };\n\n constructor(\n name: string,\n config: {\n over: Binding<JsonValue[]>;\n variables: { item: string };\n blocks: Block[];\n },\n ) {\n super(name);\n\n this.over = config.over;\n this.blocks = config.blocks;\n this.variables = config.variables;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n parallel: {\n dynamic: {\n blocks: await Promise.all(this.blocks?.map(async (block) => await block.toJSON())),\n paths: await toJS<JsonValue[]>(this.over),\n variables: this.variables,\n },\n wait: "WAIT_ALL",\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Parallel("${this.name}", { over: ${typeof this.over === "function" ? signatureV2(await toJSBody(this.over), entities) : this.over}, variables: ${this.variables}, blocks: ${await Promise.all(this.blocks.map(async (block) => await block.toSDK(entities)).join(","))} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Parallel {\n return new Parallel(json?.name, {\n over: fromJS<JsonValue[]>(json?.parallel?.dynamic?.paths, entities),\n variables: {\n item: json?.parallel?.dynamic?.variables?.item,\n },\n blocks: json?.parallel?.dynamic?.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n });\n }\n}\n\nexport class Loop extends Block {\n private over: Binding<JsonValue[]>; // NOTE(Frank): Only for each loops are supported at the moment.\n private blocks: Block[];\n private variables: { item: string; index: string };\n\n constructor(\n name: string,\n config: {\n over: Binding<JsonValue[]>;\n variables: { item: string; index: string };\n blocks: Block[];\n },\n ) {\n super(name);\n\n this.over = config.over;\n this.variables = config.variables;\n this.blocks = config.blocks;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n loop: {\n range: await toJS<JsonValue[]>(this.over),\n type: "TYPE_FOREACH",\n variables: this.variables,\n blocks: await Promise.all(this.blocks.map(async (block) => await block.toJSON())),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Loop("${this.name}", { over: ${typeof this.over === "function" ? signatureV2(await toJSBody(this.over), entities) : this.over}, variables: ${this.variables}, blocks: ${await Promise.all(this.blocks.map(async (block) => await block.toSDK(entities)).join(","))} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Loop {\n return new Loop(json?.name, {\n over: fromJS<JsonValue[]>(json?.loop?.range, entities),\n variables: {\n item: json?.loop?.variables?.item,\n index: json?.loop?.variables?.index,\n },\n blocks: json?.loop?.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n });\n }\n}\n\nexport class Variables extends Block {\n private variables: { key: string, value: Binding<JsonValue> }[];\n\n constructor(\n name: string,\n variables: { key: string, value: Binding<JsonValue> }[],\n ) {\n super(name);\n\n this.variables = variables;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n variables: {\n items: await Promise.all(this.variables.map(async (variable) => {\n return {\n key: variable.key,\n value: await toJS<JsonValue>(variable.value),\n type: "TYPE_SIMPLE",\n mode: "MODE_READWRITE",\n };\n }))\n },\n };\n }\n \n public async toSDK(entities: string[]): Promise<string> {\n return `new Variables("${this.name}", [${this.variables?.map((variable) => `{ key: "${variable.key}", value: ${typeof variable.value === "function" ? signature(code(variable.value.toString(), { iife: true }), entities) : variable.value} }`).join(",")}])`;\n }\n\n public static fromJSON(json: any, entities: string[]): Variables {\n return new Variables(json?.name, json?.variables?.items?.map((variable: any) => ({\n key: variable.key,\n value: fromBinding(variable.value, entities),\n })));\n }\n}\n\nexport class TryCatch extends Block {\n private try: Block[];\n private catch: Block[];\n private finally?: Block[];\n private variables: { error: string };\n\n constructor(\n name: string,\n config: {\n try: Block[];\n catch: Block[];\n finally?: Block[];\n variables: { error: string };\n },\n ) {\n super(name);\n\n this.try = config.try;\n this.catch = config.catch;\n this.finally = config.finally;\n this.variables = config.variables;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n tryCatch: {\n try: { blocks: await Promise.all(this.try.map(async (block) => await block.toJSON())) },\n catch: { blocks: await Promise.all(this.catch.map(async (block) => await block.toJSON())) },\n finally: { blocks: this.finally ? await Promise.all(this.finally.map(async (block) => await block.toJSON())) : [] },\n variables: this.variables,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new TryCatch("${this.name}", { try: ${await Promise.all(this.try.map(async (block) => await block.toSDK(entities)).join(","))}, catch: ${await Promise.all(this.catch.map(async (block) => await block.toSDK(entities)).join(","))}, finally: ${this.finally?.map(async (block) => await block.toSDK(entities)).join(", ")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): TryCatch {\n return new TryCatch(json?.name, {\n try: json?.tryCatch?.try.blocks.map((block: any) => Block.fromJSON(block, entities)),\n catch: json?.tryCatch?.catch.blocks.map((block: any) => Block.fromJSON(block, entities)),\n finally: json?.tryCatch?.finally?.blocks.map((block: any) => Block.fromJSON(block, entities)),\n variables: {\n error: json?.tryCatch?.variables?.error,\n },\n });\n }\n}\n\nexport class Throw extends Block {\n private error: Binding<JsonValue>;\n\n constructor(\n name: string,\n config: {\n error: Binding<JsonValue>;\n },\n ) {\n super(name);\n\n this.error = config.error;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n throw: {\n error: await toJS(this.error),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Throw("${this.name}", { error: ${typeof this.error === "function" ? signature(code(this.error.toString()), entities) : JSON.stringify(this.error)} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Throw {\n return new Throw(json?.name, {\n error: fromJS(json?.throw?.error, entities),\n });\n }\n}\n\nexport class Return extends Block {\n private data: Binding<JsonValue>;\n\n constructor(\n name: string,\n config: {\n data: Binding<JsonValue>;\n },\n ) {\n super(name);\n\n this.data = config.data;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n return: {\n data: await toJS(this.data),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Return("${this.name}", { data: ${typeof this.data === "function" ? signature(code(this.data.toString()), entities) : JSON.stringify(this.data)} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Return {\n return new Return(json?.name, {\n data: fromJS(json?.return?.data, entities),\n });\n }\n}\n\nexport class Api {\n private blocks: Block[];\n private name: string;\n\n constructor(name: string, blocks: Block[]) {\n this.name = name;\n this.blocks = blocks;\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const imports =\n "import { Api, JavaScript, Python, PostgreSQL, Snowflake, Databricks, Conditional, Parallel, Loop, TryCatch, Variables, Throw, Return } from \'@superblocksteam/library\'";\n return `${imports}\\n\\nexport default new Api("${this.name}", [${(await Promise.all(this.blocks.map(async (block) => await block.toSDK(entities)))).join(",")}])`;\n }\n\n public static fromJSON(json: any, entities: string[]): Api {\n // NOTE(Frank): Would probs unmarshal this into the protobuf types and then do the conversion.\n return new Api(\n json?.metadata?.name as string,\n (json.blocks as any[]).map((block) => Block.fromJSON(block, entities)),\n );\n }\n\n public async toJSON(): Promise<JsonValue> {\n const api: {\n metadata: {\n name: string;\n timestamps: {\n updated: string;\n };\n };\n trigger: {\n application: {};\n };\n blocks: JsonValue[];\n } = {\n metadata: {\n name: this.name,\n timestamps: {\n updated: new Date().toISOString(),\n },\n },\n trigger: {\n application: {},\n },\n blocks: [],\n };\n\n api.blocks = await Promise.all(this.blocks.map(async (block) => await block.toJSON()));\n\n return api;\n }\n}\n\nfunction referenced(data: string, entities: string[]): string[] {\n return entities.reduce((acc: string[], entity: string) => {\n if (data.includes(entity)) {\n acc.push(entity);\n }\n return acc;\n }, []);\n}\n\nfunction signature(data: string, entities: string[]): string {\n return `({ ${referenced(data, entities).join(", ")} }) => {${data}}`;\n}\n\nfunction signatureV2(data: string, entities: string[]): string {\n return `({ ${referenced(data, entities).join(", ")} }) => ${data}`;\n}\n\n/**\n * Converts a string binding, which comprise 99% of dynamic integration fields, into a function returning an interpolated string.\n *\n * fromBinding("https://{{ \'goo\' + \'gle\' }}.com/{{ Dropdown1.value }}", [\'Dropdown1\']) -> ({ Dropdown1 }) => `https://${\'goo\' + \'gle\'}.com/${Dropdown1.value}`\n *\n * @param value - The value to convert.\n * @param entities - The master list of possible entities that could be referenced in the binding.\n *\n * @returns The converted value.\n */\nexport function fromBinding(value: string, entities: string[]): Binding<string> {\n if (!value) {\n return "";\n }\n\n const regex = /\\{\\{\\s*([^}]*)\\s*\\}\\}/g;\n const converted: string = value.replace(regex, (match, content) => `\\${${content.trim()}}`);\n\n // there were no bindings to convert\n if (converted === value) {\n return value;\n }\n\n const args: string[] = [`return \\`${converted}\\``]\n const references: string[] = referenced(converted, entities);\n\n // only add the arguments if we have references\n if (references.length > 0) {\n args.unshift(`{ ${references} }`);\n }\n\n return new Function(...args) as (_: State) => string;\n}\n\nasync function beautifyAndOptionallyCondense<T extends JsonValue>(value: ((state: State) => T), node: Node, options: { condense?: boolean, block?: boolean } = { condense: true, block: true }) {\n let start: number = node.start;\n let end: number = node.end;\n\n if (!options.block) {\n start += 1;\n end -= 1;\n }\n \n const beautified = await beautify(value.toString().slice(start, end))\n\n if (options.condense) {\n return beautified.replace(/\\s*\\n\\s*/g, \' \').replace(/\\s+/g, \' \').trim();\n }\n\n return beautified\n}\n\nfunction createAst(value: string): Program {\n return parse(value, {\n ecmaVersion: "latest",\n sourceType: "script",\n preserveParens: false,\n });\n}\n\nasync function toJSBody<T extends JsonValue>(value: ((state: State) => T), options: { block?: boolean, condense?: boolean, function?: boolean } = { block: true, condense: true, function: false }): Promise<string> {\n if (typeof value !== "function") {\n return `{{ ${JSON.stringify(value)} }}`\n }\n\n // parse the code\n const ast = createAst(value.toString());\n const program = ast.body[0];\n\n switch (program.type) {\n case "ExpressionStatement":\n const body = ((program as ExpressionStatement).expression as FunctionExpression).body;\n\n if (body.type === \'BlockStatement\') {\n return await beautifyAndOptionallyCondense(value, body, options)\n }\n\n return `${options.function ? "return " : ""}${value.toString().slice(body.start, body.end)}`\n case "FunctionDeclaration":\n let contents = value.toString().slice(program.body.start, program.body.end)\n\n if (program.body.type !== \'BlockStatement\') {\n return contents\n }\n \n if (!options.function && program.body.body.length === 1 && program.body.body[0].type === \'ReturnStatement\') {\n return value.toString().slice(program.body.body[0].argument.start, program.body.body[0].argument.end)\n }\n\n return await beautifyAndOptionallyCondense(value, program.body, options)\n\n default:\n throw new Error("you found a case we haven\'t handled yet")\n }\n}\n\nexport async function toJS<T extends JsonValue>(value: Binding<T>): Promise<string> {\n if (typeof value !== "function") {\n return `{{ ${JSON.stringify(value)} }}`\n }\n\n const body = await toJSBody(value)\n return `{{ (() => ${body})() }}`\n}\n\nexport function fromJS<T extends JsonValue>(\n value: string,\n entities: string[] = [],\n): Binding<T> {\n // determine if there are entities referenced in the value\n const refs = referenced(value, entities).join(", ")\n\n\n // remove any surrounding whitespace\n value = value.trim()\n\n // require bindings\n if (!value.startsWith("{{") || !value.endsWith("}}")) {\n throw new Error("bindings must always be wrapped in double curly braces");\n }\n\n // remove the double curly braces and trim whitespace\n value = value.slice(2, -2).trim();\n\n let unaryOps: string[] = [];\n let call = (createAst(value).body[0] as ExpressionStatement).expression;\n\n while (call?.type === \'UnaryExpression\') {\n unaryOps.push((call as UnaryExpression).operator);\n call = (call as unknown as UnaryExpression).argument as CallExpression;\n }\n \n const fn = (call as CallExpression).callee;\n let body = value;\n let prefix = "return ";\n\n // handle iife\n if (fn?.type === "ArrowFunctionExpression") {\n // i\'m not happy with this but I don\'t see another immediate way to handle this.\n // this will result in a correct result but one that isn\'t idemopotent.\n if (unaryOps.length > 0) {\n return new Function(`{ ${refs} }`, `${prefix}${body}`) as (_: State) => T;\n }\n\n\n body = value.slice(fn.body.start, fn.body.end)\n\n if (fn.body.type === \'BlockStatement\') {\n // drop the opening "{" and closing "}"\n body = body.slice(1, -1)\n prefix = ""\n } \n } else if (refs.length === 0) {\n // we\'re not an iife nor do we have references.\n // we might have to revisit this implementation since this technically reduces to a static value down to it\'s most minimal form.\n return eval(value) as T\n }\n\n // we\'re either an iife or a static value with refs.\n return new Function(`{ ${refs} }`, `${prefix}${body}`) as (_: State) => T;\n}\n\nexport async function beautify(code: string): Promise<string> {\n const eslint = new ESLint({\n fix: true,\n overrideConfigFile: true,\n baseConfig: {\n languageOptions: {\n parser: typescript_eslint_parser,\n parserOptions: {\n ecmaVersion: 2020,\n sourceType: "module",\n },\n },\n rules: {\n "arrow-body-style": "error",\n },\n },\n });\n\n code = (await eslint.lintText(code))[0]?.output || code;\n\n return await format(code, {\n parser: "typescript",\n tabWidth: 2,\n // singleQuote: true,\n trailingComma: "none",\n semi: true,\n bracketSpacing: true,\n arrowParens: "always",\n bracketSameLine: false,\n embeddedLanguageFormatting: "auto",\n quoteProps: "as-needed",\n insertPragma: false,\n requirePragma: false,\n useTabs: false,\n endOfLine: "auto",\n arrowFunctionParentheses: "always",\n // plugins: ["prettier-plugin-organize-imports"],\n });\n}\n',
|
|
315070
|
+
"src/superblocks-library-shim/index.ts": '/* eslint-disable */\nimport typescript_eslint_parser from "@typescript-eslint/parser";\nimport { CallExpression, ExpressionStatement, FunctionExpression, Node, parse, Program, UnaryExpression } from "acorn";\nimport { ESLint } from "eslint";\nimport { format } from "prettier";\n\nexport type JsonValue =\n | undefined\n | null\n | number\n | string\n | boolean\n | Array<JsonValue>\n | { [key: string]: JsonValue };\nexport type State = { [key: string]: JsonValue };\nexport type Binding<T> = T | ((state: State) => T);\n\n// DEPRECATED\nexport const code = (\n fn: string,\n options: { iife?: boolean } = { iife: false },\n): string => {\n // Parse the function string\n const ast = parse(fn, {\n ecmaVersion: "latest",\n sourceType: "script",\n });\n\n // Find the function declaration/expression\n let functionNode;\n\n // Walk through the AST to find the function\n if (ast.body[0].type === "FunctionDeclaration") {\n // Function declaration: function name() {}\n functionNode = ast.body[0];\n } else if (\n ast.body[0].type === "ExpressionStatement" &&\n (ast.body[0].expression.type === "FunctionExpression" ||\n ast.body[0].expression.type === "ArrowFunctionExpression")\n ) {\n // Function expression: const name = function() {} or const name = () => {}\n functionNode = ast.body[0].expression;\n } else if (\n ast.body[0].type === "VariableDeclaration" &&\n (ast.body[0].declarations[0]?.init?.type === "FunctionExpression" ||\n ast.body[0].declarations[0]?.init?.type === "ArrowFunctionExpression")\n ) {\n // Variable declaration: const name = function() {} or const name = () => {}\n functionNode = ast.body[0].declarations[0]?.init;\n }\n\n if (!functionNode) {\n throw new Error("Could not find a function in the provided string");\n }\n\n // Get the function body\n const body = functionNode.body;\n\n // Extract the source from the original string\n // For arrow functions with an expression body, we return the expression\n if (\n functionNode.type === "ArrowFunctionExpression" &&\n body.type !== "BlockStatement"\n ) {\n // Arrow function with expression body: () => 42\n const expressionCode = fn.substring(fn.indexOf("=>") + 2).trim();\n return options.iife\n ? `(() => ${expressionCode})()`\n : `return ${expressionCode}`;\n }\n\n // For functions with block bodies, extract content between braces\n const start = body.start + 1; // Skip the opening brace\n const end = body.end - 1; // Skip the closing brace\n\n // Get the raw body content\n const rawBodyLines = fn.substring(start, end).split("\\n");\n\n if (rawBodyLines.length <= 1) {\n // Single line body, just trim it\n const bodyCode = rawBodyLines[0].trim();\n\n if (options.iife) {\n const paramStart = fn.indexOf("(");\n const paramEnd = fn.indexOf(")", paramStart);\n const params = fn.substring(paramStart, paramEnd + 1);\n return `(${params} => { ${bodyCode} })()`;\n }\n\n return bodyCode;\n }\n\n // For multi-line bodies, normalize indentation\n // Find the minimum indentation level (ignoring empty lines)\n let minIndent = Infinity;\n for (const line of rawBodyLines) {\n const trimmedLine = line.trimStart();\n if (trimmedLine.length > 0) {\n const indent = line.length - trimmedLine.length;\n minIndent = Math.min(minIndent, indent);\n }\n }\n\n // Remove the common indentation from each line\n const normalizedLines = rawBodyLines.map((line) => {\n if (line.trimStart().length === 0) return "";\n return line.substring(minIndent);\n });\n\n // Join the normalized lines\n const bodyCode = normalizedLines\n .join(" ")\n .replace(/\\s{2,}/g, " ")\n .trim();\n\n if (options.iife) {\n const paramStart = fn.indexOf("(");\n const paramEnd = fn.indexOf(")", paramStart);\n const params = fn.substring(paramStart, paramEnd + 1);\n return `(${params} => { ${bodyCode} })()`;\n }\n\n return bodyCode;\n};\n\nasync function binding(binding: Binding<string>): Promise<string> {\n if (typeof binding === "function") {\n // (() => 5)() -> `${(() => 5)()}`\n return `\\`\\$\\{${await toJS(binding)}\\}\\``;\n }\n\n return `\\`${binding}\\``;\n}\n\ninterface Codec {\n toJSON(): Promise<JsonValue>;\n toSDK(entities: string[]): Promise<string>;\n}\n\nexport abstract class Block implements Codec {\n protected name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n public abstract toJSON(): Promise<JsonValue>;\n public abstract toSDK(entities: string[]): Promise<string>;\n\n public static fromJSON(json: any, entities: string[]): Block {\n if (json?.step) {\n return Integration.fromJSON(json, entities);\n }\n\n if ("conditional" in json) {\n return Conditional.fromJSON(json, entities);\n }\n\n if ("loop" in json) {\n return Loop.fromJSON(json, entities);\n }\n\n if ("parallel" in json) {\n return Parallel.fromJSON(json, entities);\n }\n\n if ("tryCatch" in json) {\n return TryCatch.fromJSON(json, entities);\n }\n\n if ("variables" in json) {\n return Variables.fromJSON(json, entities);\n }\n\n if ("throw" in json) {\n return Throw.fromJSON(json, entities);\n }\n\n if ("return" in json) {\n return Return.fromJSON(json, entities);\n }\n\n throw new Error("mysterious block");\n }\n}\n\nexport abstract class Integration extends Block {\n protected integration: string;\n\n constructor(name: string, integration: string) {\n super(name);\n\n this.integration = integration;\n }\n\n public abstract toJSON(): Promise<JsonValue>;\n public abstract toSDK(entities: string[]): Promise<string>;\n\n public static fromJSON(json: any, entities: string[]): Block {\n if ("javascript" in json?.step) {\n return JavaScript.fromJSON(json, entities);\n }\n\n if ("python" in json?.step) {\n return Python.fromJSON(json, entities);\n }\n\n if ("postgres" in json?.step) {\n return PostgreSQL.fromJSON(json, entities);\n }\n\n if ("databricks" in json?.step) {\n return Databricks.fromJSON(json, entities);\n }\n\n if ("email" in json?.step) {\n return Email.fromJSON(json, entities);\n }\n\n if ("restapi" in json?.step) {\n return RestApi.fromJSON(json, entities);\n }\n\n throw new Error("mysterious integration");\n }\n}\n\nexport class Python extends Integration {\n private fn: string;\n\n constructor(name: string, config: {\n fn: string;\n }) {\n super(name, "python");\n\n this.fn = config.fn;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "python",\n python: {\n body: this.fn,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Python("${this.name}", { fn: ${this.fn} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Python {\n return new Python(json?.name, {\n fn: json?.step?.python?.body,\n });\n }\n}\n\nexport class JavaScript extends Integration {\n private fn: (_: State) => JsonValue;\n\n constructor(\n name: string,\n config: {\n fn: (_: State) => JsonValue;\n },\n ) {\n super(name, "javascript");\n\n this.fn = config.fn;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "javascript",\n javascript: {\n body: await toJSBody(this.fn, { block: false, function: true }),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new JavaScript("${this.name}", { fn: ${signature(code(this.fn.toString()), entities)} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): JavaScript {\n const args = [json?.step?.javascript?.body]\n const references = referenced(json?.step?.javascript?.body, entities)\n\n if (references.length > 0) {\n args.unshift(`{ ${references.join(", ")} }`)\n }\n\n return new JavaScript(json?.name, {\n fn: new Function(...args) as (_: State) => JsonValue,\n });\n }\n}\n\n// TODO(Frank): There is way too much in common between Snowflake and PostgreSQL. Need to add a parent class for these.\nexport class Snowflake extends Integration {\n private statement: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n ) {\n super(name, integration);\n\n this.statement = config.statement;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n snowflake: {\n body: await binding(this.statement),\n usePreparedSql: false,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Snowflake("${this.name}", "${this.integration}", { statement: ${typeof this.statement === "function" ? signatureV2(await toJSBody(this.statement), entities) : `"${this.statement}"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Snowflake {\n return new Snowflake(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.snowflake?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class PostgreSQL extends Integration {\n private statement: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n ) {\n super(name, integration);\n\n this.statement = config.statement;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n postgres: {\n body: await binding(this.statement),\n usePreparedSql: false,\n operation: "run_sql",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new PostgreSQL("${this.name}", "${this.integration}", { statement: ${typeof this.statement === "function" ? signatureV2(await toJSBody(this.statement), entities) : `"${this.statement}"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): PostgreSQL {\n return new PostgreSQL(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.postgres?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class RestApi extends Integration {\n private method: string;\n private url: Binding<string>;\n private headers?: { key: Binding<string>; value: Binding<string> }[];\n private params?: { key: Binding<string>; value: Binding<string> }[];\n private body?: Binding<string>;\n\n constructor(\n name: string,\n config: {\n method: string;\n url?: Binding<string>;\n headers?: { key: Binding<string>; value: Binding<string> }[];\n params?: { key: Binding<string>; value: Binding<string> }[];\n body?: Binding<string>;\n },\n ) {\n super(name, "restapi");\n\n this.method = config.method;\n this.url = config.url;\n this.headers = config.headers;\n this.params = config.params;\n this.body = config.body;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "restapi",\n restapi: {\n httpMethod: this.method,\n ...(this.url ? { path: await binding(this.url) } : {}),\n ...(this.headers ? { headers: await Promise.all(this.headers.map(async (header) => ({ key: await binding(header.key), value: await binding(header.value) }))) } : {}),\n ...(this.params ? { params: await Promise.all(this.params.map(async (param) => ({ key: await binding(param.key), value: await binding(param.value) }))) } : {}),\n ...(this.body ? { body: await binding(this.body) } : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [`method: "${this.method}"`];\n\n if (this.url) {\n parts.push(\n `url: ${\n typeof this.url === "function"\n ? signatureV2(await toJSBody(this.url), entities)\n : `"${this.url}"`\n }`,\n );\n }\n\n if (this.headers) {\n const headers = this.headers\n .map(async (h) =>\n `{ key: ${\n typeof h.key === "function"\n ? signatureV2(await toJSBody(h.key), entities)\n : `"${h.key}"`\n }, value: ${\n typeof h.value === "function"\n ? signatureV2(await toJSBody(h.value), entities)\n : `"${h.value}"`\n } }`,\n )\n .join(", ");\n parts.push(`headers: [${headers}]`);\n }\n\n if (this.params) {\n const params = this.params\n .map(async (p) =>\n `{ key: ${\n typeof p.key === "function"\n ? signatureV2(await toJSBody(p.key), entities)\n : `"${p.key}"`\n }, value: ${\n typeof p.value === "function"\n ? signatureV2(await toJSBody(p.value), entities)\n : `"${p.value}"`\n } }`,\n )\n .join(", ");\n parts.push(`params: [${params}]`);\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === "function"\n ? signatureV2(await toJSBody(this.body), entities)\n : JSON.stringify(this.body)\n }`,\n );\n }\n\n return `new RestApi("${this.name}", { ${parts.join(", ")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): RestApi {\n return new RestApi(json?.name, {\n method: json?.step?.restapi?.httpMethod,\n url: fromBinding(json?.step?.restapi?.path, entities),\n headers: json?.step?.restapi?.headers?.map((header: any) => ({ key: fromBinding(header.key, entities), value: fromBinding(header.value, entities) })),\n params: json?.step?.restapi?.params?.map((param: any) => ({ key: fromBinding(param.key, entities), value: fromBinding(param.value, entities) })),\n body: fromBinding(json?.step?.restapi?.body, entities),\n });\n }\n}\n\nexport class Email extends Integration {\n private subject: Binding<string>;\n private from: Binding<string>; // comma separated list\n private to: Binding<string>; // comma separated list\n private cc?: Binding<string>; // comma separated list\n private bcc?: Binding<string>; // comma separated list\n private body: Binding<string>;\n\n constructor(\n name: string,\n config: {\n from: Binding<string>;\n to: Binding<string>;\n subject: Binding<string>;\n cc?: Binding<string>;\n bcc?: Binding<string>;\n body?: Binding<string>;\n },\n ) {\n super(name, "email");\n\n this.from = config.from;\n this.to = config.to;\n this.subject = config.subject;\n this.cc = config.cc;\n this.bcc = config.bcc;\n this.body = config.body;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: "email",\n email: {\n ...(this.from ? { emailFrom: await binding(this.from) } : {}),\n ...(this.to ? { emailTo: await binding(this.to) } : {}),\n ...(this.cc ? { emailCc: await binding(this.cc) } : {}),\n ...(this.bcc ? { emailBcc: await binding(this.bcc) } : {}),\n ...(this.subject ? { emailSubject: await binding(this.subject) } : {}),\n ...(this.body ? { emailBody: await binding(this.body) } : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [];\n\n if (this.from) {\n parts.push(\n `from: ${\n typeof this.from === "function"\n ? signatureV2(code(this.from.toString()), entities)\n : `"${this.from}"`\n }`,\n );\n }\n\n if (this.to) {\n parts.push(\n `to: ${\n typeof this.to === "function"\n ? signatureV2(code(this.to.toString()), entities)\n : `"${this.to}"`\n }`,\n );\n }\n\n if (this.cc) {\n parts.push(\n `cc: ${\n typeof this.cc === "function"\n ? signatureV2(code(this.cc.toString()), entities)\n : `"${this.cc}"`\n }`,\n );\n }\n\n if (this.bcc) {\n parts.push(\n `bcc: ${\n typeof this.bcc === "function"\n ? signatureV2(code(this.bcc.toString()), entities)\n : `"${this.bcc}"`\n }`,\n );\n }\n\n if (this.subject) {\n parts.push(\n `subject: ${\n typeof this.subject === "function"\n ? signatureV2(code(this.subject.toString()), entities)\n : `"${this.subject}"`\n }`,\n );\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === "function"\n ? signatureV2(code(this.body.toString()), entities)\n : `"${this.body}"`\n }`,\n );\n }\n\n return `new Email("${this.name}", { ${parts.join(", ")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Email {\n return new Email(json?.name, {\n from: fromBinding(json?.step?.email?.emailFrom, entities),\n to: fromBinding(json?.step?.email?.emailTo, entities),\n subject: fromBinding(json?.step?.email?.emailSubject, entities),\n body: fromBinding(json?.step?.email?.emailBody, entities),\n cc: json?.step?.email?.emailCc ? fromBinding(json?.step?.email?.emailCc, entities) : undefined,\n bcc: json?.step?.email?.emailBcc ? fromBinding(json?.step?.email?.emailBcc, entities) : undefined,\n });\n }\n}\n\nexport class Databricks extends Integration {\n private statement: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n ) {\n super(name, integration);\n\n this.statement = config.statement;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n databricks: {\n runSql: {\n sqlBody: await binding(this.statement),\n useParameterized: false,\n },\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Databricks("${this.name}", "${this.integration}", { statement: ${typeof this.statement === "function" ? signatureV2(await toJSBody(this.statement), entities) : `"${this.statement}"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Databricks {\n return new Databricks(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.databricks?.runSql?.sqlBody as string,\n entities,\n ),\n });\n }\n}\n\nexport type Condition = {\n when: Binding<boolean>;\n then: Block[];\n};\n\nasync function conditionToSDK(condition: Condition, entities: string[]): Promise<string> {\n return `{ when: ${typeof condition.when === "function" ? signatureV2(await toJSBody(condition.when), entities) : condition.when}, then: [${(await Promise.all(condition.then.map(async (block) => await block.toSDK(entities)))).join(",")}] }`\n}\n\nexport type Conditions = {\n if: Condition;\n elif?: Condition[];\n else?: Block[];\n};\n\nexport class Conditional extends Block {\n public conditions: Conditions;\n\n constructor(name: string, config: Conditions) {\n super(name);\n\n this.conditions = config;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n conditional: {\n if: {\n condition: await toJS<boolean>(this.conditions.if.when),\n blocks: await Promise.all(this.conditions.if.then.map(async (block) => await block.toJSON())),\n },\n ...await (async () =>\n this.conditions.elif\n ? {\n elseIf: await Promise.all(this.conditions.elif.map(async (condition) => ({\n condition: await toJS<boolean>(condition.when),\n blocks: await Promise.all(condition.then.map(async (block) => await block.toJSON())),\n }))),\n }\n : { elseIf: [] })(),\n else: this.conditions.else ? {\n blocks: await Promise.all(this.conditions.else.map(async (block) => await block.toJSON()))\n } : undefined,\n },\n };\n }\n\n public static fromJSON(json: any, entities: string[]): Conditional {\n return new Conditional(json?.name, {\n if: {\n when: fromJS<boolean>(json?.conditional?.if?.condition, entities),\n then: json?.conditional?.if?.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n },\n elif: json?.conditional?.elseIf ? json?.conditional?.elseIf?.map((condition: any) => ({\n when: fromJS<boolean>(condition.condition, entities),\n then: condition.blocks.map((block: any) => Block.fromJSON(block, entities)),\n })) : [],\n else: json?.conditional?.else ? json?.conditional?.else?.blocks?.map((block: any) => Block.fromJSON(block, entities)) : [],\n });\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Conditional("${this.name}", { if: ${await conditionToSDK(this.conditions.if, entities)}, elif: [${this.conditions.elif ? (await Promise.all(this.conditions.elif?.map(async (condition) => await conditionToSDK(condition, entities)))).join(",") : \'\'}], else: ${this.conditions.else ? (await Promise.all(this.conditions.else?.map(async (block) => await block.toSDK(entities)))).join(",") : "undefined"} })`;\n }\n}\n\nexport class Parallel extends Block {\n private over: Binding<JsonValue[]>;\n private blocks: Block[];\n private variables: { item: string };\n\n constructor(\n name: string,\n config: {\n over: Binding<JsonValue[]>;\n variables: { item: string };\n blocks: Block[];\n },\n ) {\n super(name);\n\n this.over = config.over;\n this.blocks = config.blocks;\n this.variables = config.variables;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n parallel: {\n dynamic: {\n blocks: await Promise.all(this.blocks?.map(async (block) => await block.toJSON())),\n paths: await toJS<JsonValue[]>(this.over),\n variables: this.variables,\n },\n wait: "WAIT_ALL",\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Parallel("${this.name}", { over: ${typeof this.over === "function" ? signatureV2(await toJSBody(this.over), entities) : this.over}, variables: ${this.variables}, blocks: ${await Promise.all(this.blocks.map(async (block) => await block.toSDK(entities)).join(","))} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Parallel {\n return new Parallel(json?.name, {\n over: fromJS<JsonValue[]>(json?.parallel?.dynamic?.paths, entities),\n variables: {\n item: json?.parallel?.dynamic?.variables?.item,\n },\n blocks: json?.parallel?.dynamic?.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n });\n }\n}\n\nexport class Loop extends Block {\n private over: Binding<JsonValue[]>; // NOTE(Frank): Only for each loops are supported at the moment.\n private blocks: Block[];\n private variables: { item: string; index: string };\n\n constructor(\n name: string,\n config: {\n over: Binding<JsonValue[]>;\n variables: { item: string; index: string };\n blocks: Block[];\n },\n ) {\n super(name);\n\n this.over = config.over;\n this.variables = config.variables;\n this.blocks = config.blocks;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n loop: {\n range: await toJS<JsonValue[]>(this.over),\n type: "TYPE_FOREACH",\n variables: this.variables,\n blocks: await Promise.all(this.blocks.map(async (block) => await block.toJSON())),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Loop("${this.name}", { over: ${typeof this.over === "function" ? signatureV2(await toJSBody(this.over), entities) : this.over}, variables: ${this.variables}, blocks: ${await Promise.all(this.blocks.map(async (block) => await block.toSDK(entities)).join(","))} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Loop {\n return new Loop(json?.name, {\n over: fromJS<JsonValue[]>(json?.loop?.range, entities),\n variables: {\n item: json?.loop?.variables?.item,\n index: json?.loop?.variables?.index,\n },\n blocks: json?.loop?.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n });\n }\n}\n\nexport class Variables extends Block {\n private variables: { key: string, value: Binding<JsonValue> }[];\n\n constructor(\n name: string,\n variables: { key: string, value: Binding<JsonValue> }[],\n ) {\n super(name);\n\n this.variables = variables;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n variables: {\n items: await Promise.all(this.variables.map(async (variable) => {\n return {\n key: variable.key,\n value: await toJS<JsonValue>(variable.value),\n type: "TYPE_SIMPLE",\n mode: "MODE_READWRITE",\n };\n }))\n },\n };\n }\n \n public async toSDK(entities: string[]): Promise<string> {\n return `new Variables("${this.name}", [${this.variables?.map((variable) => `{ key: "${variable.key}", value: ${typeof variable.value === "function" ? signature(code(variable.value.toString(), { iife: true }), entities) : variable.value} }`).join(",")}])`;\n }\n\n public static fromJSON(json: any, entities: string[]): Variables {\n return new Variables(json?.name, json?.variables?.items?.map((variable: any) => ({\n key: variable.key,\n value: fromBinding(variable.value, entities),\n })));\n }\n}\n\nexport class TryCatch extends Block {\n private try: Block[];\n private catch: Block[];\n private finally?: Block[];\n private variables: { error: string };\n\n constructor(\n name: string,\n config: {\n try: Block[];\n catch: Block[];\n finally?: Block[];\n variables: { error: string };\n },\n ) {\n super(name);\n\n this.try = config.try;\n this.catch = config.catch;\n this.finally = config.finally;\n this.variables = config.variables;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n tryCatch: {\n try: { blocks: await Promise.all(this.try.map(async (block) => await block.toJSON())) },\n catch: { blocks: await Promise.all(this.catch.map(async (block) => await block.toJSON())) },\n finally: { blocks: this.finally ? await Promise.all(this.finally.map(async (block) => await block.toJSON())) : [] },\n variables: this.variables,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new TryCatch("${this.name}", { try: ${await Promise.all(this.try.map(async (block) => await block.toSDK(entities)).join(","))}, catch: ${await Promise.all(this.catch.map(async (block) => await block.toSDK(entities)).join(","))}, finally: ${this.finally?.map(async (block) => await block.toSDK(entities)).join(", ")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): TryCatch {\n return new TryCatch(json?.name, {\n try: json?.tryCatch?.try.blocks.map((block: any) => Block.fromJSON(block, entities)),\n catch: json?.tryCatch?.catch.blocks.map((block: any) => Block.fromJSON(block, entities)),\n finally: json?.tryCatch?.finally?.blocks.map((block: any) => Block.fromJSON(block, entities)),\n variables: {\n error: json?.tryCatch?.variables?.error,\n },\n });\n }\n}\n\nexport class Throw extends Block {\n private error: Binding<JsonValue>;\n\n constructor(\n name: string,\n config: {\n error: Binding<JsonValue>;\n },\n ) {\n super(name);\n\n this.error = config.error;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n throw: {\n error: await toJS<JsonValue>(this.error),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Throw("${this.name}", { error: ${typeof this.error === "function" ? signature(code(this.error.toString()), entities) : JSON.stringify(this.error)} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Throw {\n return new Throw(json?.name, {\n error: fromJS(json?.throw?.error, entities),\n });\n }\n}\n\nexport class Return extends Block {\n private data: Binding<JsonValue>;\n\n constructor(\n name: string,\n config: {\n data: Binding<JsonValue>;\n },\n ) {\n super(name);\n\n this.data = config.data;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n return: {\n data: await toJS<JsonValue>(this.data),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Return("${this.name}", { data: ${typeof this.data === "function" ? signature(code(this.data.toString()), entities) : JSON.stringify(this.data)} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Return {\n return new Return(json?.name, {\n data: fromJS(json?.return?.data, entities),\n });\n }\n}\n\nexport class Api {\n private blocks: Block[];\n private name: string;\n\n constructor(name: string, blocks: Block[]) {\n this.name = name;\n this.blocks = blocks;\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const imports =\n "import { Api, JavaScript, Python, PostgreSQL, Snowflake, Databricks, Conditional, Parallel, Loop, TryCatch, Variables, Throw, Return } from \'@superblocksteam/library\'";\n return `${imports}\\n\\nexport default new Api("${this.name}", [${(await Promise.all(this.blocks.map(async (block) => await block.toSDK(entities)))).join(",")}])`;\n }\n\n public static fromJSON(json: any, entities: string[]): Api {\n // NOTE(Frank): Would probs unmarshal this into the protobuf types and then do the conversion.\n return new Api(\n json?.metadata?.name as string,\n (json.blocks as any[]).map((block) => Block.fromJSON(block, entities)),\n );\n }\n\n public async toJSON(): Promise<JsonValue> {\n const api: {\n metadata: {\n name: string;\n timestamps: {\n updated: string;\n };\n };\n trigger: {\n application: {};\n };\n blocks: JsonValue[];\n } = {\n metadata: {\n name: this.name,\n timestamps: {\n updated: new Date().toISOString(),\n },\n },\n trigger: {\n application: {},\n },\n blocks: [],\n };\n\n api.blocks = await Promise.all(this.blocks.map(async (block) => await block.toJSON()));\n\n return api;\n }\n}\n\nfunction referenced(data: string, entities: string[]): string[] {\n return entities.reduce((acc: string[], entity: string) => {\n if (data.includes(entity)) {\n acc.push(entity);\n }\n return acc;\n }, []);\n}\n\nfunction signature(data: string, entities: string[]): string {\n return `({ ${referenced(data, entities).join(", ")} }) => {${data}}`;\n}\n\nfunction signatureV2(data: string, entities: string[]): string {\n return `({ ${referenced(data, entities).join(", ")} }) => ${data}`;\n}\n\n/**\n * Converts a string binding, which comprise 99% of dynamic integration fields, into a function returning an interpolated string.\n *\n * fromBinding(`https://${ \'goo\' + \'gle\' }.com/${ Dropdown1.value }`, [\'Dropdown1\']) -> ({ Dropdown1 }) => `https://${\'goo\' + \'gle\'}.com/${Dropdown1.value}`\n *\n * @param value - The value to convert.\n * @param entities - The master list of possible entities that could be referenced in the binding.\n *\n * @returns The converted value.\n */\nexport function fromBinding(value: string, entities: string[]): Binding<string> {\n if (!value) {\n return "";\n }\n\n if (!value.startsWith("`") || !value.endsWith("`")) {\n return value;\n }\n\n const args: string[] = [`return ${value}`]\n const references: string[] = referenced(value, entities);\n\n if (references.length === 0) {\n return eval(value) as string;\n }\n\n // only add the arguments if we have references\n args.unshift(`{ ${references} }`);\n\n return new Function(...args) as (_: State) => string;\n}\n\nasync function beautifyAndOptionallyCondense<T extends JsonValue>(value: ((state: State) => T), node: Node, options: { condense?: boolean, block?: boolean } = { condense: true, block: true }) {\n let start: number = node.start;\n let end: number = node.end;\n\n if (!options.block) {\n start += 1;\n end -= 1;\n }\n \n const beautified = await beautify(value.toString().slice(start, end))\n\n if (options.condense) {\n return beautified.replace(/\\s*\\n\\s*/g, \' \').replace(/\\s+/g, \' \').trim();\n }\n\n return beautified\n}\n\nfunction createAst(value: string): Program {\n return parse(value, {\n ecmaVersion: "latest",\n sourceType: "script",\n preserveParens: false,\n });\n}\n\nasync function toJSBody<T extends JsonValue>(value: ((state: State) => T), options: { block?: boolean, condense?: boolean, function?: boolean } = { block: true, condense: true, function: false }): Promise<string> {\n if (typeof value !== "function") {\n return `\\`${JSON.stringify(value)}\\``\n }\n\n // parse the code\n const ast = createAst(value.toString());\n const program = ast.body[0];\n\n switch (program.type) {\n case "ExpressionStatement":\n const body = ((program as ExpressionStatement).expression as FunctionExpression).body;\n\n if (body.type === \'BlockStatement\') {\n return await beautifyAndOptionallyCondense(value, body, options)\n }\n\n return `${options.function ? "return " : ""}${value.toString().slice(body.start, body.end)}`\n case "FunctionDeclaration":\n let contents = value.toString().slice(program.body.start, program.body.end)\n\n if (program.body.type !== \'BlockStatement\') {\n return contents\n }\n \n if (!options.function && program.body.body.length === 1 && program.body.body[0].type === \'ReturnStatement\') {\n return value.toString().slice(program.body.body[0].argument.start, program.body.body[0].argument.end)\n }\n\n return await beautifyAndOptionallyCondense(value, program.body, options)\n\n default:\n throw new Error("you found a case we haven\'t handled yet")\n }\n}\n\nexport async function toJS<T extends JsonValue>(value: Binding<T>): Promise<string> {\n return `(() => ${typeof value === "function" ? await toJSBody(value) : JSON.stringify(value)})()`\n}\n\nexport function fromJS<T extends JsonValue>(\n value: string,\n entities: string[] = [],\n): Binding<T> {\n // determine if there are entities referenced in the value\n const refs = referenced(value, entities).join(", ")\n\n // remove any surrounding whitespace\n value = value.trim()\n\n let unaryOps: string[] = [];\n let call = (createAst(value).body[0] as ExpressionStatement).expression;\n\n while (call?.type === \'UnaryExpression\') {\n unaryOps.push((call as UnaryExpression).operator);\n call = (call as unknown as UnaryExpression).argument as CallExpression;\n }\n \n const fn = (call as CallExpression).callee;\n let body = value;\n let prefix = "return ";\n\n // handle iife\n if (fn?.type === "ArrowFunctionExpression") {\n // i\'m not happy with this but I don\'t see another immediate way to handle this.\n // this will result in a correct result but one that isn\'t idemopotent.\n if (unaryOps.length > 0) {\n return new Function(`{ ${refs} }`, `${prefix}${body}`) as (_: State) => T;\n }\n\n\n body = value.slice(fn.body.start, fn.body.end)\n\n if (fn.body.type === \'BlockStatement\') {\n // drop the opening "{" and closing "}"\n body = body.slice(1, -1)\n prefix = ""\n } \n } else if (refs.length === 0) {\n // we\'re not an iife nor do we have references.\n // we might have to revisit this implementation since this technically reduces to a static value down to it\'s most minimal form.\n return eval(value) as T\n }\n\n // we\'re either an iife or a static value with refs.\n return new Function(`{ ${refs} }`, `${prefix}${body}`) as (_: State) => T;\n}\n\nexport async function beautify(code: string): Promise<string> {\n const eslint = new ESLint({\n fix: true,\n overrideConfigFile: true,\n baseConfig: {\n languageOptions: {\n parser: typescript_eslint_parser,\n parserOptions: {\n ecmaVersion: 2020,\n sourceType: "module",\n },\n },\n rules: {\n "arrow-body-style": "error",\n },\n },\n });\n\n code = (await eslint.lintText(code))[0]?.output || code;\n\n return await format(code, {\n parser: "typescript",\n tabWidth: 2,\n // singleQuote: true,\n trailingComma: "none",\n semi: true,\n bracketSpacing: true,\n arrowParens: "always",\n bracketSameLine: false,\n embeddedLanguageFormatting: "auto",\n quoteProps: "as-needed",\n insertPragma: false,\n requirePragma: false,\n useTabs: false,\n endOfLine: "auto",\n arrowFunctionParentheses: "always",\n // plugins: ["prettier-plugin-organize-imports"],\n });\n}\n',
|
|
315071
315071
|
"src/to-sdk/__template__.ts": 'import { Api } from "@superblocksteam/library";\n\nconst json = {};\n\nconst entities = [];\n\nconst api = Api.fromJSON(json, entities);\n\nexport default {\n toSDK: async () => await api.toSDK(entities),\n};\n',
|
|
315072
315072
|
"tsconfig.json": '{\n "compilerOptions": {\n "target": "ES2020",\n "module": "ESNext",\n "moduleResolution": "bundler",\n "baseUrl": ".",\n "outDir": "dist",\n "rootDir": "src",\n "esModuleInterop": true,\n "resolveJsonModule": true,\n "skipLibCheck": true,\n "types": [\n "node"\n ],\n "paths": {\n "@superblocksteam/library": [\n "src/superblocks-library-shim"\n ]\n }\n },\n "include": [\n "src"\n ],\n "exclude": [\n "node_modules",\n "dist",\n ]\n}'
|
|
315073
315073
|
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superblocksteam/cli",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.45",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Official Superblocks CLI",
|
|
6
6
|
"homepage": "https://www.superblocks.com",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@eslint/js": "^9.16.0",
|
|
44
44
|
"@oclif/test": "^4.1.11",
|
|
45
|
-
"@superblocksteam/sdk": "2.0.0-next.
|
|
45
|
+
"@superblocksteam/sdk": "2.0.0-next.45",
|
|
46
46
|
"@superblocksteam/shared": "0.9137.0",
|
|
47
|
-
"@superblocksteam/util": "2.0.0-next.
|
|
47
|
+
"@superblocksteam/util": "2.0.0-next.45",
|
|
48
48
|
"@types/babel__core": "^7.20.0",
|
|
49
49
|
"@types/chai": "^4",
|
|
50
50
|
"@types/fs-extra": "^11.0.1",
|