d25d482dc2
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
121 lines
3.9 KiB
TypeScript
Executable File
121 lines
3.9 KiB
TypeScript
Executable File
#!/usr/bin/env bun
|
|
|
|
/**
|
|
* Export workflow JSON from database
|
|
*
|
|
* Usage:
|
|
* bun apps/sim/scripts/export-workflow.ts <workflow-id>
|
|
*
|
|
* This script exports a workflow in the same format as the export API route.
|
|
* It fetches the workflow state from normalized tables, combines it with metadata
|
|
* and variables, sanitizes it, and outputs the JSON.
|
|
*
|
|
* Make sure DATABASE_URL or POSTGRES_URL is set in your environment.
|
|
*/
|
|
|
|
// Suppress console logs from imported modules - only JSON should go to stdout
|
|
const originalConsole = {
|
|
log: console.log,
|
|
warn: console.warn,
|
|
error: console.error,
|
|
}
|
|
console.log = () => {}
|
|
console.warn = () => {}
|
|
console.error = () => {}
|
|
|
|
import { writeFileSync } from 'fs'
|
|
import { eq } from 'drizzle-orm'
|
|
import { db } from '../../../packages/db/db.js'
|
|
import { workflow } from '../../../packages/db/schema.js'
|
|
import { loadWorkflowFromNormalizedTables } from '../lib/workflows/persistence/utils.js'
|
|
import { sanitizeForExport } from '../lib/workflows/sanitization/json-sanitizer.js'
|
|
|
|
// ---------- CLI argument parsing ----------
|
|
const args = process.argv.slice(2)
|
|
const workflowId = args[0]
|
|
const outputFile = args[1] // Optional output filename
|
|
|
|
if (!workflowId) {
|
|
process.stderr.write(
|
|
'Usage: bun apps/sim/scripts/export-workflow.ts <workflow-id> [output-file]\n'
|
|
)
|
|
process.stderr.write('\n')
|
|
process.stderr.write('Examples:\n')
|
|
process.stderr.write(' bun apps/sim/scripts/export-workflow.ts abc123\n')
|
|
process.stderr.write(' bun apps/sim/scripts/export-workflow.ts abc123 workflow.json\n')
|
|
process.stderr.write('\n')
|
|
process.stderr.write('Make sure DATABASE_URL or POSTGRES_URL is set in your environment.\n')
|
|
process.exit(1)
|
|
}
|
|
|
|
// ---------- Main export function ----------
|
|
async function exportWorkflow(workflowId: string, outputFile?: string): Promise<void> {
|
|
try {
|
|
// Fetch workflow metadata
|
|
const [workflowData] = await db
|
|
.select()
|
|
.from(workflow)
|
|
.where(eq(workflow.id, workflowId))
|
|
.limit(1)
|
|
|
|
if (!workflowData) {
|
|
process.stderr.write(`Error: Workflow ${workflowId} not found\n`)
|
|
process.exit(1)
|
|
}
|
|
|
|
// Load workflow from normalized tables
|
|
const normalizedData = await loadWorkflowFromNormalizedTables(workflowId)
|
|
|
|
if (!normalizedData) {
|
|
process.stderr.write(`Error: Workflow ${workflowId} has no normalized data\n`)
|
|
process.exit(1)
|
|
}
|
|
|
|
// Get variables in Record format (as stored in database)
|
|
type VariableType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'plain'
|
|
const workflowVariables = workflowData.variables as
|
|
| Record<string, { id: string; name: string; type: VariableType; value: unknown }>
|
|
| undefined
|
|
|
|
// Prepare export state - match the exact format from the UI
|
|
const workflowState = {
|
|
blocks: normalizedData.blocks,
|
|
edges: normalizedData.edges,
|
|
loops: normalizedData.loops,
|
|
parallels: normalizedData.parallels,
|
|
metadata: {
|
|
name: workflowData.name,
|
|
description: workflowData.description ?? undefined,
|
|
exportedAt: new Date().toISOString(),
|
|
},
|
|
variables: workflowVariables,
|
|
}
|
|
|
|
// Sanitize and export - this returns { version, exportedAt, state }
|
|
const exportState = sanitizeForExport(workflowState)
|
|
const jsonString = JSON.stringify(exportState, null, 2)
|
|
|
|
// Write to file or stdout
|
|
if (outputFile) {
|
|
writeFileSync(outputFile, jsonString, 'utf-8')
|
|
process.stderr.write(`Workflow exported to ${outputFile}\n`)
|
|
} else {
|
|
// Output the JSON to stdout only
|
|
process.stdout.write(`${jsonString}\n`)
|
|
}
|
|
} catch (error) {
|
|
process.stderr.write(`Error exporting workflow: ${error}\n`)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
// ---------- Execute ----------
|
|
exportWorkflow(workflowId, outputFile)
|
|
.then(() => {
|
|
process.exit(0)
|
|
})
|
|
.catch((error) => {
|
|
process.stderr.write(`Unexpected error: ${error}\n`)
|
|
process.exit(1)
|
|
})
|