@superblocksteam/ai-service-templates 2.0.68-next.4 → 2.0.69-next.0
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/package.json +2 -2
- package/templates.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superblocksteam/ai-service-templates",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.69-next.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./reify-template": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/node": "^20",
|
|
22
|
-
"vite": "6.
|
|
22
|
+
"vite": "6.4.1",
|
|
23
23
|
"vitest": "^3.2.0"
|
|
24
24
|
},
|
|
25
25
|
"publishConfig": {
|
package/templates.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
export const templates = {
|
|
3
3
|
"api-builder-to-yaml": {
|
|
4
4
|
"bootstrap.mjs": "import { register } from \"node:module\";\nimport { pathToFileURL } from \"node:url\";\n\nregister(\"./shim-loader.mjs\", pathToFileURL(\"./\"));\n",
|
|
5
|
-
"package.json": "{\n \"type\": \"module\",\n \"scripts\": {\n \"build\": \"tsc\",\n \"test\": \"pnpm build && vitest run src/superblocks-library-shim/index.test.ts\"\n },\n \"dependencies\": {\n \"@types/node\": \"^20\",\n \"@typescript-eslint/parser\": \"^8.34.0\",\n \"acorn\": \"^8.14.0\",\n \"eslint\": \"^9.39.1\",\n \"prettier\": \"^3.6.2\",\n \"typescript\": \"^5.9.3\",\n \"yaml\": \"^2.7.1\"\n },\n \"devDependencies\": {\n \"vite\": \"6.
|
|
5
|
+
"package.json": "{\n \"type\": \"module\",\n \"scripts\": {\n \"build\": \"tsc\",\n \"test\": \"pnpm build && vitest run src/superblocks-library-shim/index.test.ts\"\n },\n \"dependencies\": {\n \"@types/node\": \"^20\",\n \"@typescript-eslint/parser\": \"^8.34.0\",\n \"acorn\": \"^8.14.0\",\n \"eslint\": \"^9.39.1\",\n \"prettier\": \"^3.6.2\",\n \"typescript\": \"^5.9.3\",\n \"yaml\": \"^2.7.1\"\n },\n \"devDependencies\": {\n \"vite\": \"6.4.1\",\n \"vitest\": \"^3.2.0\"\n }\n}\n",
|
|
6
6
|
"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",
|
|
7
7
|
"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 specified directory,\n// imports each module, converts its JSON representation to SDK,\n// and returns a map with filenames as keys and SDK content as values.\nexport async function processSdkFiles(\n apisDir: string,\n): Promise<Record<string, string>> {\n const files = fs.readdirSync(apisDir);\n const jsFiles = files.filter(\n (file) => file.endsWith(\".js\") && file !== \"__template__.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.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 return results;\n}\n\nasync function main() {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n const apisDir = path.resolve(__dirname, \"./to-sdk\");\n\n const results = await processSdkFiles(apisDir);\n console.log(JSON.stringify(results, null, 2));\n}\n\nmain().catch((error) => {\n console.error(\"Error:\", error);\n process.exit(1);\n});\n",
|
|
8
8
|
"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 specified directory,\n// imports each module, converts its JSON representation to YAML,\n// and returns a map with filenames as keys and YAML content as values.\n\nexport async function processYamlFiles(apisDir: string): Promise<Record<string, string>> {\n const files = fs.readdirSync(apisDir);\n const jsFiles = files.filter((file) => file.endsWith(\".js\"));\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 const yamlContent = yaml.stringify(jsonData);\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 return results;\n}\n\nasync function main() {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n const apisDir = path.resolve(__dirname, \"./to-yaml\");\n \n const results = await processYamlFiles(apisDir);\n console.log(JSON.stringify(results, null, 2));\n}\n\nmain().catch((error) => {\n console.error(\"Error:\", error);\n process.exit(1);\n});\n",
|
|
9
9
|
"src/superblocks-library-shim/index.d.ts": "export type JsonValue = any;\n\nexport type State = { [key: string]: JsonValue };\n\nexport type Binding<T> = T | ((state: State) => T);\n\nexport declare abstract class Block {\n protected name: string;\n\n constructor(name: string);\n}\n\nexport declare abstract class Integration extends Block {\n protected integration: string;\n\n constructor(name: string, integration: string);\n}\n\nexport declare class Python extends Integration {\n constructor(\n name: string,\n config: {\n fn: string;\n },\n );\n}\n\nexport declare class JavaScript extends Integration {\n constructor(\n name: string,\n config: {\n fn: (_: State) => JsonValue;\n },\n );\n}\n\nexport declare class Athena extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n sqlBody: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Athena;\n}\n\nexport declare class BigQuery extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n sqlBody: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): BigQuery;\n}\n\nexport type DynamoDbAction =\n | \"getItem\"\n | \"updateItem\"\n | \"putItem\"\n | \"batchWriteItem\"\n | \"deleteItem\"\n | \"query\"\n | \"scan\"\n | \"executeStatement\"\n | \"executeTransaction\"\n | \"listTagsOfResource\"\n | \"tagResource\"\n | \"listTables\"\n | \"describeTable\"\n | \"createTable\"\n | \"updateTable\"\n | \"deleteTable\";\n\nexport declare class DynamoDb extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n action: DynamoDbAction;\n paramsJson: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): DynamoDb;\n}\n\nexport declare class Snowflake extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Snowflake;\n}\n\nexport declare class PostgreSQL extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): PostgreSQL;\n}\n\nexport declare class MicrosoftSql extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): MicrosoftSql;\n}\n\nexport declare class MySQL extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): MySQL;\n}\n\nexport declare class RestApi extends Integration {\n constructor(\n name: string,\n integration?: 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 openapi?: {\n path: string;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n protected constructorParametersString(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): RestApi;\n}\n\nexport type SalesforceAction =\n | { action: \"SOQL_ACTION_SOQL\"; soqlBody: Binding<string> }\n | {\n action: \"CRUD_ACTION_READ\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_CREATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_UPDATE\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_DELETE\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"BULK_ACTION_CREATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"BULK_ACTION_UPDATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n };\n\nexport declare class Salesforce extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n action: SalesforceAction;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Salesforce;\n}\n\nexport declare class OpenApi extends RestApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n );\n\n public static configFromJSON(\n json: any,\n entities: string[],\n ): {\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 public static openapiFromJSON(json: any):\n | {\n path: string;\n }\n | undefined;\n}\n\nexport declare class Jira extends OpenApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n );\n\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Jira;\n}\n\n// OpenAPI Integration Classes\nexport declare const Airtable: typeof OpenApi;\nexport declare const Anthropic: typeof OpenApi;\nexport declare const Asana: typeof OpenApi;\nexport declare const Bitbucket: typeof OpenApi;\nexport declare const Box: typeof OpenApi;\nexport declare const CircleCI: typeof OpenApi;\nexport declare const Cohere: typeof OpenApi;\nexport declare const Datadog: typeof OpenApi;\nexport declare const Dropbox: typeof OpenApi;\nexport declare const Elasticsearch: typeof OpenApi;\nexport declare const Fireworks: typeof OpenApi;\nexport declare const Front: typeof OpenApi;\nexport declare const Gemini: typeof OpenApi;\nexport declare const GitHub: typeof OpenApi;\nexport declare const GoogleAnalytics: typeof OpenApi;\nexport declare const GoogleDrive: typeof OpenApi;\nexport declare const Groq: typeof OpenApi;\nexport declare const HubSpot: typeof OpenApi;\nexport declare const Intercom: typeof OpenApi;\nexport declare const LaunchDarkly: typeof OpenApi;\nexport declare const Mistral: typeof OpenApi;\nexport declare const Notion: typeof OpenApi;\nexport declare const OpenAI: typeof OpenApi;\nexport declare const PagerDuty: typeof OpenApi;\nexport declare const Perplexity: typeof OpenApi;\nexport declare const Segment: typeof OpenApi;\nexport declare const SendGrid: typeof OpenApi;\nexport declare const Slack: typeof OpenApi;\nexport declare const StabilityAI: typeof OpenApi;\nexport declare const Stripe: typeof OpenApi;\nexport declare const Twilio: typeof OpenApi;\nexport declare const Zendesk: typeof OpenApi;\nexport declare const Zoom: typeof OpenApi;\n\nexport declare class Email extends Integration {\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\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Email;\n}\n\nexport declare class Databricks extends Integration {\n constructor(\n name: string,\n integration: string,\n config: {\n statement: Binding<string>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Databricks;\n}\n\nexport type Condition = {\n when: Binding<boolean>;\n then: Block[];\n};\n\nexport type Conditions = {\n if: Condition;\n elif?: Condition[];\n else?: Block[];\n};\n\nexport declare class Conditional extends Block {\n public conditions: Conditions;\n\n constructor(name: string, config: Conditions);\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Conditional;\n}\n\nexport declare class Parallel extends Block {\n constructor(\n name: string,\n config: {\n over: Binding<JsonValue[]>;\n variables: { item: string };\n blocks: Block[];\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Parallel;\n}\n\nexport declare class Loop extends Block {\n constructor(\n name: string,\n config: {\n over: Binding<JsonValue[]>;\n variables: { item: string; index: string };\n blocks: Block[];\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Loop;\n}\n\nexport declare class Variables extends Block {\n constructor(\n name: string,\n variables: { key: string; value: Binding<JsonValue> }[],\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Variables;\n}\n\nexport declare class TryCatch extends Block {\n constructor(\n name: string,\n config: {\n try: Block[];\n catch: Block[];\n finally?: Block[];\n variables: { error: string };\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): TryCatch;\n}\n\nexport declare class Throw extends Block {\n constructor(\n name: string,\n config: {\n error: Binding<JsonValue>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Throw;\n}\n\nexport declare class Return extends Block {\n constructor(\n name: string,\n config: {\n data: Binding<JsonValue>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Return;\n}\n\nexport declare class Break extends Block {\n constructor(\n name: string,\n config: {\n condition: Binding<JsonValue>;\n },\n );\n\n public toJSON(): Promise<JsonValue>;\n public toSDK(entities: string[]): Promise<string>;\n public static fromJSON(json: any, entities: string[]): Break;\n}\n\nexport type Authorization =\n | {\n type: \"AUTHORIZATION_TYPE_APP_USERS\";\n }\n | {\n type: \"AUTHORIZATION_TYPE_JS_EXPRESSION\";\n expression: Binding<boolean>;\n };\n\nexport declare class Api {\n constructor(name: string, blocks?: Block[], authorization?: Authorization);\n\n public toSDK(entities: string[]): Promise<string>;\n public toJSON(): Promise<JsonValue>;\n public static fromJSON(json: any, entities: string[]): Api;\n}\n",
|
|
10
|
-
"src/superblocks-library-shim/index.ts": "/* eslint-disable */\nimport typescript_eslint_parser from \"@typescript-eslint/parser\";\nimport {\n CallExpression,\n ExpressionStatement,\n FunctionExpression,\n Literal,\n Node,\n parse,\n Program,\n UnaryExpression,\n} from \"acorn\";\nimport { ESLint } from \"eslint\";\nimport { format } from \"prettier\";\n\nexport const Global: Record<string, any> = {};\n\nexport type JsonValue = any;\n\n// This is the ideal type, but it's too restrictive when we use it for generating code,\n// because the builder side is doing access like `someVar.value`, but JsonValue is not\n// strict enough to avoid type errors, so you see a lot of:\n// error TS2551: Property 'value' does not exist on type 'JsonValue'. Did you mean 'valueOf'?\n// Property 'value' does not exist on type 'string'.\n//\n// export 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 function trimSqlSpaces(content: string): string {\n if (!content) return \"\";\n return content\n .replace(/[ \\t]+/g, \" \") // Replace multiple spaces/tabs with single space\n .replace(/[ \\t]*\\n[ \\t]*/g, \"\\n\") // Remove spaces around line breaks\n .replace(/^\\s+|\\s+$/g, \"\") // Trim leading and trailing whitespace\n .trim();\n}\nasync function binding(binding: Binding<string>): Promise<string> {\n if (typeof binding === \"function\") {\n const { body, node } = await toJS(binding);\n\n if (\n node?.type === \"Literal\" &&\n typeof (node as Literal).value === \"string\"\n ) {\n return `\\`${(node as Literal).value}\\``;\n }\n\n if (node?.type === \"TemplateLiteral\") {\n return body;\n }\n\n return `\\`\\$\\{${body}\\}\\``;\n }\n\n return `\\`${binding}\\``;\n}\n\nasync function formatGraphQLQuery(query: string): Promise<string> {\n if (!query || typeof query !== \"string\") {\n return query;\n }\n\n try {\n const formatted = await format(query, {\n parser: \"graphql\",\n printWidth: 80,\n tabWidth: 2,\n useTabs: false,\n });\n return formatted.trim();\n } catch (error) {\n // if prettier fails to format, return the original query\n return query;\n }\n}\n\nexport async function bindingSql(binding: Binding<string>): Promise<string> {\n if (typeof binding === \"function\") {\n const ret = await toJSBody(binding as (state: State) => string, {\n condense: false,\n });\n const { body, iife, node } = ret;\n\n if (\n node?.type === \"Literal\" &&\n typeof (node as Literal).value === \"string\"\n ) {\n const escapedValue = (node as Literal).value as string;\n // Escape backticks in the SQL string\n const escaped = escapedValue.replace(/`/g, \"\\\\`\");\n return `\\`${trimSqlSpaces(escaped)}\\``;\n }\n\n if (node?.type === \"TemplateLiteral\") {\n const trimmedBody = trimSqlSpaces(body);\n return iife ? `(() => ${trimmedBody})()` : trimmedBody;\n }\n\n let finalBody = body;\n\n if (iife) {\n finalBody = `(() => ${body})()`;\n }\n\n finalBody = trimSqlSpaces(finalBody);\n\n // Special handling for template literals - trim content within backticks\n finalBody = finalBody.replace(/`([^`]*)`/g, (_match, content) => {\n const trimmedContent = trimSqlSpaces(content);\n return `\\`${trimmedContent}\\``;\n });\n\n return `\\`\\$\\{${finalBody}\\}\\``;\n }\n\n const trimmedBinding = trimSqlSpaces(binding);\n // Escape backticks in the SQL string\n const escaped = trimmedBinding.replace(/`/g, \"\\\\`\");\n return `\\`${escaped}\\``;\n}\n\nexport async function bindingGraphQL(\n binding: Binding<string>,\n): Promise<string> {\n if (typeof binding === \"function\") {\n const ret = await toJSBody(binding as (state: State) => string, {\n condense: false,\n });\n const { body, iife, node } = ret;\n\n if (\n node?.type === \"Literal\" &&\n typeof (node as Literal).value === \"string\"\n ) {\n const formatted = await formatGraphQLQuery(\n (node as Literal).value as string,\n );\n return `\\`${formatted}\\``;\n }\n\n if (node?.type === \"TemplateLiteral\") {\n return iife ? `(() => ${body})()` : body;\n }\n\n let finalBody = body;\n\n if (iife) {\n finalBody = `(() => ${body})()`;\n }\n\n return `\\`\\$\\{${finalBody}\\}\\``;\n }\n\n const formatted = await formatGraphQLQuery(binding);\n return `\\`${formatted}\\``;\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 if (\"break\" in json) {\n return Break.fromJSON(json, entities);\n }\n\n throw new Error(\"Unknown 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 private static integrationRegistry: Record<string, any> = {};\n\n public static registerIntegration(key: string, integrationClass: any) {\n this.integrationRegistry[key] = integrationClass;\n }\n\n public static fromJSON(json: any, entities: string[]): Block {\n if (\"restapi\" in json?.step || \"restapiintegration\" in json?.step) {\n return RestApi.fromJSON(json, entities);\n }\n\n for (const [key, IntegrationClass] of Object.entries(\n this.integrationRegistry,\n )) {\n if (key in json?.step) {\n return IntegrationClass.fromJSON(json, entities);\n }\n }\n\n console.error(\"Unknown integration\", json?.step);\n throw new Error(\"Unknown integration\");\n }\n}\n\nexport class Python extends Integration {\n private fn: string;\n\n constructor(\n name: string,\n config: {\n fn: string;\n },\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 .body,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new JavaScript(\"${this.name}\", { fn: ${signatureV2((await toJSBody(this.fn)).body, 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\nexport class Athena extends Integration {\n private sqlBody: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n sqlBody: Binding<string>;\n },\n ) {\n super(name, integration);\n this.sqlBody = config.sqlBody;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n athena: {\n runSql: {\n sqlBody: await bindingSql(this.sqlBody),\n useParameterized: true,\n },\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Athena(\"${this.name}\", \"${this.integration}\", { sqlBody: \"${this.sqlBody}\" })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Athena {\n return new Athena(json?.name, json?.step?.integration, {\n sqlBody: fromBinding(json?.step?.athena?.runSql?.sqlBody, entities),\n });\n }\n}\n\nexport class BigQuery extends Integration {\n private sqlBody: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n sqlBody: Binding<string>;\n },\n ) {\n super(name, integration);\n this.sqlBody = config.sqlBody;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n bigquery: {\n body: await bindingSql(this.sqlBody),\n usePreparedSql: true,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new BigQuery(\"${this.name}\", \"${this.integration}\", { sqlBody: \"${this.sqlBody}\" })`;\n }\n\n public static fromJSON(json: any, entities: string[]): BigQuery {\n return new BigQuery(json?.name, json?.step?.integration, {\n sqlBody: fromBinding(json?.step?.bigquery?.body, entities),\n });\n }\n}\n\ntype DynamoDbAction =\n | \"getItem\"\n | \"updateItem\"\n | \"putItem\"\n | \"batchWriteItem\"\n | \"deleteItem\"\n | \"query\"\n | \"scan\"\n | \"executeStatement\"\n | \"executeTransaction\"\n | \"listTagsOfResource\"\n | \"tagResource\"\n | \"listTables\"\n | \"describeTable\"\n | \"createTable\"\n | \"updateTable\"\n | \"deleteTable\";\n\nexport class DynamoDb extends Integration {\n private action: DynamoDbAction;\n private paramsJson: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n action: DynamoDbAction;\n paramsJson: Binding<string>;\n },\n ) {\n super(name, integration);\n this.action = config.action;\n this.paramsJson = config.paramsJson;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n dynamodb: {\n action: this.action,\n body: await binding(this.paramsJson),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new DynamoDb(\"${this.name}\", \"${this.integration}\", { action: \"${this.action}\", paramsJson: \"${this.paramsJson}\" })`;\n }\n\n public static fromJSON(json: any, entities: string[]): DynamoDb {\n return new DynamoDb(json?.name, json?.step?.integration, {\n action: json?.step?.dynamodb?.action,\n paramsJson: fromBinding(json?.step?.dynamodb?.body, entities),\n });\n }\n}\n\ntype S3Action =\n | \"LIST_OBJECTS\"\n | \"LIST_BUCKET_OBJECTS\"\n | \"GET_OBJECT\"\n | \"DELETE_OBJECT\"\n | \"UPLOAD_OBJECT\"\n | \"LIST_BUCKETS\"\n | \"CREATE_BUCKET\"\n | \"UPLOAD_MULTIPLE_OBJECTS\"\n | \"GENERATE_PRESIGNED_URL\";\n\nexport class S3 extends Integration {\n private action: S3Action;\n private resource?: Binding<string>;\n private path?: Binding<string>;\n private body?: Binding<string>;\n private fileObjects?: Binding<string>;\n private listFilesConfig?: {\n prefix?: Binding<string>;\n delimiter?: Binding<string>;\n };\n\n constructor(\n name: string,\n integration: string,\n config: {\n action: S3Action;\n resource?: Binding<string>;\n path?: Binding<string>;\n body?: Binding<string>;\n fileObjects?: Binding<string>;\n listFilesConfig?: {\n prefix?: Binding<string>;\n delimiter?: Binding<string>;\n };\n },\n ) {\n super(name, integration);\n this.action = config.action;\n this.resource = config.resource;\n this.path = config.path;\n this.body = config.body;\n this.fileObjects = config.fileObjects;\n this.listFilesConfig = config.listFilesConfig;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n s3: {\n action: this.action,\n ...(this.resource ? { resource: await binding(this.resource) } : {}),\n ...(this.path ? { path: await binding(this.path) } : {}),\n ...(this.body ? { body: await binding(this.body) } : {}),\n ...(this.fileObjects\n ? { fileObjects: await binding(this.fileObjects) }\n : {}),\n ...(this.listFilesConfig\n ? {\n listFilesConfig: {\n ...(this.listFilesConfig.prefix\n ? { prefix: await binding(this.listFilesConfig.prefix) }\n : {}),\n ...(this.listFilesConfig.delimiter\n ? {\n delimiter: await binding(\n this.listFilesConfig.delimiter,\n ),\n }\n : {}),\n },\n }\n : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [`action: \"${this.action}\"`];\n\n if (this.resource) {\n parts.push(\n `resource: ${\n typeof this.resource === \"function\"\n ? signatureV2((await toJSBody(this.resource)).body, entities)\n : `\"${this.resource}\"`\n }`,\n );\n }\n\n if (this.path) {\n parts.push(\n `path: ${\n typeof this.path === \"function\"\n ? signatureV2((await toJSBody(this.path)).body, entities)\n : `\"${this.path}\"`\n }`,\n );\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === \"function\"\n ? signatureV2((await toJSBody(this.body)).body, entities)\n : `\"${this.body}\"`\n }`,\n );\n }\n\n if (this.fileObjects) {\n parts.push(\n `fileObjects: ${\n typeof this.fileObjects === \"function\"\n ? signatureV2((await toJSBody(this.fileObjects)).body, entities)\n : `\"${this.fileObjects}\"`\n }`,\n );\n }\n\n if (this.listFilesConfig) {\n const configParts: string[] = [];\n if (this.listFilesConfig.prefix) {\n configParts.push(\n `prefix: ${\n typeof this.listFilesConfig.prefix === \"function\"\n ? signatureV2(\n (await toJSBody(this.listFilesConfig.prefix)).body,\n entities,\n )\n : `\"${this.listFilesConfig.prefix}\"`\n }`,\n );\n }\n if (this.listFilesConfig.delimiter) {\n configParts.push(\n `delimiter: ${\n typeof this.listFilesConfig.delimiter === \"function\"\n ? signatureV2(\n (await toJSBody(this.listFilesConfig.delimiter)).body,\n entities,\n )\n : `\"${this.listFilesConfig.delimiter}\"`\n }`,\n );\n }\n if (configParts.length > 0) {\n parts.push(`listFilesConfig: { ${configParts.join(\", \")} }`);\n }\n }\n\n return `new S3(\"${this.name}\", \"${this.integration}\", { ${parts.join(\", \")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): S3 {\n return new S3(json?.name, json?.step?.integration, {\n action: json?.step?.s3?.action,\n resource: json?.step?.s3?.resource\n ? fromBinding(json?.step?.s3?.resource, entities)\n : undefined,\n path: json?.step?.s3?.path\n ? fromBinding(json?.step?.s3?.path, entities)\n : undefined,\n body: json?.step?.s3?.body\n ? fromBinding(json?.step?.s3?.body, entities)\n : undefined,\n fileObjects: json?.step?.s3?.fileObjects\n ? fromBinding(json?.step?.s3?.fileObjects, entities)\n : undefined,\n listFilesConfig: json?.step?.s3?.listFilesConfig\n ? {\n prefix: json?.step?.s3?.listFilesConfig?.prefix\n ? fromBinding(json?.step?.s3?.listFilesConfig?.prefix, entities)\n : undefined,\n delimiter: json?.step?.s3?.listFilesConfig?.delimiter\n ? fromBinding(\n json?.step?.s3?.listFilesConfig?.delimiter,\n entities,\n )\n : undefined,\n }\n : undefined,\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 bindingSql(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, { condense: false })).body, 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 bindingSql(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, { condense: false })).body, 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 Redshift 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 redshift: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Redshift(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement, { condense: false })).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Redshift {\n return new Redshift(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.redshift?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class MicrosoftSql 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 mssql: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new MicrosoftSql(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement)).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): MicrosoftSql {\n return new MicrosoftSql(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.mssql?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class MariaDB 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 mariadb: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n useAdvancedMatching: \"auto\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new MariaDB(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement, { condense: false })).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): MariaDB {\n return new MariaDB(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.mariadb?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class MySQL 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 mysql: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n useAdvancedMatching: \"auto\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new MySQL(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement, { condense: false })).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): MySQL {\n return new MySQL(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.mysql?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class GraphQL extends Integration {\n private body: Binding<string>;\n private variables?: Binding<string>;\n private headers?: { key: Binding<string>; value: Binding<string> }[];\n\n constructor(\n name: string,\n integration: string,\n config: {\n query: Binding<string>;\n variables?: Binding<string>;\n headers?: { key: Binding<string>; value: Binding<string> }[];\n },\n ) {\n super(name, integration);\n\n this.body = config.query;\n this.variables = config.variables;\n this.headers = config.headers;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n graphqlintegration: {\n body: await bindingGraphQL(this.body),\n ...(this.variables\n ? {\n custom: {\n variables: {\n value: await binding(this.variables),\n },\n },\n }\n : {}),\n ...(this.headers && Array.isArray(this.headers)\n ? {\n headers: await Promise.all(\n this.headers.map(async (header) => ({\n key: await binding(header.key),\n value: await binding(header.value),\n })),\n ),\n }\n : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [\n `query: ${typeof this.body === \"function\" ? signatureV2((await toJSBody(this.body)).body, entities) : `\"${this.body}\"`}`,\n ];\n\n if (this.variables) {\n parts.push(\n `variables: ${typeof this.variables === \"function\" ? signatureV2((await toJSBody(this.variables)).body, entities) : `\"${this.variables}\"`}`,\n );\n }\n\n if (this.headers) {\n const headers = (\n await Promise.all(\n this.headers.map(\n async (h) =>\n `{ key: ${\n typeof h.key === \"function\"\n ? signatureV2((await toJSBody(h.key)).body, entities)\n : `\"${h.key}\"`\n }, value: ${\n typeof h.value === \"function\"\n ? signatureV2((await toJSBody(h.value)).body, entities)\n : `\"${h.value}\"`\n } }`,\n ),\n )\n ).join(\", \");\n parts.push(`headers: [${headers}]`);\n }\n\n return `new GraphQL(\"${this.name}\", \"${this.integration}\", { ${parts.join(\", \")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): GraphQL {\n const graphql = json?.step?.graphqlintegration;\n\n return new GraphQL(json?.name, json?.step?.integration, {\n query: fromBinding(graphql?.body, entities),\n variables: graphql?.custom?.variables?.value\n ? fromBinding(graphql?.custom?.variables?.value, entities)\n : undefined,\n headers: graphql?.headers?.map((header: any) => ({\n key: fromBinding(header.key, entities),\n value: fromBinding(header.value, 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 private openapi?: {\n path: string;\n };\n\n protected type: string;\n\n constructor(\n name: string,\n integration: string = \"restapi\",\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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration);\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 this.openapi = openapi;\n this.type = this.isIntegration() ? \"restapiintegration\" : \"restapi\";\n }\n\n public async toJSON(): Promise<JsonValue> {\n const openApiAction = (): string => {\n if (!this.isIntegration()) {\n return undefined;\n }\n\n if (this.openapi?.path) {\n let path: string = this.openapi.path.trim();\n\n if (path.startsWith(\"`\") && path.endsWith(\"`\")) {\n path = path.slice(1, -1);\n }\n\n return `${this.method} ${path}`;\n }\n\n return \"genericHttpRequest\";\n };\n\n const method = this.method?.toString().toUpperCase();\n const supportedMethods = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"DELETE\",\n \"PATCH\",\n \"HEAD\",\n \"OPTIONS\",\n ];\n\n return {\n name: this.name,\n step: {\n integration: this.integration,\n [this.type]: {\n httpMethod: supportedMethods.includes(method) ? method : \"GET\",\n openApiAction: openApiAction(),\n ...(this.url\n ? {\n [this.isIntegration() ? \"urlPath\" : \"path\"]: await binding(\n this.url,\n ),\n }\n : {}),\n ...(this.headers && Array.isArray(this.headers)\n ? {\n headers: await Promise.all(\n this.headers.map(async (header) => ({\n key: await binding(header.key),\n value: await binding(header.value),\n })),\n ),\n }\n : {}),\n ...(this.params && Array.isArray(this.params)\n ? {\n params: await Promise.all(\n this.params.map(async (param) => ({\n key: await binding(param.key),\n value: await binding(param.value),\n })),\n ),\n }\n : {}),\n ...(this.body ? { body: await binding(this.body) } : {}),\n\n // Other params that I might need to add.\n responseType: \"auto\",\n bodyType: \"jsonBody\",\n },\n },\n };\n }\n\n private isIntegration(): boolean {\n return this.integration !== \"restapi\";\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new RestApi(${await this.constructorParametersString(entities)})`;\n }\n\n protected async constructorParametersString(\n entities: string[],\n ): 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)).body, entities)\n : `\"${this.url}\"`\n }`,\n );\n }\n\n if (this.headers) {\n const headers = (\n await Promise.all(\n this.headers.map(\n async (h) =>\n `{ key: ${\n typeof h.key === \"function\"\n ? signatureV2((await toJSBody(h.key)).body, entities)\n : `\"${h.key}\"`\n }, value: ${\n typeof h.value === \"function\"\n ? signatureV2((await toJSBody(h.value)).body, entities)\n : `\"${h.value}\"`\n } }`,\n ),\n )\n ).join(\", \");\n parts.push(`headers: [${headers}]`);\n }\n\n if (this.params) {\n const params = (\n await Promise.all(\n this.params.map(\n async (p) =>\n `{ key: ${\n typeof p.key === \"function\"\n ? signatureV2((await toJSBody(p.key)).body, entities)\n : `\"${p.key}\"`\n }, value: ${\n typeof p.value === \"function\"\n ? signatureV2((await toJSBody(p.value)).body, entities)\n : `\"${p.value}\"`\n } }`,\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)).body, entities)\n : JSON.stringify(this.body)\n }`,\n );\n }\n\n return `\"${this.name}\", \"${this.integration}\", { ${parts.join(\", \")} }, ${JSON.stringify(this.openapi)}`;\n }\n\n public static fromJSON(json: any, entities: string[]): RestApi {\n const config =\n json?.step?.[\n json?.step?.integration === \"restapi\" ? \"restapi\" : \"restapiintegration\"\n ];\n\n if (json?.step?.integration === \"restapiintegration\") {\n return new RestApi(\n json?.name,\n json?.step?.integration,\n OpenApi.configFromJSON(config, entities),\n OpenApi.openapiFromJSON(config),\n );\n }\n\n return new RestApi(\n json?.name,\n json?.step?.integration,\n {\n method: config?.httpMethod,\n url: fromBinding(config?.path, entities),\n headers: config?.headers?.map((header: any) => ({\n key: fromBinding(header.key, entities),\n value: fromBinding(header.value, entities),\n })),\n params: config?.params?.map((param: any) => ({\n key: fromBinding(param.key, entities),\n value: fromBinding(param.value, entities),\n })),\n body: fromBinding(config?.body, entities),\n },\n OpenApi.openapiFromJSON(config),\n );\n }\n}\n\ntype SalesforceAction =\n | { action: \"SOQL_ACTION_SOQL\"; soqlBody: Binding<string> }\n | {\n action: \"CRUD_ACTION_READ\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_CREATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_UPDATE\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_DELETE\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"BULK_ACTION_CREATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"BULK_ACTION_UPDATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n };\n\nexport class Salesforce extends Integration {\n private action: SalesforceAction;\n\n constructor(\n name: string,\n integration: string,\n config: {\n action: SalesforceAction;\n },\n ) {\n super(name, integration);\n this.action = config.action;\n }\n\n public async toJSON(): Promise<JsonValue> {\n let salesforce;\n switch (this.action.action) {\n case \"SOQL_ACTION_SOQL\":\n salesforce = {\n soql: {\n action: this.action.action,\n sqlBody: await binding(this.action.soqlBody),\n },\n };\n break;\n\n case \"CRUD_ACTION_READ\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceId: await binding(this.action.resourceId),\n },\n };\n break;\n\n case \"CRUD_ACTION_CREATE\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"CRUD_ACTION_UPDATE\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceId: await binding(this.action.resourceId),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"CRUD_ACTION_DELETE\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceId: await binding(this.action.resourceId),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"BULK_ACTION_CREATE\":\n salesforce = {\n bulk: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"BULK_ACTION_UPDATE\":\n salesforce = {\n bulk: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n }\n return {\n name: this.name,\n step: {\n integration: this.integration,\n salesforce,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n switch (this.action.action) {\n case \"SOQL_ACTION_SOQL\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"SOQL_ACTION_SOQL\", soqlBody: ${typeof this.action.soqlBody === \"function\" ? signatureV2((await toJSBody(this.action.soqlBody, { condense: false })).body, entities) : `\"${this.action.soqlBody}\"`} } })`;\n\n case \"CRUD_ACTION_READ\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_READ\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceId: ${typeof this.action.resourceId === \"function\" ? signatureV2((await toJSBody(this.action.resourceId, { condense: false })).body, entities) : `\"${this.action.resourceId}\"`} } })`;\n\n case \"CRUD_ACTION_CREATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_CREATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"CRUD_ACTION_UPDATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_UPDATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceId: ${typeof this.action.resourceId === \"function\" ? signatureV2((await toJSBody(this.action.resourceId, { condense: false })).body, entities) : `\"${this.action.resourceId}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"CRUD_ACTION_DELETE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_DELETE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceId: ${typeof this.action.resourceId === \"function\" ? signatureV2((await toJSBody(this.action.resourceId, { condense: false })).body, entities) : `\"${this.action.resourceId}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"BULK_ACTION_CREATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"BULK_ACTION_CREATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"BULK_ACTION_UPDATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"BULK_ACTION_UPDATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n }\n }\n\n public static fromJSON(json: any, entities: string[]): Salesforce {\n // NOTE: @joeyagreco - we use if statements instead of switch statements here since the json field is at different places (proto oneofs dont be the most annoying thing to work around challenge: impossible)\n if (json?.step?.salesforce?.soql?.action === \"SOQL_ACTION_SOQL\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"SOQL_ACTION_SOQL\",\n soqlBody: fromBinding(\n json?.step?.salesforce?.soql?.soqlBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_READ\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_READ\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceId: fromBinding(\n json?.step?.salesforce?.crud?.resourceId,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_CREATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_CREATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.crud?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_UPDATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_UPDATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceId: fromBinding(\n json?.step?.salesforce?.crud?.resourceId,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.crud?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_DELETE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_DELETE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceId: fromBinding(\n json?.step?.salesforce?.crud?.resourceId,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.crud?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.bulk?.action === \"BULK_ACTION_CREATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"BULK_ACTION_CREATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.bulk?.resourceType,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.bulk?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.bulk?.action === \"BULK_ACTION_UPDATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"BULK_ACTION_UPDATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.bulk?.resourceType,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.bulk?.resourceBody,\n entities,\n ),\n },\n });\n }\n }\n}\n\nexport class OpenApi extends RestApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration, config, openapi);\n }\n\n public static configFromJSON(\n json: any,\n entities: string[],\n ): {\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 return {\n method: json?.httpMethod,\n url: fromBinding(json?.urlPath, entities),\n headers: json?.headers?.map((header: any) => ({\n key: fromBinding(header.key, entities),\n value: fromBinding(header.value, entities),\n })),\n params: json?.params?.map((param: any) => ({\n key: fromBinding(param.key, entities),\n value: fromBinding(param.value, entities),\n })),\n body: fromBinding(json?.body, entities),\n };\n }\n\n public static openapiFromJSON(json: any): {\n path: string;\n } {\n return json?.openApiAction &&\n json.openApiAction !== \"\" &&\n json.openApiAction !== \"genericHttpRequest\"\n ? { path: json.openApiAction.split(\" \")[1] }\n : undefined;\n }\n}\n\nexport class Jira extends OpenApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration, config, openapi);\n this.type = \"jira\";\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Jira(${await this.constructorParametersString(entities)})`;\n }\n\n public static fromJSON(json: any, entities: string[]): Jira {\n return new Jira(\n json?.name,\n json?.step?.integration,\n OpenApi.configFromJSON(json?.step?.jira, entities),\n OpenApi.openapiFromJSON(json?.step?.jira),\n );\n }\n}\n\nfunction createOpenApiIntegrationClass(\n className: string,\n integrationName: string,\n) {\n return class extends OpenApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration, config, openapi);\n this.type = integrationName;\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new ${className}(${await this.constructorParametersString(entities)})`;\n }\n\n public static fromJSON(json: any, entities: string[]) {\n return new this(\n json?.name,\n json?.step?.integration,\n OpenApi.configFromJSON(json?.step?.[integrationName], entities),\n OpenApi.openapiFromJSON(json?.step?.[integrationName]),\n );\n }\n };\n}\n\n// All of the openapi integrations should go here\nexport const Airtable = createOpenApiIntegrationClass(\"Airtable\", \"airtable\");\nexport const Anthropic = createOpenApiIntegrationClass(\n \"Anthropic\",\n \"anthropic\",\n);\nexport const Asana = createOpenApiIntegrationClass(\"Asana\", \"asana\");\nexport const Bitbucket = createOpenApiIntegrationClass(\n \"Bitbucket\",\n \"bitbucket\",\n);\nexport const Box = createOpenApiIntegrationClass(\"Box\", \"box\");\nexport const CircleCI = createOpenApiIntegrationClass(\"CircleCI\", \"circleci\");\nexport const Cohere = createOpenApiIntegrationClass(\"Cohere\", \"cohere\");\nexport const Confluence = createOpenApiIntegrationClass(\n \"Confluence\",\n \"confluence\",\n);\nexport const Datadog = createOpenApiIntegrationClass(\"Datadog\", \"datadog\");\nexport const Dropbox = createOpenApiIntegrationClass(\"Dropbox\", \"dropbox\");\nexport const Elasticsearch = createOpenApiIntegrationClass(\n \"Elasticsearch\",\n \"elasticsearch\",\n);\nexport const Fireworks = createOpenApiIntegrationClass(\n \"Fireworks\",\n \"fireworks\",\n);\nexport const Front = createOpenApiIntegrationClass(\"Front\", \"front\");\nexport const Gemini = createOpenApiIntegrationClass(\"Gemini\", \"gemini\");\nexport const GitHub = createOpenApiIntegrationClass(\"GitHub\", \"github\");\nexport const GoogleAnalytics = createOpenApiIntegrationClass(\n \"GoogleAnalytics\",\n \"googleanalytics\",\n);\nexport const GoogleDrive = createOpenApiIntegrationClass(\n \"GoogleDrive\",\n \"googledrive\",\n);\nexport const Groq = createOpenApiIntegrationClass(\"Groq\", \"groq\");\nexport const HubSpot = createOpenApiIntegrationClass(\"HubSpot\", \"hubspot\");\nexport const Intercom = createOpenApiIntegrationClass(\"Intercom\", \"intercom\");\nexport const LaunchDarkly = createOpenApiIntegrationClass(\n \"LaunchDarkly\",\n \"launchdarkly\",\n);\nexport const Mistral = createOpenApiIntegrationClass(\"Mistral\", \"mistral\");\nexport const Notion = createOpenApiIntegrationClass(\"Notion\", \"notion\");\nexport const OpenAI = createOpenApiIntegrationClass(\"OpenAI\", \"openai_v2\");\nexport const PagerDuty = createOpenApiIntegrationClass(\n \"PagerDuty\",\n \"pagerduty\",\n);\nexport const Perplexity = createOpenApiIntegrationClass(\n \"Perplexity\",\n \"perplexity\",\n);\nexport const Segment = createOpenApiIntegrationClass(\"Segment\", \"segment\");\nexport const SendGrid = createOpenApiIntegrationClass(\"SendGrid\", \"sendgrid\");\nexport const Slack = createOpenApiIntegrationClass(\"Slack\", \"slack\");\nexport const StabilityAI = createOpenApiIntegrationClass(\n \"StabilityAI\",\n \"stabilityai\",\n);\nexport const Stripe = createOpenApiIntegrationClass(\"Stripe\", \"stripe\");\nexport const Twilio = createOpenApiIntegrationClass(\"Twilio\", \"twilio\");\nexport const Zendesk = createOpenApiIntegrationClass(\"Zendesk\", \"zendesk\");\nexport const Zoom = createOpenApiIntegrationClass(\"Zoom\", \"zoom\");\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\n ? { emailSubject: await binding(this.subject) }\n : {}),\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((await toJSBody(this.from)).body, entities)\n : `\"${this.from}\"`\n }`,\n );\n }\n\n if (this.to) {\n parts.push(\n `to: ${\n typeof this.to === \"function\"\n ? signatureV2((await toJSBody(this.to)).body, entities)\n : `\"${this.to}\"`\n }`,\n );\n }\n\n if (this.cc) {\n parts.push(\n `cc: ${\n typeof this.cc === \"function\"\n ? signatureV2((await toJSBody(this.cc)).body, entities)\n : `\"${this.cc}\"`\n }`,\n );\n }\n\n if (this.bcc) {\n parts.push(\n `bcc: ${\n typeof this.bcc === \"function\"\n ? signatureV2((await toJSBody(this.bcc)).body, entities)\n : `\"${this.bcc}\"`\n }`,\n );\n }\n\n if (this.subject) {\n parts.push(\n `subject: ${\n typeof this.subject === \"function\"\n ? signatureV2((await toJSBody(this.subject)).body, entities)\n : `\"${this.subject}\"`\n }`,\n );\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === \"function\"\n ? signatureV2((await toJSBody(this.body)).body, 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\n ? fromBinding(json?.step?.email?.emailCc, entities)\n : undefined,\n bcc: json?.step?.email?.emailBcc\n ? fromBinding(json?.step?.email?.emailBcc, entities)\n : 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 bindingSql(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, { condense: false })).body, 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(\n condition: Condition,\n entities: string[],\n): Promise<string> {\n return `{ when: ${typeof condition.when === \"function\" ? signatureV2((await toJSBody(condition.when)).body, 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: ensureIIFE(\n (await toJS<boolean>(this.conditions.if.when)).body,\n ),\n blocks: await Promise.all(\n this.conditions.if.then.map(async (block) => await block.toJSON()),\n ),\n },\n ...(await (async () =>\n this.conditions.elif\n ? {\n elseIf: await Promise.all(\n this.conditions.elif.map(async (condition) => ({\n condition: ensureIIFE(\n (await toJS<boolean>(condition.when)).body,\n ),\n blocks: await Promise.all(\n condition.then.map(async (block) => await block.toJSON()),\n ),\n })),\n ),\n }\n : { elseIf: [] })()),\n else: this.conditions.else\n ? {\n blocks: await Promise.all(\n this.conditions.else.map(async (block) => await block.toJSON()),\n ),\n }\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\n ? json?.conditional?.elseIf?.map((condition: any) => ({\n when: fromJS<boolean>(condition.condition, entities),\n then: condition.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n }))\n : [],\n else: json?.conditional?.else\n ? json?.conditional?.else?.blocks?.map((block: any) =>\n Block.fromJSON(block, entities),\n )\n : [],\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(\n this.blocks?.map(async (block) => await block.toJSON()),\n ),\n paths: ensureIIFE((await toJS<JsonValue[]>(this.over)).body),\n variables: this.variables,\n },\n wait: \"WAIT_ALL\",\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const variables = JSON.stringify(this.variables);\n const blocks = await Promise.all(\n this.blocks.map(async (block) => await block.toSDK(entities)),\n );\n return `new Parallel(\"${this.name}\", { over: ${typeof this.over === \"function\" ? signatureV2((await toJSBody(this.over)).body, entities) : this.over}, variables: ${variables}, blocks: ${blocks.length > 0 ? blocks : \"[]\"} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Parallel {\n return new Parallel(json?.name, {\n over: fromJS<JsonValue[]>(\n json?.parallel?.dynamic?.paths ?? \"''\",\n entities,\n ),\n variables: {\n item: json?.parallel?.dynamic?.variables?.item ?? \"\",\n },\n blocks:\n 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: ensureIIFE((await toJS<JsonValue[]>(this.over)).body),\n type: \"TYPE_FOREACH\",\n variables: this.variables,\n blocks: await Promise.all(\n this.blocks.map(async (block) => await block.toJSON()),\n ),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const variables = JSON.stringify(this.variables);\n const blocks = await Promise.all(\n this.blocks.map(async (block) => await block.toSDK(entities)),\n );\n return `new Loop(\"${this.name}\", { over: ${typeof this.over === \"function\" ? signatureV2((await toJSBody(this.over)).body, entities) : this.over}, variables: ${variables}, blocks: ${blocks.length > 0 ? blocks : \"[]\"} })`;\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(\n this.variables.map(async (variable) => {\n return {\n key: variable.key,\n value: ensureIIFE((await toJS<JsonValue[]>(variable.value)).body),\n type: \"TYPE_SIMPLE\",\n mode: \"MODE_READWRITE\",\n };\n }),\n ),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Variables(\"${this.name}\", [${(\n await Promise.all(\n this.variables?.map(\n async (variable) =>\n `{ key: \"${variable.key}\", value: ${typeof variable.value === \"function\" ? signatureV2((await toJSBody(variable.value)).body, entities) : variable.value} }`,\n ),\n )\n ).join(\",\")}])`;\n }\n\n public static fromJSON(json: any, entities: string[]): Variables {\n return new Variables(\n json?.name,\n json?.variables?.items?.map((variable: any) => ({\n key: variable.key,\n value: fromBinding(variable.value, entities),\n })),\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: {\n blocks: await Promise.all(\n this.try.map(async (block) => await block.toJSON()),\n ),\n },\n catch: {\n blocks: await Promise.all(\n this.catch.map(async (block) => await block.toJSON()),\n ),\n },\n finally: {\n blocks: this.finally\n ? await Promise.all(\n this.finally.map(async (block) => await block.toJSON()),\n )\n : undefined,\n },\n variables: this.variables,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const tryBlocks = await Promise.all(\n this.try.map(async (block) => await block.toSDK(entities)),\n );\n const catchBlocks = await Promise.all(\n this.catch.map(async (block) => await block.toSDK(entities)),\n );\n const finallyBlocks = this.finally?.map(\n async (block) => await block.toSDK(entities),\n );\n return `new TryCatch(\"${this.name}\", { try: [${tryBlocks.join(\",\")}], catch: [${catchBlocks.join(\",\")}], finally: [${finallyBlocks?.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) =>\n Block.fromJSON(block, entities),\n ),\n catch: json?.tryCatch?.catch.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n finally: json?.tryCatch?.finally?.blocks?.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\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)).body,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Throw(\"${this.name}\", { error: ${typeof this.error === \"function\" ? signatureV2((await toJSBody(this.error)).body, entities) : ensureIIFE(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)).body,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Return(\"${this.name}\", { data: ${typeof this.data === \"function\" ? signatureV2((await toJSBody(this.data)).body, entities) : ensureIIFE(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 Break extends Block {\n private condition: Binding<JsonValue>;\n\n constructor(\n name: string,\n config: {\n condition: Binding<JsonValue>;\n },\n ) {\n super(name);\n\n this.condition = config.condition;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n break: {\n condition: ensureIIFE((await toJS<JsonValue[]>(this.condition)).body),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Break(\"${this.name}\", { condition: ${typeof this.condition === \"function\" ? signatureV2((await toJSBody(this.condition)).body, entities) : ensureIIFE(JSON.stringify(this.condition))} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Break {\n return new Break(json?.name, {\n condition: fromJS(json?.break?.condition, entities),\n });\n }\n}\n\nexport type Authorization =\n | {\n type: \"AUTHORIZATION_TYPE_APP_USERS\";\n }\n | {\n type: \"AUTHORIZATION_TYPE_JS_EXPRESSION\";\n expression: Binding<boolean>;\n };\n\nexport class Api {\n private blocks: Block[];\n private name: string;\n private authorization?: Authorization;\n\n constructor(\n name: string,\n blocks: Block[] = [],\n authorization: Authorization = { type: \"AUTHORIZATION_TYPE_APP_USERS\" },\n ) {\n this.name = name;\n this.blocks = blocks;\n this.authorization = authorization;\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const imports =\n \"import { Api, JavaScript, Python, Athena, BigQuery, DynamoDb, MicrosoftSql, MySQL, PostgreSQL, Redshift, Snowflake, S3, Salesforce, RestApi, GraphQL, Databricks, Conditional, Parallel, Loop, TryCatch, Variables, Throw, Return, Break, Email, Airtable, Anthropic, Asana, Bitbucket, Box, CircleCI, Cohere, Datadog, Dropbox, Elasticsearch, Fireworks, Front, Gemini, GitHub, GoogleAnalytics, GoogleDrive, Groq, HubSpot, Intercom, Jira, LaunchDarkly, Mistral, Notion, OpenAI, PagerDuty, Perplexity, Segment, SendGrid, Slack, StabilityAI, Stripe, Twilio, Zendesk, Zoom, Confluence } 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(\",\")}], ${this.authorization.type === \"AUTHORIZATION_TYPE_JS_EXPRESSION\" ? `{ type: \"AUTHORIZATION_TYPE_JS_EXPRESSION\", expression: ${typeof this.authorization.expression === \"function\" ? signatureV2((await toJSBody(this.authorization.expression)).body, entities) : this.authorization.expression} }` : `{ type: \"AUTHORIZATION_TYPE_APP_USERS\" }`})`;\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 type: json.authorization.type,\n expression:\n json.authorization.type === \"AUTHORIZATION_TYPE_JS_EXPRESSION\"\n ? fromJS(json.authorization.expression, entities)\n : undefined,\n },\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 authorization: {\n type:\n | \"AUTHORIZATION_TYPE_APP_USERS\"\n | \"AUTHORIZATION_TYPE_JS_EXPRESSION\";\n expression?: string;\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 authorization: {\n type: this.authorization.type,\n ...{\n expression:\n this.authorization.type === \"AUTHORIZATION_TYPE_JS_EXPRESSION\"\n ? `(() => ${(await toJS<boolean>(this.authorization.expression)).body})()`\n : undefined,\n },\n },\n trigger: {\n application: {},\n },\n blocks: [],\n };\n\n api.blocks = await Promise.all(\n this.blocks.map(async (block) => await block.toJSON()),\n );\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\nexport function 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(\n value: string,\n entities: string[],\n): 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 try {\n const ast = parse(value, {\n ecmaVersion: \"latest\",\n sourceType: \"script\",\n });\n\n const identifiers = Array.from(extractIdentifiers(ast));\n\n return new Function(\n `{ ${identifiers.join(\", \")} }`,\n `return (${value})`,\n ) as (_: State) => string;\n } catch (e) {\n console.error(\n `We couldn't extract identifiers from the binding ${value}`,\n e,\n );\n return value;\n }\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>(\n value: (state: State) => T,\n node: Node,\n options: { condense?: boolean; block?: boolean } = {\n condense: true,\n block: true,\n },\n) {\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, \" \").trim();\n }\n\n return beautified;\n}\n\nfunction createAst(value: string): Program {\n if (value.startsWith(\"{\") && value.endsWith(\"}\")) {\n value = `(${value})`;\n }\n\n return parse(value, {\n ecmaVersion: \"latest\",\n sourceType: \"script\",\n preserveParens: false,\n });\n}\n\nexport async function toJSBody<T extends JsonValue>(\n value: (state: State) => T,\n options: { block?: boolean; condense?: boolean; function?: boolean } = {\n block: true,\n condense: true,\n function: false,\n },\n): Promise<{ body: string; iife: boolean; node?: Node }> {\n if (typeof value !== \"function\") {\n return {\n body: `\\`${JSON.stringify(value)}\\``,\n iife: true,\n };\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 = (\n (program as ExpressionStatement).expression as FunctionExpression\n ).body;\n\n if (body.type === \"BlockStatement\") {\n return {\n body: await beautifyAndOptionallyCondense(value, body, {\n ...options,\n block: options.block !== false, // Use the provided block option\n }),\n iife: true,\n node: body,\n };\n }\n\n let bodyText = safeBodyText(\n value.toString().slice(body.start, body.end),\n body,\n );\n if (options.condense) {\n bodyText = bodyText\n .replace(/\\s*\\n\\s*/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n }\n\n return {\n body: `${options.function ? \"return \" : \"\"}${bodyText}`,\n iife: options.function,\n node: body,\n };\n case \"FunctionDeclaration\":\n let contents = value\n .toString()\n .slice(program.body.start, program.body.end);\n\n if (program.body.type !== \"BlockStatement\") {\n return {\n body: contents,\n iife: false,\n node: program.body,\n };\n }\n\n if (\n !options.function &&\n program.body.body.length === 1 &&\n program.body.body[0].type === \"ReturnStatement\"\n ) {\n const argument = program.body.body[0].argument;\n if (!argument) {\n return {\n body: ``,\n iife: false,\n node: program.body.body[0],\n };\n }\n\n let bodyText = safeBodyText(\n value.toString().slice(argument.start, argument.end),\n argument,\n );\n\n return {\n body: bodyText,\n iife: false, // This should be false but we need to deal with the nested string template case.\n node: argument,\n };\n }\n\n return {\n body: await beautifyAndOptionallyCondense(value, program.body, options),\n iife: true,\n node: program.body,\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>(\n value: Binding<T>,\n): Promise<{ body: string; node?: Node }> {\n if (typeof value !== \"function\") {\n return {\n body: JSON.stringify(value),\n };\n }\n\n const { body, iife, node } = await toJSBody(value as (state: State) => T);\n\n if (iife) {\n return {\n body: `(() => ${body})()`,\n node,\n };\n }\n\n return { body, node };\n}\n\nexport function fromJS<T extends JsonValue>(\n value: string,\n entities: string[] = [],\n): Binding<T> {\n try {\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 if (value.length === 0) {\n return new Function(\"return \") as (_: State) => T;\n }\n\n let unaryOps: string[] = [];\n const ast = createAst(value);\n\n if (ast.body.length === 0) {\n return new Function(\"return \") as (_: State) => T;\n }\n\n let call = (ast.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 (\n _: State,\n ) => T;\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 const ast = createAst(value);\n\n const identifiers = Array.from(extractIdentifiers(ast));\n\n return new Function(\n `{ ${identifiers.join(\", \")} }`,\n `return (${value})`,\n ) as (_: State) => 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 } catch (e) {\n console.error(\"There was an error during parsing in fromJS\", e);\n // fallback to an empty function so we don't crash\n return new Function(\"return ''\") as (_: State) => T;\n }\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\nexport function ensureIIFE(value: string): string {\n // We write the IIFE so we can be loose with the fomratting here.\n // For example, we'd never get ( ( ) =>)().\n if (value.startsWith(\"(() => \") && value.endsWith(\")()\")) {\n return value;\n }\n\n let safeValue = value.trim();\n if (safeValue.startsWith(\"{\") && safeValue.endsWith(\"}\")) {\n safeValue = `(${safeValue})`;\n }\n\n return `(() => ${safeValue})()`;\n}\n\n/**\n * Extracts identifier names from an AST by walking the tree.\n */\nfunction extractIdentifiers(\n node: Node,\n identifiers: Set<string> = new Set(),\n): Set<string> {\n if (!node) {\n return identifiers;\n }\n\n // we only care about the root of the expression, so we gotta unwind the subtree\n if (node.type === \"MemberExpression\") {\n const memberExpr = node as any;\n extractIdentifiers(memberExpr.object, identifiers);\n return identifiers;\n }\n\n if (node.type === \"Identifier\") {\n identifiers.add((node as any).name);\n }\n\n for (const key in node) {\n const value = (node as any)[key];\n\n if (value && typeof value === \"object\") {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === \"object\" && item.type) {\n extractIdentifiers(item, identifiers);\n }\n }\n } else if (value.type) {\n extractIdentifiers(value, identifiers);\n }\n }\n }\n\n return identifiers;\n}\n\nfunction safeBodyText(body: string, node: Node): string {\n if (node.type === \"ObjectExpression\") {\n return `(${body})`;\n }\n return body;\n}\n\n// All of the integrations (openapi and not) should be registered\n// NOTE: @joeyagreco - when adding support for an integration here, make sure to update:\n// NOTE: @joeyagreco - 1. to-sdk-transformer.ts\n// NOTE: @joeyagreco - 2. context-util.ts\n// NOTE: @joeyagreco - 3. the import statement in Api.toSDK()\n// NOTE: @joeyagreco - 4. superblocks-api.md\nIntegration.registerIntegration(\"airtable\", Airtable);\nIntegration.registerIntegration(\"athena\", Athena);\nIntegration.registerIntegration(\"anthropic\", Anthropic);\nIntegration.registerIntegration(\"asana\", Asana);\nIntegration.registerIntegration(\"bigquery\", BigQuery);\nIntegration.registerIntegration(\"bitbucket\", Bitbucket);\nIntegration.registerIntegration(\"box\", Box);\nIntegration.registerIntegration(\"circleci\", CircleCI);\nIntegration.registerIntegration(\"cohere\", Cohere);\nIntegration.registerIntegration(\"confluence\", Confluence);\nIntegration.registerIntegration(\"databricks\", Databricks);\nIntegration.registerIntegration(\"datadog\", Datadog);\nIntegration.registerIntegration(\"dropbox\", Dropbox);\nIntegration.registerIntegration(\"dynamodb\", DynamoDb);\nIntegration.registerIntegration(\"elasticsearch\", Elasticsearch);\nIntegration.registerIntegration(\"email\", Email);\nIntegration.registerIntegration(\"fireworks\", Fireworks);\nIntegration.registerIntegration(\"front\", Front);\nIntegration.registerIntegration(\"gemini\", Gemini);\nIntegration.registerIntegration(\"github\", GitHub);\nIntegration.registerIntegration(\"googleanalytics\", GoogleAnalytics);\nIntegration.registerIntegration(\"googledrive\", GoogleDrive);\nIntegration.registerIntegration(\"graphqlintegration\", GraphQL);\nIntegration.registerIntegration(\"groq\", Groq);\nIntegration.registerIntegration(\"hubspot\", HubSpot);\nIntegration.registerIntegration(\"intercom\", Intercom);\nIntegration.registerIntegration(\"javascript\", JavaScript);\nIntegration.registerIntegration(\"jira\", Jira);\nIntegration.registerIntegration(\"launchdarkly\", LaunchDarkly);\nIntegration.registerIntegration(\"mistral\", Mistral);\nIntegration.registerIntegration(\"notion\", Notion);\nIntegration.registerIntegration(\"pagerduty\", PagerDuty);\nIntegration.registerIntegration(\"perplexity\", Perplexity);\nIntegration.registerIntegration(\"postgres\", PostgreSQL);\nIntegration.registerIntegration(\"mssql\", MicrosoftSql);\nIntegration.registerIntegration(\"mariadb\", MariaDB);\nIntegration.registerIntegration(\"mysql\", MySQL);\nIntegration.registerIntegration(\"python\", Python);\nIntegration.registerIntegration(\"redshift\", Redshift);\nIntegration.registerIntegration(\"s3\", S3);\nIntegration.registerIntegration(\"salesforce\", Salesforce);\nIntegration.registerIntegration(\"segment\", Segment);\nIntegration.registerIntegration(\"sendgrid\", SendGrid);\nIntegration.registerIntegration(\"slack\", Slack);\nIntegration.registerIntegration(\"snowflake\", Snowflake);\nIntegration.registerIntegration(\"stabilityai\", StabilityAI);\nIntegration.registerIntegration(\"stripe\", Stripe);\nIntegration.registerIntegration(\"twilio\", Twilio);\nIntegration.registerIntegration(\"zendesk\", Zendesk);\nIntegration.registerIntegration(\"zoom\", Zoom);\n",
|
|
10
|
+
"src/superblocks-library-shim/index.ts": "/* eslint-disable */\nimport typescript_eslint_parser from \"@typescript-eslint/parser\";\nimport {\n CallExpression,\n ExpressionStatement,\n FunctionExpression,\n Literal,\n Node,\n parse,\n Program,\n UnaryExpression,\n} from \"acorn\";\nimport { ESLint } from \"eslint\";\nimport { format } from \"prettier\";\n\nexport const Global: Record<string, any> = {};\n\nexport type JsonValue = any;\n\n// This is the ideal type, but it's too restrictive when we use it for generating code,\n// because the builder side is doing access like `someVar.value`, but JsonValue is not\n// strict enough to avoid type errors, so you see a lot of:\n// error TS2551: Property 'value' does not exist on type 'JsonValue'. Did you mean 'valueOf'?\n// Property 'value' does not exist on type 'string'.\n//\n// export 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 function trimSqlSpaces(content: string): string {\n if (!content) return \"\";\n return content\n .replace(/[ \\t]+/g, \" \") // Replace multiple spaces/tabs with single space\n .replace(/[ \\t]*\\n[ \\t]*/g, \"\\n\") // Remove spaces around line breaks\n .replace(/^\\s+|\\s+$/g, \"\") // Trim leading and trailing whitespace\n .trim();\n}\nasync function binding(binding: Binding<string>): Promise<string> {\n if (typeof binding === \"function\") {\n const { body, node } = await toJS(binding);\n\n if (\n node?.type === \"Literal\" &&\n typeof (node as Literal).value === \"string\"\n ) {\n return `\\`${(node as Literal).value}\\``;\n }\n\n if (node?.type === \"TemplateLiteral\") {\n return body;\n }\n\n return `\\`\\$\\{${body}\\}\\``;\n }\n\n return `\\`${binding}\\``;\n}\n\nasync function formatGraphQLQuery(query: string): Promise<string> {\n if (!query || typeof query !== \"string\") {\n return query;\n }\n\n try {\n const formatted = await format(query, {\n parser: \"graphql\",\n printWidth: 80,\n tabWidth: 2,\n useTabs: false,\n });\n return formatted.trim();\n } catch (error) {\n // if prettier fails to format, return the original query\n return query;\n }\n}\n\nexport async function bindingSql(binding: Binding<string>): Promise<string> {\n if (typeof binding === \"function\") {\n const ret = await toJSBody(binding as (state: State) => string, {\n condense: false,\n });\n const { body, iife, node } = ret;\n\n if (\n node?.type === \"Literal\" &&\n typeof (node as Literal).value === \"string\"\n ) {\n const escapedValue = (node as Literal).value as string;\n // Escape backticks in the SQL string\n const escaped = escapedValue.replace(/`/g, \"\\\\`\");\n return `\\`${trimSqlSpaces(escaped)}\\``;\n }\n\n if (node?.type === \"TemplateLiteral\") {\n const trimmedBody = trimSqlSpaces(body);\n return iife ? `(() => ${trimmedBody})()` : trimmedBody;\n }\n\n let finalBody = body;\n\n if (iife) {\n finalBody = `(() => ${body})()`;\n }\n\n finalBody = trimSqlSpaces(finalBody);\n\n // Special handling for template literals - trim content within backticks\n finalBody = finalBody.replace(/`([^`]*)`/g, (_match, content) => {\n const trimmedContent = trimSqlSpaces(content);\n return `\\`${trimmedContent}\\``;\n });\n\n return `\\`\\$\\{${finalBody}\\}\\``;\n }\n\n const trimmedBinding = trimSqlSpaces(binding);\n // Escape backticks in the SQL string\n const escaped = trimmedBinding.replace(/`/g, \"\\\\`\");\n return `\\`${escaped}\\``;\n}\n\nexport async function bindingGraphQL(\n binding: Binding<string>,\n): Promise<string> {\n if (typeof binding === \"function\") {\n const ret = await toJSBody(binding as (state: State) => string, {\n condense: false,\n });\n const { body, iife, node } = ret;\n\n if (\n node?.type === \"Literal\" &&\n typeof (node as Literal).value === \"string\"\n ) {\n const formatted = await formatGraphQLQuery(\n (node as Literal).value as string,\n );\n return `\\`${formatted}\\``;\n }\n\n if (node?.type === \"TemplateLiteral\") {\n return iife ? `(() => ${body})()` : body;\n }\n\n let finalBody = body;\n\n if (iife) {\n finalBody = `(() => ${body})()`;\n }\n\n return `\\`\\$\\{${finalBody}\\}\\``;\n }\n\n const formatted = await formatGraphQLQuery(binding);\n return `\\`${formatted}\\``;\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 if (\"break\" in json) {\n return Break.fromJSON(json, entities);\n }\n\n throw new Error(\"Unknown 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 private static integrationRegistry: Record<string, any> = {};\n\n public static registerIntegration(key: string, integrationClass: any) {\n this.integrationRegistry[key] = integrationClass;\n }\n\n public static fromJSON(json: any, entities: string[]): Block {\n if (\"restapi\" in json?.step || \"restapiintegration\" in json?.step) {\n return RestApi.fromJSON(json, entities);\n }\n\n for (const [key, IntegrationClass] of Object.entries(\n this.integrationRegistry,\n )) {\n if (key in json?.step) {\n return IntegrationClass.fromJSON(json, entities);\n }\n }\n\n console.error(\"Unknown integration\", json?.step);\n throw new Error(\"Unknown integration\");\n }\n}\n\nexport class Python extends Integration {\n private fn: string;\n\n constructor(\n name: string,\n config: {\n fn: string;\n },\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 .body,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new JavaScript(\"${this.name}\", { fn: ${signatureV2((await toJSBody(this.fn)).body, 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\nexport class Athena extends Integration {\n private sqlBody: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n sqlBody: Binding<string>;\n },\n ) {\n super(name, integration);\n this.sqlBody = config.sqlBody;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n athena: {\n runSql: {\n sqlBody: await bindingSql(this.sqlBody),\n useParameterized: true,\n },\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Athena(\"${this.name}\", \"${this.integration}\", { sqlBody: \"${this.sqlBody}\" })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Athena {\n return new Athena(json?.name, json?.step?.integration, {\n sqlBody: fromBinding(json?.step?.athena?.runSql?.sqlBody, entities),\n });\n }\n}\n\nexport class BigQuery extends Integration {\n private sqlBody: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n sqlBody: Binding<string>;\n },\n ) {\n super(name, integration);\n this.sqlBody = config.sqlBody;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n bigquery: {\n body: await bindingSql(this.sqlBody),\n usePreparedSql: true,\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new BigQuery(\"${this.name}\", \"${this.integration}\", { sqlBody: \"${this.sqlBody}\" })`;\n }\n\n public static fromJSON(json: any, entities: string[]): BigQuery {\n return new BigQuery(json?.name, json?.step?.integration, {\n sqlBody: fromBinding(json?.step?.bigquery?.body, entities),\n });\n }\n}\n\ntype DynamoDbAction =\n | \"getItem\"\n | \"updateItem\"\n | \"putItem\"\n | \"batchWriteItem\"\n | \"deleteItem\"\n | \"query\"\n | \"scan\"\n | \"executeStatement\"\n | \"executeTransaction\"\n | \"listTagsOfResource\"\n | \"tagResource\"\n | \"listTables\"\n | \"describeTable\"\n | \"createTable\"\n | \"updateTable\"\n | \"deleteTable\";\n\nexport class DynamoDb extends Integration {\n private action: DynamoDbAction;\n private paramsJson: Binding<string>;\n\n constructor(\n name: string,\n integration: string,\n config: {\n action: DynamoDbAction;\n paramsJson: Binding<string>;\n },\n ) {\n super(name, integration);\n this.action = config.action;\n this.paramsJson = config.paramsJson;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n dynamodb: {\n action: this.action,\n body: await binding(this.paramsJson),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new DynamoDb(\"${this.name}\", \"${this.integration}\", { action: \"${this.action}\", paramsJson: \"${this.paramsJson}\" })`;\n }\n\n public static fromJSON(json: any, entities: string[]): DynamoDb {\n return new DynamoDb(json?.name, json?.step?.integration, {\n action: json?.step?.dynamodb?.action,\n paramsJson: fromBinding(json?.step?.dynamodb?.body, entities),\n });\n }\n}\n\ntype S3Action =\n | \"LIST_OBJECTS\"\n | \"LIST_BUCKET_OBJECTS\"\n | \"GET_OBJECT\"\n | \"DELETE_OBJECT\"\n | \"UPLOAD_OBJECT\"\n | \"LIST_BUCKETS\"\n | \"CREATE_BUCKET\"\n | \"UPLOAD_MULTIPLE_OBJECTS\"\n | \"GENERATE_PRESIGNED_URL\";\n\nexport class S3 extends Integration {\n private action: S3Action;\n private resource?: Binding<string>;\n private path?: Binding<string>;\n private body?: Binding<string>;\n private fileObjects?: Binding<string>;\n private listFilesConfig?: {\n prefix?: Binding<string>;\n delimiter?: Binding<string>;\n };\n\n constructor(\n name: string,\n integration: string,\n config: {\n action: S3Action;\n resource?: Binding<string>;\n path?: Binding<string>;\n body?: Binding<string>;\n fileObjects?: Binding<string>;\n listFilesConfig?: {\n prefix?: Binding<string>;\n delimiter?: Binding<string>;\n };\n },\n ) {\n super(name, integration);\n this.action = config.action;\n this.resource = config.resource;\n this.path = config.path;\n this.body = config.body;\n this.fileObjects = config.fileObjects;\n this.listFilesConfig = config.listFilesConfig;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n s3: {\n action: this.action,\n ...(this.resource ? { resource: await binding(this.resource) } : {}),\n ...(this.path ? { path: await binding(this.path) } : {}),\n ...(this.body ? { body: await binding(this.body) } : {}),\n ...(this.fileObjects\n ? { fileObjects: await binding(this.fileObjects) }\n : {}),\n ...(this.listFilesConfig\n ? {\n listFilesConfig: {\n ...(this.listFilesConfig.prefix\n ? { prefix: await binding(this.listFilesConfig.prefix) }\n : {}),\n ...(this.listFilesConfig.delimiter\n ? {\n delimiter: await binding(\n this.listFilesConfig.delimiter,\n ),\n }\n : {}),\n },\n }\n : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [`action: \"${this.action}\"`];\n\n if (this.resource) {\n parts.push(\n `resource: ${\n typeof this.resource === \"function\"\n ? signatureV2((await toJSBody(this.resource)).body, entities)\n : `\"${this.resource}\"`\n }`,\n );\n }\n\n if (this.path) {\n parts.push(\n `path: ${\n typeof this.path === \"function\"\n ? signatureV2((await toJSBody(this.path)).body, entities)\n : `\"${this.path}\"`\n }`,\n );\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === \"function\"\n ? signatureV2((await toJSBody(this.body)).body, entities)\n : `\"${this.body}\"`\n }`,\n );\n }\n\n if (this.fileObjects) {\n parts.push(\n `fileObjects: ${\n typeof this.fileObjects === \"function\"\n ? signatureV2((await toJSBody(this.fileObjects)).body, entities)\n : `\"${this.fileObjects}\"`\n }`,\n );\n }\n\n if (this.listFilesConfig) {\n const configParts: string[] = [];\n if (this.listFilesConfig.prefix) {\n configParts.push(\n `prefix: ${\n typeof this.listFilesConfig.prefix === \"function\"\n ? signatureV2(\n (await toJSBody(this.listFilesConfig.prefix)).body,\n entities,\n )\n : `\"${this.listFilesConfig.prefix}\"`\n }`,\n );\n }\n if (this.listFilesConfig.delimiter) {\n configParts.push(\n `delimiter: ${\n typeof this.listFilesConfig.delimiter === \"function\"\n ? signatureV2(\n (await toJSBody(this.listFilesConfig.delimiter)).body,\n entities,\n )\n : `\"${this.listFilesConfig.delimiter}\"`\n }`,\n );\n }\n if (configParts.length > 0) {\n parts.push(`listFilesConfig: { ${configParts.join(\", \")} }`);\n }\n }\n\n return `new S3(\"${this.name}\", \"${this.integration}\", { ${parts.join(\", \")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): S3 {\n return new S3(json?.name, json?.step?.integration, {\n action: json?.step?.s3?.action,\n resource: json?.step?.s3?.resource\n ? fromBinding(json?.step?.s3?.resource, entities)\n : undefined,\n path: json?.step?.s3?.path\n ? fromBinding(json?.step?.s3?.path, entities)\n : undefined,\n body: json?.step?.s3?.body\n ? fromBinding(json?.step?.s3?.body, entities)\n : undefined,\n fileObjects: json?.step?.s3?.fileObjects\n ? fromBinding(json?.step?.s3?.fileObjects, entities)\n : undefined,\n listFilesConfig: json?.step?.s3?.listFilesConfig\n ? {\n prefix: json?.step?.s3?.listFilesConfig?.prefix\n ? fromBinding(json?.step?.s3?.listFilesConfig?.prefix, entities)\n : undefined,\n delimiter: json?.step?.s3?.listFilesConfig?.delimiter\n ? fromBinding(\n json?.step?.s3?.listFilesConfig?.delimiter,\n entities,\n )\n : undefined,\n }\n : undefined,\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 bindingSql(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, { condense: false })).body, 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 bindingSql(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, { condense: false })).body, 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 Redshift 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 redshift: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Redshift(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement, { condense: false })).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Redshift {\n return new Redshift(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.redshift?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class MicrosoftSql 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 mssql: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new MicrosoftSql(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement)).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): MicrosoftSql {\n return new MicrosoftSql(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.mssql?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class MariaDB 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 mariadb: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n useAdvancedMatching: \"auto\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new MariaDB(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement, { condense: false })).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): MariaDB {\n return new MariaDB(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.mariadb?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class MySQL 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 mysql: {\n body: await bindingSql(this.statement),\n usePreparedSql: true,\n operation: \"run_sql\",\n useAdvancedMatching: \"auto\",\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new MySQL(\"${this.name}\", \"${this.integration}\", { statement: ${typeof this.statement === \"function\" ? signatureV2((await toJSBody(this.statement, { condense: false })).body, entities) : `\"${this.statement}\"`} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): MySQL {\n return new MySQL(json?.name, json?.step?.integration, {\n statement: fromBinding(\n json?.step?.mysql?.body as string | undefined,\n entities,\n ),\n });\n }\n}\n\nexport class GraphQL extends Integration {\n private body: Binding<string>;\n private variables?: Binding<string>;\n private headers?: { key: Binding<string>; value: Binding<string> }[];\n\n constructor(\n name: string,\n integration: string,\n config: {\n query: Binding<string>;\n variables?: Binding<string>;\n headers?: { key: Binding<string>; value: Binding<string> }[];\n },\n ) {\n super(name, integration);\n\n this.body = config.query;\n this.variables = config.variables;\n this.headers = config.headers;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n step: {\n integration: this.integration,\n graphqlintegration: {\n body: await bindingGraphQL(this.body),\n ...(this.variables\n ? {\n custom: {\n variables: {\n value: await binding(this.variables),\n },\n },\n }\n : {}),\n ...(this.headers && Array.isArray(this.headers)\n ? {\n headers: await Promise.all(\n this.headers.map(async (header) => ({\n key: await binding(header.key),\n value: await binding(header.value),\n })),\n ),\n }\n : {}),\n },\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const parts: string[] = [\n `query: ${typeof this.body === \"function\" ? signatureV2((await toJSBody(this.body)).body, entities) : `\"${this.body}\"`}`,\n ];\n\n if (this.variables) {\n parts.push(\n `variables: ${typeof this.variables === \"function\" ? signatureV2((await toJSBody(this.variables)).body, entities) : `\"${this.variables}\"`}`,\n );\n }\n\n if (this.headers) {\n const headers = (\n await Promise.all(\n this.headers.map(\n async (h) =>\n `{ key: ${\n typeof h.key === \"function\"\n ? signatureV2((await toJSBody(h.key)).body, entities)\n : `\"${h.key}\"`\n }, value: ${\n typeof h.value === \"function\"\n ? signatureV2((await toJSBody(h.value)).body, entities)\n : `\"${h.value}\"`\n } }`,\n ),\n )\n ).join(\", \");\n parts.push(`headers: [${headers}]`);\n }\n\n return `new GraphQL(\"${this.name}\", \"${this.integration}\", { ${parts.join(\", \")} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): GraphQL {\n const graphql = json?.step?.graphqlintegration;\n\n return new GraphQL(json?.name, json?.step?.integration, {\n query: fromBinding(graphql?.body, entities),\n variables: graphql?.custom?.variables?.value\n ? fromBinding(graphql?.custom?.variables?.value, entities)\n : undefined,\n headers: graphql?.headers?.map((header: any) => ({\n key: fromBinding(header.key, entities),\n value: fromBinding(header.value, 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 private openapi?: {\n path: string;\n };\n\n protected type: string;\n\n constructor(\n name: string,\n integration: string = \"restapi\",\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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration);\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 this.openapi = openapi;\n this.type = this.isIntegration() ? \"restapiintegration\" : \"restapi\";\n }\n\n public async toJSON(): Promise<JsonValue> {\n const openApiAction = (): string => {\n if (!this.isIntegration()) {\n return undefined;\n }\n\n if (this.openapi?.path) {\n let path: string = this.openapi.path.trim();\n\n if (path.startsWith(\"`\") && path.endsWith(\"`\")) {\n path = path.slice(1, -1);\n }\n\n return `${this.method} ${path}`;\n }\n\n return \"genericHttpRequest\";\n };\n\n const method = this.method?.toString().toUpperCase();\n const supportedMethods = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"DELETE\",\n \"PATCH\",\n \"HEAD\",\n \"OPTIONS\",\n ];\n\n return {\n name: this.name,\n step: {\n integration: this.integration,\n [this.type]: {\n httpMethod: supportedMethods.includes(method) ? method : \"GET\",\n openApiAction: openApiAction(),\n ...(this.url\n ? {\n [this.isIntegration() ? \"urlPath\" : \"path\"]: await binding(\n this.url,\n ),\n }\n : {}),\n ...(this.headers && Array.isArray(this.headers)\n ? {\n headers: await Promise.all(\n this.headers.map(async (header) => ({\n key: await binding(header.key),\n value: await binding(header.value),\n })),\n ),\n }\n : {}),\n ...(this.params && Array.isArray(this.params)\n ? {\n params: await Promise.all(\n this.params.map(async (param) => ({\n key: await binding(param.key),\n value: await binding(param.value),\n })),\n ),\n }\n : {}),\n ...(this.body ? { body: await binding(this.body) } : {}),\n\n // Other params that I might need to add.\n responseType: \"auto\",\n bodyType: \"jsonBody\",\n },\n },\n };\n }\n\n private isIntegration(): boolean {\n return this.integration !== \"restapi\";\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new RestApi(${await this.constructorParametersString(entities)})`;\n }\n\n protected async constructorParametersString(\n entities: string[],\n ): 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)).body, entities)\n : `\"${this.url}\"`\n }`,\n );\n }\n\n if (this.headers) {\n const headers = (\n await Promise.all(\n this.headers.map(\n async (h) =>\n `{ key: ${\n typeof h.key === \"function\"\n ? signatureV2((await toJSBody(h.key)).body, entities)\n : `\"${h.key}\"`\n }, value: ${\n typeof h.value === \"function\"\n ? signatureV2((await toJSBody(h.value)).body, entities)\n : `\"${h.value}\"`\n } }`,\n ),\n )\n ).join(\", \");\n parts.push(`headers: [${headers}]`);\n }\n\n if (this.params) {\n const params = (\n await Promise.all(\n this.params.map(\n async (p) =>\n `{ key: ${\n typeof p.key === \"function\"\n ? signatureV2((await toJSBody(p.key)).body, entities)\n : `\"${p.key}\"`\n }, value: ${\n typeof p.value === \"function\"\n ? signatureV2((await toJSBody(p.value)).body, entities)\n : `\"${p.value}\"`\n } }`,\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)).body, entities)\n : JSON.stringify(this.body)\n }`,\n );\n }\n\n return `\"${this.name}\", \"${this.integration}\", { ${parts.join(\", \")} }, ${JSON.stringify(this.openapi)}`;\n }\n\n public static fromJSON(json: any, entities: string[]): RestApi {\n const config =\n json?.step?.[\n json?.step?.integration === \"restapi\" ? \"restapi\" : \"restapiintegration\"\n ];\n\n if (json?.step?.integration === \"restapiintegration\") {\n return new RestApi(\n json?.name,\n json?.step?.integration,\n OpenApi.configFromJSON(config, entities),\n OpenApi.openapiFromJSON(config),\n );\n }\n\n return new RestApi(\n json?.name,\n json?.step?.integration,\n {\n method: config?.httpMethod,\n url: fromBinding(config?.path, entities),\n headers: config?.headers?.map((header: any) => ({\n key: fromBinding(header.key, entities),\n value: fromBinding(header.value, entities),\n })),\n params: config?.params?.map((param: any) => ({\n key: fromBinding(param.key, entities),\n value: fromBinding(param.value, entities),\n })),\n body: fromBinding(config?.body, entities),\n },\n OpenApi.openapiFromJSON(config),\n );\n }\n}\n\ntype SalesforceAction =\n | { action: \"SOQL_ACTION_SOQL\"; soqlBody: Binding<string> }\n | {\n action: \"CRUD_ACTION_READ\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_CREATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_UPDATE\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"CRUD_ACTION_DELETE\";\n resourceType: Binding<string>;\n resourceId: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"BULK_ACTION_CREATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n }\n | {\n action: \"BULK_ACTION_UPDATE\";\n resourceType: Binding<string>;\n resourceBody: Binding<string>;\n };\n\nexport class Salesforce extends Integration {\n private action: SalesforceAction;\n\n constructor(\n name: string,\n integration: string,\n config: {\n action: SalesforceAction;\n },\n ) {\n super(name, integration);\n this.action = config.action;\n }\n\n public async toJSON(): Promise<JsonValue> {\n let salesforce;\n switch (this.action.action) {\n case \"SOQL_ACTION_SOQL\":\n salesforce = {\n soql: {\n action: this.action.action,\n sqlBody: await binding(this.action.soqlBody),\n },\n };\n break;\n\n case \"CRUD_ACTION_READ\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceId: await binding(this.action.resourceId),\n },\n };\n break;\n\n case \"CRUD_ACTION_CREATE\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"CRUD_ACTION_UPDATE\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceId: await binding(this.action.resourceId),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"CRUD_ACTION_DELETE\":\n salesforce = {\n crud: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceId: await binding(this.action.resourceId),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"BULK_ACTION_CREATE\":\n salesforce = {\n bulk: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n\n case \"BULK_ACTION_UPDATE\":\n salesforce = {\n bulk: {\n action: this.action.action,\n resourceType: await binding(this.action.resourceType),\n resourceBody: await binding(this.action.resourceBody),\n },\n };\n break;\n }\n return {\n name: this.name,\n step: {\n integration: this.integration,\n salesforce,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n switch (this.action.action) {\n case \"SOQL_ACTION_SOQL\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"SOQL_ACTION_SOQL\", soqlBody: ${typeof this.action.soqlBody === \"function\" ? signatureV2((await toJSBody(this.action.soqlBody, { condense: false })).body, entities) : `\"${this.action.soqlBody}\"`} } })`;\n\n case \"CRUD_ACTION_READ\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_READ\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceId: ${typeof this.action.resourceId === \"function\" ? signatureV2((await toJSBody(this.action.resourceId, { condense: false })).body, entities) : `\"${this.action.resourceId}\"`} } })`;\n\n case \"CRUD_ACTION_CREATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_CREATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"CRUD_ACTION_UPDATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_UPDATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceId: ${typeof this.action.resourceId === \"function\" ? signatureV2((await toJSBody(this.action.resourceId, { condense: false })).body, entities) : `\"${this.action.resourceId}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"CRUD_ACTION_DELETE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"CRUD_ACTION_DELETE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceId: ${typeof this.action.resourceId === \"function\" ? signatureV2((await toJSBody(this.action.resourceId, { condense: false })).body, entities) : `\"${this.action.resourceId}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"BULK_ACTION_CREATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"BULK_ACTION_CREATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n\n case \"BULK_ACTION_UPDATE\":\n return `new Salesforce(\"${this.name}\", \"${this.integration}\", { action: { action: \"BULK_ACTION_UPDATE\", resourceType: ${typeof this.action.resourceType === \"function\" ? signatureV2((await toJSBody(this.action.resourceType, { condense: false })).body, entities) : `\"${this.action.resourceType}\"`}, resourceBody: ${typeof this.action.resourceBody === \"function\" ? signatureV2((await toJSBody(this.action.resourceBody, { condense: false })).body, entities) : `\"${this.action.resourceBody}\"`} } })`;\n }\n }\n\n public static fromJSON(json: any, entities: string[]): Salesforce {\n // NOTE: @joeyagreco - we use if statements instead of switch statements here since the json field is at different places (proto oneofs dont be the most annoying thing to work around challenge: impossible)\n if (json?.step?.salesforce?.soql?.action === \"SOQL_ACTION_SOQL\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"SOQL_ACTION_SOQL\",\n soqlBody: fromBinding(\n json?.step?.salesforce?.soql?.soqlBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_READ\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_READ\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceId: fromBinding(\n json?.step?.salesforce?.crud?.resourceId,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_CREATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_CREATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.crud?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_UPDATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_UPDATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceId: fromBinding(\n json?.step?.salesforce?.crud?.resourceId,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.crud?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.crud?.action === \"CRUD_ACTION_DELETE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"CRUD_ACTION_DELETE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.crud?.resourceType,\n entities,\n ),\n resourceId: fromBinding(\n json?.step?.salesforce?.crud?.resourceId,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.crud?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.bulk?.action === \"BULK_ACTION_CREATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"BULK_ACTION_CREATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.bulk?.resourceType,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.bulk?.resourceBody,\n entities,\n ),\n },\n });\n } else if (json?.step?.salesforce?.bulk?.action === \"BULK_ACTION_UPDATE\") {\n return new Salesforce(json?.name, json?.step?.integration, {\n action: {\n action: \"BULK_ACTION_UPDATE\",\n resourceType: fromBinding(\n json?.step?.salesforce?.bulk?.resourceType,\n entities,\n ),\n resourceBody: fromBinding(\n json?.step?.salesforce?.bulk?.resourceBody,\n entities,\n ),\n },\n });\n }\n }\n}\n\nexport class OpenApi extends RestApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration, config, openapi);\n }\n\n public static configFromJSON(\n json: any,\n entities: string[],\n ): {\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 return {\n method: json?.httpMethod,\n url: fromBinding(json?.urlPath, entities),\n headers: json?.headers?.map((header: any) => ({\n key: fromBinding(header.key, entities),\n value: fromBinding(header.value, entities),\n })),\n params: json?.params?.map((param: any) => ({\n key: fromBinding(param.key, entities),\n value: fromBinding(param.value, entities),\n })),\n body: fromBinding(json?.body, entities),\n };\n }\n\n public static openapiFromJSON(json: any): {\n path: string;\n } {\n return json?.openApiAction &&\n json.openApiAction !== \"\" &&\n json.openApiAction !== \"genericHttpRequest\"\n ? { path: json.openApiAction.split(\" \")[1] }\n : undefined;\n }\n}\n\nexport class Jira extends OpenApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration, config, openapi);\n this.type = \"jira\";\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Jira(${await this.constructorParametersString(entities)})`;\n }\n\n public static fromJSON(json: any, entities: string[]): Jira {\n return new Jira(\n json?.name,\n json?.step?.integration,\n OpenApi.configFromJSON(json?.step?.jira, entities),\n OpenApi.openapiFromJSON(json?.step?.jira),\n );\n }\n}\n\nfunction createOpenApiIntegrationClass(\n className: string,\n integrationName: string,\n) {\n return class extends OpenApi {\n constructor(\n name: string,\n integration: 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 openapi?: {\n path: string;\n },\n ) {\n super(name, integration, config, openapi);\n this.type = integrationName;\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new ${className}(${await this.constructorParametersString(entities)})`;\n }\n\n public static fromJSON(json: any, entities: string[]) {\n return new this(\n json?.name,\n json?.step?.integration,\n OpenApi.configFromJSON(json?.step?.[integrationName], entities),\n OpenApi.openapiFromJSON(json?.step?.[integrationName]),\n );\n }\n };\n}\n\n// All of the openapi integrations should go here\nexport const Airtable = createOpenApiIntegrationClass(\"Airtable\", \"airtable\");\nexport const Anthropic = createOpenApiIntegrationClass(\n \"Anthropic\",\n \"anthropic\",\n);\nexport const Asana = createOpenApiIntegrationClass(\"Asana\", \"asana\");\nexport const Bitbucket = createOpenApiIntegrationClass(\n \"Bitbucket\",\n \"bitbucket\",\n);\nexport const Box = createOpenApiIntegrationClass(\"Box\", \"box\");\nexport const CircleCI = createOpenApiIntegrationClass(\"CircleCI\", \"circleci\");\nexport const Cohere = createOpenApiIntegrationClass(\"Cohere\", \"cohere\");\nexport const Confluence = createOpenApiIntegrationClass(\n \"Confluence\",\n \"confluence\",\n);\nexport const Datadog = createOpenApiIntegrationClass(\"Datadog\", \"datadog\");\nexport const Dropbox = createOpenApiIntegrationClass(\"Dropbox\", \"dropbox\");\nexport const Elasticsearch = createOpenApiIntegrationClass(\n \"Elasticsearch\",\n \"elasticsearch\",\n);\nexport const Fireworks = createOpenApiIntegrationClass(\n \"Fireworks\",\n \"fireworks\",\n);\nexport const Front = createOpenApiIntegrationClass(\"Front\", \"front\");\nexport const Gemini = createOpenApiIntegrationClass(\"Gemini\", \"gemini\");\nexport const GitHub = createOpenApiIntegrationClass(\"GitHub\", \"github\");\nexport const GoogleAnalytics = createOpenApiIntegrationClass(\n \"GoogleAnalytics\",\n \"googleanalytics\",\n);\nexport const GoogleDrive = createOpenApiIntegrationClass(\n \"GoogleDrive\",\n \"googledrive\",\n);\nexport const Groq = createOpenApiIntegrationClass(\"Groq\", \"groq\");\nexport const HubSpot = createOpenApiIntegrationClass(\"HubSpot\", \"hubspot\");\nexport const Intercom = createOpenApiIntegrationClass(\"Intercom\", \"intercom\");\nexport const LaunchDarkly = createOpenApiIntegrationClass(\n \"LaunchDarkly\",\n \"launchdarkly\",\n);\nexport const Mistral = createOpenApiIntegrationClass(\"Mistral\", \"mistral\");\nexport const Notion = createOpenApiIntegrationClass(\"Notion\", \"notion\");\nexport const OpenAI = createOpenApiIntegrationClass(\"OpenAI\", \"openai_v2\");\nexport const PagerDuty = createOpenApiIntegrationClass(\n \"PagerDuty\",\n \"pagerduty\",\n);\nexport const Perplexity = createOpenApiIntegrationClass(\n \"Perplexity\",\n \"perplexity\",\n);\nexport const Segment = createOpenApiIntegrationClass(\"Segment\", \"segment\");\nexport const SendGrid = createOpenApiIntegrationClass(\"SendGrid\", \"sendgrid\");\nexport const Slack = createOpenApiIntegrationClass(\"Slack\", \"slack\");\nexport const StabilityAI = createOpenApiIntegrationClass(\n \"StabilityAI\",\n \"stabilityai\",\n);\nexport const Stripe = createOpenApiIntegrationClass(\"Stripe\", \"stripe\");\nexport const Twilio = createOpenApiIntegrationClass(\"Twilio\", \"twilio\");\nexport const Zendesk = createOpenApiIntegrationClass(\"Zendesk\", \"zendesk\");\nexport const Zoom = createOpenApiIntegrationClass(\"Zoom\", \"zoom\");\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\n ? { emailSubject: await binding(this.subject) }\n : {}),\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((await toJSBody(this.from)).body, entities)\n : `\"${this.from}\"`\n }`,\n );\n }\n\n if (this.to) {\n parts.push(\n `to: ${\n typeof this.to === \"function\"\n ? signatureV2((await toJSBody(this.to)).body, entities)\n : `\"${this.to}\"`\n }`,\n );\n }\n\n if (this.cc) {\n parts.push(\n `cc: ${\n typeof this.cc === \"function\"\n ? signatureV2((await toJSBody(this.cc)).body, entities)\n : `\"${this.cc}\"`\n }`,\n );\n }\n\n if (this.bcc) {\n parts.push(\n `bcc: ${\n typeof this.bcc === \"function\"\n ? signatureV2((await toJSBody(this.bcc)).body, entities)\n : `\"${this.bcc}\"`\n }`,\n );\n }\n\n if (this.subject) {\n parts.push(\n `subject: ${\n typeof this.subject === \"function\"\n ? signatureV2((await toJSBody(this.subject)).body, entities)\n : `\"${this.subject}\"`\n }`,\n );\n }\n\n if (this.body) {\n parts.push(\n `body: ${\n typeof this.body === \"function\"\n ? signatureV2((await toJSBody(this.body)).body, 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\n ? fromBinding(json?.step?.email?.emailCc, entities)\n : undefined,\n bcc: json?.step?.email?.emailBcc\n ? fromBinding(json?.step?.email?.emailBcc, entities)\n : 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 bindingSql(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, { condense: false })).body, 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(\n condition: Condition,\n entities: string[],\n): Promise<string> {\n return `{ when: ${typeof condition.when === \"function\" ? signatureV2((await toJSBody(condition.when)).body, 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: ensureIIFE(\n (await toJS<boolean>(this.conditions.if.when)).body,\n ),\n blocks: await Promise.all(\n this.conditions.if.then.map(async (block) => await block.toJSON()),\n ),\n },\n ...(await (async () =>\n this.conditions.elif\n ? {\n elseIf: await Promise.all(\n this.conditions.elif.map(async (condition) => ({\n condition: ensureIIFE(\n (await toJS<boolean>(condition.when)).body,\n ),\n blocks: await Promise.all(\n condition.then.map(async (block) => await block.toJSON()),\n ),\n })),\n ),\n }\n : { elseIf: [] })()),\n else: this.conditions.else\n ? {\n blocks: await Promise.all(\n this.conditions.else.map(async (block) => await block.toJSON()),\n ),\n }\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\n ? json?.conditional?.elseIf?.map((condition: any) => ({\n when: fromJS<boolean>(condition.condition, entities),\n then: condition.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n }))\n : [],\n else: json?.conditional?.else\n ? json?.conditional?.else?.blocks?.map((block: any) =>\n Block.fromJSON(block, entities),\n )\n : [],\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(\n this.blocks?.map(async (block) => await block.toJSON()),\n ),\n paths: ensureIIFE((await toJS<JsonValue[]>(this.over)).body),\n variables: this.variables,\n },\n wait: \"WAIT_ALL\",\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const variables = JSON.stringify(this.variables);\n const blocks = await Promise.all(\n this.blocks.map(async (block) => await block.toSDK(entities)),\n );\n return `new Parallel(\"${this.name}\", { over: ${typeof this.over === \"function\" ? signatureV2((await toJSBody(this.over)).body, entities) : this.over}, variables: ${variables}, blocks: ${blocks.length > 0 ? blocks : \"[]\"} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Parallel {\n return new Parallel(json?.name, {\n over: fromJS<JsonValue[]>(\n json?.parallel?.dynamic?.paths ?? \"''\",\n entities,\n ),\n variables: {\n item: json?.parallel?.dynamic?.variables?.item ?? \"\",\n },\n blocks:\n 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: ensureIIFE((await toJS<JsonValue[]>(this.over)).body),\n type: \"TYPE_FOREACH\",\n variables: this.variables,\n blocks: await Promise.all(\n this.blocks.map(async (block) => await block.toJSON()),\n ),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const variables = JSON.stringify(this.variables);\n const blocks = await Promise.all(\n this.blocks.map(async (block) => await block.toSDK(entities)),\n );\n return `new Loop(\"${this.name}\", { over: ${typeof this.over === \"function\" ? signatureV2((await toJSBody(this.over)).body, entities) : this.over}, variables: ${variables}, blocks: ${blocks.length > 0 ? blocks : \"[]\"} })`;\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(\n this.variables.map(async (variable) => {\n return {\n key: variable.key,\n value: ensureIIFE((await toJS<JsonValue[]>(variable.value)).body),\n type: \"TYPE_SIMPLE\",\n mode: \"MODE_READWRITE\",\n };\n }),\n ),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Variables(\"${this.name}\", [${(\n await Promise.all(\n this.variables?.map(\n async (variable) =>\n `{ key: \"${variable.key}\", value: ${typeof variable.value === \"function\" ? signatureV2((await toJSBody(variable.value)).body, entities) : variable.value} }`,\n ),\n )\n ).join(\",\")}])`;\n }\n\n public static fromJSON(json: any, entities: string[]): Variables {\n return new Variables(\n json?.name,\n json?.variables?.items?.map((variable: any) => ({\n key: variable.key,\n value: fromBinding(variable.value, entities),\n })),\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: {\n blocks: await Promise.all(\n this.try.map(async (block) => await block.toJSON()),\n ),\n },\n catch: {\n blocks: await Promise.all(\n this.catch.map(async (block) => await block.toJSON()),\n ),\n },\n finally: {\n blocks: this.finally\n ? await Promise.all(\n this.finally.map(async (block) => await block.toJSON()),\n )\n : undefined,\n },\n variables: this.variables,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const tryBlocks = await Promise.all(\n this.try.map(async (block) => await block.toSDK(entities)),\n );\n const catchBlocks = await Promise.all(\n this.catch.map(async (block) => await block.toSDK(entities)),\n );\n const finallyBlocks = this.finally?.map(\n async (block) => await block.toSDK(entities),\n );\n return `new TryCatch(\"${this.name}\", { try: [${tryBlocks.join(\",\")}], catch: [${catchBlocks.join(\",\")}], finally: [${finallyBlocks?.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) =>\n Block.fromJSON(block, entities),\n ),\n catch: json?.tryCatch?.catch.blocks.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\n finally: json?.tryCatch?.finally?.blocks?.map((block: any) =>\n Block.fromJSON(block, entities),\n ),\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)).body,\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Throw(\"${this.name}\", { error: ${typeof this.error === \"function\" ? signatureV2((await toJSBody(this.error)).body, entities) : ensureIIFE(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: ensureIIFE((await toJS<JsonValue>(this.data)).body),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const dataFn =\n typeof this.data === \"function\"\n ? signatureV2((await toJSBody(this.data)).body, entities)\n : ensureIIFE(JSON.stringify(this.data));\n return `new Return(\"${this.name}\", { data: ${dataFn} })`;\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 Break extends Block {\n private condition: Binding<JsonValue>;\n\n constructor(\n name: string,\n config: {\n condition: Binding<JsonValue>;\n },\n ) {\n super(name);\n\n this.condition = config.condition;\n }\n\n public async toJSON(): Promise<JsonValue> {\n return {\n name: this.name,\n break: {\n condition: ensureIIFE((await toJS<JsonValue[]>(this.condition)).body),\n },\n };\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n return `new Break(\"${this.name}\", { condition: ${typeof this.condition === \"function\" ? signatureV2((await toJSBody(this.condition)).body, entities) : ensureIIFE(JSON.stringify(this.condition))} })`;\n }\n\n public static fromJSON(json: any, entities: string[]): Break {\n return new Break(json?.name, {\n condition: fromJS(json?.break?.condition, entities),\n });\n }\n}\n\nexport type Authorization =\n | {\n type: \"AUTHORIZATION_TYPE_APP_USERS\";\n }\n | {\n type: \"AUTHORIZATION_TYPE_JS_EXPRESSION\";\n expression: Binding<boolean>;\n };\n\nexport class Api {\n private blocks: Block[];\n private name: string;\n private authorization?: Authorization;\n\n constructor(\n name: string,\n blocks: Block[] = [],\n authorization: Authorization = { type: \"AUTHORIZATION_TYPE_APP_USERS\" },\n ) {\n this.name = name;\n this.blocks = blocks;\n this.authorization = authorization;\n }\n\n public async toSDK(entities: string[]): Promise<string> {\n const imports =\n \"import { Api, JavaScript, Python, Athena, BigQuery, DynamoDb, MicrosoftSql, MySQL, PostgreSQL, Redshift, Snowflake, S3, Salesforce, RestApi, GraphQL, Databricks, Conditional, Parallel, Loop, TryCatch, Variables, Throw, Return, Break, Email, Airtable, Anthropic, Asana, Bitbucket, Box, CircleCI, Cohere, Datadog, Dropbox, Elasticsearch, Fireworks, Front, Gemini, GitHub, GoogleAnalytics, GoogleDrive, Groq, HubSpot, Intercom, Jira, LaunchDarkly, Mistral, Notion, OpenAI, PagerDuty, Perplexity, Segment, SendGrid, Slack, StabilityAI, Stripe, Twilio, Zendesk, Zoom, Confluence } 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(\",\")}], ${this.authorization.type === \"AUTHORIZATION_TYPE_JS_EXPRESSION\" ? `{ type: \"AUTHORIZATION_TYPE_JS_EXPRESSION\", expression: ${typeof this.authorization.expression === \"function\" ? signatureV2((await toJSBody(this.authorization.expression)).body, entities) : this.authorization.expression} }` : `{ type: \"AUTHORIZATION_TYPE_APP_USERS\" }`})`;\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 type: json.authorization.type,\n expression:\n json.authorization.type === \"AUTHORIZATION_TYPE_JS_EXPRESSION\"\n ? fromJS(json.authorization.expression, entities)\n : undefined,\n },\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 authorization: {\n type:\n | \"AUTHORIZATION_TYPE_APP_USERS\"\n | \"AUTHORIZATION_TYPE_JS_EXPRESSION\";\n expression?: string;\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 authorization: {\n type: this.authorization.type,\n ...{\n expression:\n this.authorization.type === \"AUTHORIZATION_TYPE_JS_EXPRESSION\"\n ? `(() => ${(await toJS<boolean>(this.authorization.expression)).body})()`\n : undefined,\n },\n },\n trigger: {\n application: {},\n },\n blocks: [],\n };\n\n api.blocks = await Promise.all(\n this.blocks.map(async (block) => await block.toJSON()),\n );\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\nexport function 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(\n value: string,\n entities: string[],\n): 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 try {\n const ast = parse(value, {\n ecmaVersion: \"latest\",\n sourceType: \"script\",\n });\n\n const identifiers = Array.from(extractIdentifiers(ast));\n\n return new Function(\n `{ ${identifiers.join(\", \")} }`,\n `return (${value})`,\n ) as (_: State) => string;\n } catch (e) {\n console.error(\n `We couldn't extract identifiers from the binding ${value}`,\n e,\n );\n return value;\n }\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>(\n value: (state: State) => T,\n node: Node,\n options: { condense?: boolean; block?: boolean } = {\n condense: true,\n block: true,\n },\n) {\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, \" \").trim();\n }\n\n return beautified;\n}\n\nfunction createAst(value: string): Program {\n if (value.startsWith(\"{\") && value.endsWith(\"}\")) {\n value = `(${value})`;\n }\n\n return parse(value, {\n ecmaVersion: \"latest\",\n sourceType: \"script\",\n preserveParens: false,\n });\n}\n\nexport async function toJSBody<T extends JsonValue>(\n value: (state: State) => T,\n options: { block?: boolean; condense?: boolean; function?: boolean } = {\n block: true,\n condense: true,\n function: false,\n },\n): Promise<{ body: string; iife: boolean; node?: Node }> {\n if (typeof value !== \"function\") {\n return {\n body: `\\`${JSON.stringify(value)}\\``,\n iife: true,\n };\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 = (\n (program as ExpressionStatement).expression as FunctionExpression\n ).body;\n\n if (body.type === \"BlockStatement\") {\n return {\n body: await beautifyAndOptionallyCondense(value, body, {\n ...options,\n block: options.block !== false, // Use the provided block option\n }),\n iife: true,\n node: body,\n };\n }\n\n let bodyText = safeBodyText(\n value.toString().slice(body.start, body.end),\n body,\n );\n if (options.condense) {\n bodyText = bodyText\n .replace(/\\s*\\n\\s*/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n }\n\n return {\n body: `${options.function ? \"return \" : \"\"}${bodyText}`,\n iife: options.function,\n node: body,\n };\n case \"FunctionDeclaration\":\n let contents = value\n .toString()\n .slice(program.body.start, program.body.end);\n\n if (program.body.type !== \"BlockStatement\") {\n return {\n body: contents,\n iife: false,\n node: program.body,\n };\n }\n\n if (\n !options.function &&\n program.body.body.length === 1 &&\n program.body.body[0].type === \"ReturnStatement\"\n ) {\n const argument = program.body.body[0].argument;\n if (!argument) {\n return {\n body: ``,\n iife: false,\n node: program.body.body[0],\n };\n }\n\n let bodyText = safeBodyText(\n value.toString().slice(argument.start, argument.end),\n argument,\n );\n\n return {\n body: bodyText,\n iife: false, // This should be false but we need to deal with the nested string template case.\n node: argument,\n };\n }\n\n return {\n body: await beautifyAndOptionallyCondense(value, program.body, options),\n iife: true,\n node: program.body,\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>(\n value: Binding<T>,\n): Promise<{ body: string; node?: Node }> {\n if (typeof value !== \"function\") {\n return {\n body: JSON.stringify(value),\n };\n }\n\n const { body, iife, node } = await toJSBody(value as (state: State) => T);\n\n if (iife) {\n return {\n body: `(() => ${body})()`,\n node,\n };\n }\n\n return { body, node };\n}\n\nexport function fromJS<T extends JsonValue>(\n value: string,\n entities: string[] = [],\n): Binding<T> {\n try {\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 if (value.length === 0) {\n return new Function(\"return \") as (_: State) => T;\n }\n\n let unaryOps: string[] = [];\n const ast = createAst(value);\n\n if (ast.body.length === 0) {\n return new Function(\"return \") as (_: State) => T;\n }\n\n let call = (ast.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 (\n _: State,\n ) => T;\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 const ast = createAst(value);\n\n const identifiers = Array.from(extractIdentifiers(ast));\n\n return new Function(\n `{ ${identifiers.join(\", \")} }`,\n `return (${value})`,\n ) as (_: State) => 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 } catch (e) {\n console.error(\"There was an error during parsing in fromJS\", e);\n // fallback to an empty function so we don't crash\n return new Function(\"return ''\") as (_: State) => T;\n }\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\nexport function ensureIIFE(value: string): string {\n // We write the IIFE so we can be loose with the fomratting here.\n // For example, we'd never get ( ( ) =>)().\n if (value.startsWith(\"(() => \") && value.endsWith(\")()\")) {\n return value;\n }\n\n let safeValue = value.trim();\n if (safeValue.startsWith(\"{\") && safeValue.endsWith(\"}\")) {\n safeValue = `(${safeValue})`;\n }\n\n return `(() => ${safeValue})()`;\n}\n\n/**\n * Extracts identifier names from an AST by walking the tree.\n */\nfunction extractIdentifiers(\n node: Node,\n identifiers: Set<string> = new Set(),\n): Set<string> {\n if (!node) {\n return identifiers;\n }\n\n // we only care about the root of the expression, so we gotta unwind the subtree\n if (node.type === \"MemberExpression\") {\n const memberExpr = node as any;\n extractIdentifiers(memberExpr.object, identifiers);\n return identifiers;\n }\n\n if (node.type === \"Identifier\") {\n identifiers.add((node as any).name);\n }\n\n for (const key in node) {\n const value = (node as any)[key];\n\n if (value && typeof value === \"object\") {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === \"object\" && item.type) {\n extractIdentifiers(item, identifiers);\n }\n }\n } else if (value.type) {\n extractIdentifiers(value, identifiers);\n }\n }\n }\n\n return identifiers;\n}\n\nfunction safeBodyText(body: string, node: Node): string {\n if (node.type === \"ObjectExpression\") {\n return `(${body})`;\n }\n return body;\n}\n\n// All of the integrations (openapi and not) should be registered\n// NOTE: @joeyagreco - when adding support for an integration here, make sure to update:\n// NOTE: @joeyagreco - 1. to-sdk-transformer.ts\n// NOTE: @joeyagreco - 2. context-util.ts\n// NOTE: @joeyagreco - 3. the import statement in Api.toSDK()\n// NOTE: @joeyagreco - 4. superblocks-api.md\nIntegration.registerIntegration(\"airtable\", Airtable);\nIntegration.registerIntegration(\"athena\", Athena);\nIntegration.registerIntegration(\"anthropic\", Anthropic);\nIntegration.registerIntegration(\"asana\", Asana);\nIntegration.registerIntegration(\"bigquery\", BigQuery);\nIntegration.registerIntegration(\"bitbucket\", Bitbucket);\nIntegration.registerIntegration(\"box\", Box);\nIntegration.registerIntegration(\"circleci\", CircleCI);\nIntegration.registerIntegration(\"cohere\", Cohere);\nIntegration.registerIntegration(\"confluence\", Confluence);\nIntegration.registerIntegration(\"databricks\", Databricks);\nIntegration.registerIntegration(\"datadog\", Datadog);\nIntegration.registerIntegration(\"dropbox\", Dropbox);\nIntegration.registerIntegration(\"dynamodb\", DynamoDb);\nIntegration.registerIntegration(\"elasticsearch\", Elasticsearch);\nIntegration.registerIntegration(\"email\", Email);\nIntegration.registerIntegration(\"fireworks\", Fireworks);\nIntegration.registerIntegration(\"front\", Front);\nIntegration.registerIntegration(\"gemini\", Gemini);\nIntegration.registerIntegration(\"github\", GitHub);\nIntegration.registerIntegration(\"googleanalytics\", GoogleAnalytics);\nIntegration.registerIntegration(\"googledrive\", GoogleDrive);\nIntegration.registerIntegration(\"graphqlintegration\", GraphQL);\nIntegration.registerIntegration(\"groq\", Groq);\nIntegration.registerIntegration(\"hubspot\", HubSpot);\nIntegration.registerIntegration(\"intercom\", Intercom);\nIntegration.registerIntegration(\"javascript\", JavaScript);\nIntegration.registerIntegration(\"jira\", Jira);\nIntegration.registerIntegration(\"launchdarkly\", LaunchDarkly);\nIntegration.registerIntegration(\"mistral\", Mistral);\nIntegration.registerIntegration(\"notion\", Notion);\nIntegration.registerIntegration(\"pagerduty\", PagerDuty);\nIntegration.registerIntegration(\"perplexity\", Perplexity);\nIntegration.registerIntegration(\"postgres\", PostgreSQL);\nIntegration.registerIntegration(\"mssql\", MicrosoftSql);\nIntegration.registerIntegration(\"mariadb\", MariaDB);\nIntegration.registerIntegration(\"mysql\", MySQL);\nIntegration.registerIntegration(\"python\", Python);\nIntegration.registerIntegration(\"redshift\", Redshift);\nIntegration.registerIntegration(\"s3\", S3);\nIntegration.registerIntegration(\"salesforce\", Salesforce);\nIntegration.registerIntegration(\"segment\", Segment);\nIntegration.registerIntegration(\"sendgrid\", SendGrid);\nIntegration.registerIntegration(\"slack\", Slack);\nIntegration.registerIntegration(\"snowflake\", Snowflake);\nIntegration.registerIntegration(\"stabilityai\", StabilityAI);\nIntegration.registerIntegration(\"stripe\", Stripe);\nIntegration.registerIntegration(\"twilio\", Twilio);\nIntegration.registerIntegration(\"zendesk\", Zendesk);\nIntegration.registerIntegration(\"zoom\", Zoom);\n",
|
|
11
11
|
"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",
|
|
12
12
|
"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 \"isolatedModules\": true,\n \"skipLibCheck\": true,\n \"types\": [\"node\"],\n \"paths\": {\n \"@superblocksteam/library\": [\"src/superblocks-library-shim\"]\n }\n },\n \"include\": [\"src\"],\n \"exclude\": [\"node_modules\", \"dist\", \"fixtures\"]\n}\n"
|
|
13
13
|
}
|