@synergenius/flow-weaver 0.2.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/LICENSE +122 -0
- package/README.md +315 -0
- package/dist/annotation-generator.d.ts +45 -0
- package/dist/annotation-generator.js +557 -0
- package/dist/api/builder.d.ts +223 -0
- package/dist/api/builder.js +345 -0
- package/dist/api/compile.d.ts +92 -0
- package/dist/api/compile.js +149 -0
- package/dist/api/extract-types.d.ts +29 -0
- package/dist/api/extract-types.js +57 -0
- package/dist/api/generate-in-place.d.ts +73 -0
- package/dist/api/generate-in-place.js +1353 -0
- package/dist/api/generate.d.ts +83 -0
- package/dist/api/generate.js +510 -0
- package/dist/api/helpers.d.ts +248 -0
- package/dist/api/helpers.js +285 -0
- package/dist/api/index.d.ts +46 -0
- package/dist/api/index.js +45 -0
- package/dist/api/inline-runtime.d.ts +27 -0
- package/dist/api/inline-runtime.js +551 -0
- package/dist/api/manipulation/connections.d.ts +79 -0
- package/dist/api/manipulation/connections.js +151 -0
- package/dist/api/manipulation/index.d.ts +34 -0
- package/dist/api/manipulation/index.js +41 -0
- package/dist/api/manipulation/node-types.d.ts +123 -0
- package/dist/api/manipulation/node-types.js +200 -0
- package/dist/api/manipulation/nodes.d.ts +144 -0
- package/dist/api/manipulation/nodes.js +333 -0
- package/dist/api/manipulation/ports.d.ts +59 -0
- package/dist/api/manipulation/ports.js +228 -0
- package/dist/api/manipulation/scopes.d.ts +52 -0
- package/dist/api/manipulation/scopes.js +156 -0
- package/dist/api/manipulation/validation.d.ts +6 -0
- package/dist/api/manipulation/validation.js +6 -0
- package/dist/api/manipulation/workflow.d.ts +81 -0
- package/dist/api/manipulation/workflow.js +116 -0
- package/dist/api/manipulation.d.ts +8 -0
- package/dist/api/manipulation.js +8 -0
- package/dist/api/parse.d.ts +48 -0
- package/dist/api/parse.js +110 -0
- package/dist/api/patterns.d.ts +112 -0
- package/dist/api/patterns.js +306 -0
- package/dist/api/query.d.ts +429 -0
- package/dist/api/query.js +816 -0
- package/dist/api/templates.d.ts +98 -0
- package/dist/api/templates.js +117 -0
- package/dist/api/transform.d.ts +31 -0
- package/dist/api/transform.js +40 -0
- package/dist/api/validate.d.ts +25 -0
- package/dist/api/validate.js +39 -0
- package/dist/api/workflow-file-operations.d.ts +29 -0
- package/dist/api/workflow-file-operations.js +180 -0
- package/dist/ast/builder.d.ts +210 -0
- package/dist/ast/builder.js +395 -0
- package/dist/ast/index.d.ts +5 -0
- package/dist/ast/index.js +5 -0
- package/dist/ast/serialization-node.d.ts +6 -0
- package/dist/ast/serialization-node.js +30 -0
- package/dist/ast/serialization.d.ts +43 -0
- package/dist/ast/serialization.js +134 -0
- package/dist/ast/types.d.ts +852 -0
- package/dist/ast/types.js +2 -0
- package/dist/ast/workflow-utils.d.ts +54 -0
- package/dist/ast/workflow-utils.js +114 -0
- package/dist/body-generator.d.ts +31 -0
- package/dist/body-generator.js +35 -0
- package/dist/built-in-nodes/delay.d.ts +11 -0
- package/dist/built-in-nodes/delay.js +29 -0
- package/dist/built-in-nodes/index.d.ts +5 -0
- package/dist/built-in-nodes/index.js +4 -0
- package/dist/built-in-nodes/invoke-workflow.d.ts +13 -0
- package/dist/built-in-nodes/invoke-workflow.js +25 -0
- package/dist/built-in-nodes/mock-types.d.ts +18 -0
- package/dist/built-in-nodes/mock-types.js +12 -0
- package/dist/built-in-nodes/wait-for-event.d.ts +13 -0
- package/dist/built-in-nodes/wait-for-event.js +25 -0
- package/dist/chevrotain-parser/connect-parser.d.ts +24 -0
- package/dist/chevrotain-parser/connect-parser.js +98 -0
- package/dist/chevrotain-parser/grammar-diagrams.d.ts +29 -0
- package/dist/chevrotain-parser/grammar-diagrams.js +264 -0
- package/dist/chevrotain-parser/index.d.ts +25 -0
- package/dist/chevrotain-parser/index.js +27 -0
- package/dist/chevrotain-parser/map-parser.d.ts +33 -0
- package/dist/chevrotain-parser/map-parser.js +130 -0
- package/dist/chevrotain-parser/node-parser.d.ts +36 -0
- package/dist/chevrotain-parser/node-parser.js +466 -0
- package/dist/chevrotain-parser/path-parser.d.ts +28 -0
- package/dist/chevrotain-parser/path-parser.js +118 -0
- package/dist/chevrotain-parser/port-parser.d.ts +36 -0
- package/dist/chevrotain-parser/port-parser.js +442 -0
- package/dist/chevrotain-parser/position-parser.d.ts +20 -0
- package/dist/chevrotain-parser/position-parser.js +83 -0
- package/dist/chevrotain-parser/scope-parser.d.ts +19 -0
- package/dist/chevrotain-parser/scope-parser.js +104 -0
- package/dist/chevrotain-parser/tokens.d.ts +78 -0
- package/dist/chevrotain-parser/tokens.js +384 -0
- package/dist/chevrotain-parser/trigger-cancel-parser.d.ts +50 -0
- package/dist/chevrotain-parser/trigger-cancel-parser.js +282 -0
- package/dist/cli/commands/changelog.d.ts +13 -0
- package/dist/cli/commands/changelog.js +135 -0
- package/dist/cli/commands/compile.d.ts +64 -0
- package/dist/cli/commands/compile.js +278 -0
- package/dist/cli/commands/create.d.ts +33 -0
- package/dist/cli/commands/create.js +147 -0
- package/dist/cli/commands/describe.d.ts +68 -0
- package/dist/cli/commands/describe.js +377 -0
- package/dist/cli/commands/dev.d.ts +32 -0
- package/dist/cli/commands/dev.js +384 -0
- package/dist/cli/commands/diagram.d.ts +13 -0
- package/dist/cli/commands/diagram.js +33 -0
- package/dist/cli/commands/diff.d.ts +11 -0
- package/dist/cli/commands/diff.js +59 -0
- package/dist/cli/commands/doctor.d.ts +57 -0
- package/dist/cli/commands/doctor.js +719 -0
- package/dist/cli/commands/export.d.ts +57 -0
- package/dist/cli/commands/export.js +163 -0
- package/dist/cli/commands/grammar.d.ts +9 -0
- package/dist/cli/commands/grammar.js +39 -0
- package/dist/cli/commands/init.d.ts +59 -0
- package/dist/cli/commands/init.js +435 -0
- package/dist/cli/commands/listen.d.ts +16 -0
- package/dist/cli/commands/listen.js +39 -0
- package/dist/cli/commands/market.d.ts +52 -0
- package/dist/cli/commands/market.js +436 -0
- package/dist/cli/commands/migrate.d.ts +13 -0
- package/dist/cli/commands/migrate.js +89 -0
- package/dist/cli/commands/openapi.d.ts +37 -0
- package/dist/cli/commands/openapi.js +67 -0
- package/dist/cli/commands/pattern.d.ts +34 -0
- package/dist/cli/commands/pattern.js +185 -0
- package/dist/cli/commands/plugin.d.ts +16 -0
- package/dist/cli/commands/plugin.js +176 -0
- package/dist/cli/commands/run.d.ts +49 -0
- package/dist/cli/commands/run.js +191 -0
- package/dist/cli/commands/serve.d.ts +45 -0
- package/dist/cli/commands/serve.js +81 -0
- package/dist/cli/commands/templates.d.ts +8 -0
- package/dist/cli/commands/templates.js +54 -0
- package/dist/cli/commands/ui.d.ts +16 -0
- package/dist/cli/commands/ui.js +130 -0
- package/dist/cli/commands/validate.d.ts +12 -0
- package/dist/cli/commands/validate.js +247 -0
- package/dist/cli/commands/watch.d.ts +9 -0
- package/dist/cli/commands/watch.js +70 -0
- package/dist/cli/flow-weaver.mjs +92924 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.js +742 -0
- package/dist/cli/templates/ai/mock-provider.d.ts +7 -0
- package/dist/cli/templates/ai/mock-provider.js +64 -0
- package/dist/cli/templates/ai/types.d.ts +47 -0
- package/dist/cli/templates/ai/types.js +5 -0
- package/dist/cli/templates/approvals/index.d.ts +15 -0
- package/dist/cli/templates/approvals/index.js +241 -0
- package/dist/cli/templates/index.d.ts +102 -0
- package/dist/cli/templates/index.js +101 -0
- package/dist/cli/templates/nodes/agent-router.d.ts +3 -0
- package/dist/cli/templates/nodes/agent-router.js +114 -0
- package/dist/cli/templates/nodes/aggregator.d.ts +7 -0
- package/dist/cli/templates/nodes/aggregator.js +63 -0
- package/dist/cli/templates/nodes/conversation-memory.d.ts +3 -0
- package/dist/cli/templates/nodes/conversation-memory.js +85 -0
- package/dist/cli/templates/nodes/http.d.ts +7 -0
- package/dist/cli/templates/nodes/http.js +80 -0
- package/dist/cli/templates/nodes/human-approval.d.ts +3 -0
- package/dist/cli/templates/nodes/human-approval.js +110 -0
- package/dist/cli/templates/nodes/json-extractor.d.ts +3 -0
- package/dist/cli/templates/nodes/json-extractor.js +119 -0
- package/dist/cli/templates/nodes/llm-call.d.ts +3 -0
- package/dist/cli/templates/nodes/llm-call.js +106 -0
- package/dist/cli/templates/nodes/prompt-template.d.ts +3 -0
- package/dist/cli/templates/nodes/prompt-template.js +52 -0
- package/dist/cli/templates/nodes/rag-retriever.d.ts +3 -0
- package/dist/cli/templates/nodes/rag-retriever.js +128 -0
- package/dist/cli/templates/nodes/tool-executor.d.ts +3 -0
- package/dist/cli/templates/nodes/tool-executor.js +108 -0
- package/dist/cli/templates/nodes/transformer.d.ts +7 -0
- package/dist/cli/templates/nodes/transformer.js +68 -0
- package/dist/cli/templates/nodes/validator.d.ts +7 -0
- package/dist/cli/templates/nodes/validator.js +62 -0
- package/dist/cli/templates/providers/index.d.ts +14 -0
- package/dist/cli/templates/providers/index.js +239 -0
- package/dist/cli/templates/shared/approval-types.d.ts +9 -0
- package/dist/cli/templates/shared/approval-types.js +31 -0
- package/dist/cli/templates/shared/llm-types.d.ts +15 -0
- package/dist/cli/templates/shared/llm-types.js +104 -0
- package/dist/cli/templates/workflows/aggregator.d.ts +7 -0
- package/dist/cli/templates/workflows/aggregator.js +104 -0
- package/dist/cli/templates/workflows/ai-agent-durable.d.ts +8 -0
- package/dist/cli/templates/workflows/ai-agent-durable.js +338 -0
- package/dist/cli/templates/workflows/ai-agent.d.ts +31 -0
- package/dist/cli/templates/workflows/ai-agent.js +326 -0
- package/dist/cli/templates/workflows/ai-chat.d.ts +7 -0
- package/dist/cli/templates/workflows/ai-chat.js +169 -0
- package/dist/cli/templates/workflows/ai-pipeline-durable.d.ts +8 -0
- package/dist/cli/templates/workflows/ai-pipeline-durable.js +330 -0
- package/dist/cli/templates/workflows/ai-rag.d.ts +7 -0
- package/dist/cli/templates/workflows/ai-rag.js +186 -0
- package/dist/cli/templates/workflows/ai-react.d.ts +7 -0
- package/dist/cli/templates/workflows/ai-react.js +294 -0
- package/dist/cli/templates/workflows/conditional.d.ts +12 -0
- package/dist/cli/templates/workflows/conditional.js +142 -0
- package/dist/cli/templates/workflows/error-handler.d.ts +7 -0
- package/dist/cli/templates/workflows/error-handler.js +147 -0
- package/dist/cli/templates/workflows/foreach.d.ts +7 -0
- package/dist/cli/templates/workflows/foreach.js +143 -0
- package/dist/cli/templates/workflows/sequential.d.ts +7 -0
- package/dist/cli/templates/workflows/sequential.js +198 -0
- package/dist/cli/templates/workflows/webhook.d.ts +7 -0
- package/dist/cli/templates/workflows/webhook.js +161 -0
- package/dist/cli/utils/logger.d.ts +15 -0
- package/dist/cli/utils/logger.js +46 -0
- package/dist/constants.d.ts +100 -0
- package/dist/constants.js +125 -0
- package/dist/defaults.d.ts +3 -0
- package/dist/defaults.js +3 -0
- package/dist/deployment/config/defaults.d.ts +29 -0
- package/dist/deployment/config/defaults.js +98 -0
- package/dist/deployment/config/loader.d.ts +24 -0
- package/dist/deployment/config/loader.js +236 -0
- package/dist/deployment/config/types.d.ts +117 -0
- package/dist/deployment/config/types.js +5 -0
- package/dist/deployment/core/adapters.d.ts +90 -0
- package/dist/deployment/core/adapters.js +251 -0
- package/dist/deployment/core/executor.d.ts +62 -0
- package/dist/deployment/core/executor.js +197 -0
- package/dist/deployment/core/formatters.d.ts +57 -0
- package/dist/deployment/core/formatters.js +170 -0
- package/dist/deployment/index.d.ts +31 -0
- package/dist/deployment/index.js +48 -0
- package/dist/deployment/openapi/generator.d.ts +146 -0
- package/dist/deployment/openapi/generator.js +347 -0
- package/dist/deployment/openapi/schema-converter.d.ts +49 -0
- package/dist/deployment/openapi/schema-converter.js +192 -0
- package/dist/deployment/targets/base.d.ts +316 -0
- package/dist/deployment/targets/base.js +823 -0
- package/dist/deployment/targets/cloudflare.d.ts +23 -0
- package/dist/deployment/targets/cloudflare.js +1125 -0
- package/dist/deployment/targets/inngest.d.ts +38 -0
- package/dist/deployment/targets/inngest.js +926 -0
- package/dist/deployment/targets/lambda.d.ts +23 -0
- package/dist/deployment/targets/lambda.js +1289 -0
- package/dist/deployment/targets/vercel.d.ts +23 -0
- package/dist/deployment/targets/vercel.js +886 -0
- package/dist/deployment/types.d.ts +183 -0
- package/dist/deployment/types.js +8 -0
- package/dist/diagram/geometry.d.ts +26 -0
- package/dist/diagram/geometry.js +850 -0
- package/dist/diagram/index.d.ts +16 -0
- package/dist/diagram/index.js +42 -0
- package/dist/diagram/layout.d.ts +11 -0
- package/dist/diagram/layout.js +143 -0
- package/dist/diagram/orthogonal-router.d.ts +79 -0
- package/dist/diagram/orthogonal-router.js +568 -0
- package/dist/diagram/renderer.d.ts +3 -0
- package/dist/diagram/renderer.js +207 -0
- package/dist/diagram/theme.d.ts +20 -0
- package/dist/diagram/theme.js +189 -0
- package/dist/diagram/types.d.ts +70 -0
- package/dist/diagram/types.js +2 -0
- package/dist/diff/WorkflowDiffer.d.ts +13 -0
- package/dist/diff/WorkflowDiffer.js +429 -0
- package/dist/diff/formatDiff.d.ts +10 -0
- package/dist/diff/formatDiff.js +220 -0
- package/dist/diff/impact.d.ts +29 -0
- package/dist/diff/impact.js +119 -0
- package/dist/diff/index.d.ts +10 -0
- package/dist/diff/index.js +9 -0
- package/dist/diff/types.d.ts +138 -0
- package/dist/diff/types.js +35 -0
- package/dist/doc-metadata/extractors/annotations.d.ts +56 -0
- package/dist/doc-metadata/extractors/annotations.js +337 -0
- package/dist/doc-metadata/extractors/cli-commands.d.ts +17 -0
- package/dist/doc-metadata/extractors/cli-commands.js +355 -0
- package/dist/doc-metadata/extractors/mcp-tools.d.ts +16 -0
- package/dist/doc-metadata/extractors/mcp-tools.js +689 -0
- package/dist/doc-metadata/extractors/plugin-api.d.ts +19 -0
- package/dist/doc-metadata/extractors/plugin-api.js +279 -0
- package/dist/doc-metadata/index.d.ts +5 -0
- package/dist/doc-metadata/index.js +4 -0
- package/dist/doc-metadata/types.d.ts +120 -0
- package/dist/doc-metadata/types.js +5 -0
- package/dist/editor-completions/annotationValues.d.ts +12 -0
- package/dist/editor-completions/annotationValues.js +138 -0
- package/dist/editor-completions/contextParser.d.ts +40 -0
- package/dist/editor-completions/contextParser.js +410 -0
- package/dist/editor-completions/dataTypes.d.ts +16 -0
- package/dist/editor-completions/dataTypes.js +95 -0
- package/dist/editor-completions/goToDefinition.d.ts +27 -0
- package/dist/editor-completions/goToDefinition.js +112 -0
- package/dist/editor-completions/index.d.ts +39 -0
- package/dist/editor-completions/index.js +181 -0
- package/dist/editor-completions/jsDocAnnotations.d.ts +29 -0
- package/dist/editor-completions/jsDocAnnotations.js +357 -0
- package/dist/editor-completions/modifierCompletions.d.ts +17 -0
- package/dist/editor-completions/modifierCompletions.js +197 -0
- package/dist/editor-completions/types.d.ts +119 -0
- package/dist/editor-completions/types.js +8 -0
- package/dist/export/index.d.ts +68 -0
- package/dist/export/index.js +1074 -0
- package/dist/export/templates.d.ts +24 -0
- package/dist/export/templates.js +186 -0
- package/dist/friendly-errors.d.ts +35 -0
- package/dist/friendly-errors.js +375 -0
- package/dist/function-like.d.ts +38 -0
- package/dist/function-like.js +83 -0
- package/dist/generated-branding.d.ts +16 -0
- package/dist/generated-branding.js +22 -0
- package/dist/generator/async-detection.d.ts +27 -0
- package/dist/generator/async-detection.js +56 -0
- package/dist/generator/code-utils.d.ts +76 -0
- package/dist/generator/code-utils.js +410 -0
- package/dist/generator/control-flow.d.ts +54 -0
- package/dist/generator/control-flow.js +284 -0
- package/dist/generator/inngest.d.ts +53 -0
- package/dist/generator/inngest.js +1126 -0
- package/dist/generator/scope-function-generator.d.ts +78 -0
- package/dist/generator/scope-function-generator.js +360 -0
- package/dist/generator/unified.d.ts +42 -0
- package/dist/generator/unified.js +1504 -0
- package/dist/generator.d.ts +54 -0
- package/dist/generator.js +100 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.js +89 -0
- package/dist/jsdoc-parser.d.ts +308 -0
- package/dist/jsdoc-parser.js +923 -0
- package/dist/jsdoc-port-sync/constants.d.ts +41 -0
- package/dist/jsdoc-port-sync/constants.js +103 -0
- package/dist/jsdoc-port-sync/diff.d.ts +76 -0
- package/dist/jsdoc-port-sync/diff.js +319 -0
- package/dist/jsdoc-port-sync/index.d.ts +42 -0
- package/dist/jsdoc-port-sync/index.js +45 -0
- package/dist/jsdoc-port-sync/port-parser.d.ts +68 -0
- package/dist/jsdoc-port-sync/port-parser.js +579 -0
- package/dist/jsdoc-port-sync/rename.d.ts +21 -0
- package/dist/jsdoc-port-sync/rename.js +256 -0
- package/dist/jsdoc-port-sync/signature-parser.d.ts +104 -0
- package/dist/jsdoc-port-sync/signature-parser.js +559 -0
- package/dist/jsdoc-port-sync/sync.d.ts +36 -0
- package/dist/jsdoc-port-sync/sync.js +644 -0
- package/dist/jsdoc-port-sync.d.ts +10 -0
- package/dist/jsdoc-port-sync.js +10 -0
- package/dist/marketplace/index.d.ts +11 -0
- package/dist/marketplace/index.js +10 -0
- package/dist/marketplace/manifest.d.ts +32 -0
- package/dist/marketplace/manifest.js +176 -0
- package/dist/marketplace/registry.d.ts +30 -0
- package/dist/marketplace/registry.js +100 -0
- package/dist/marketplace/types.d.ts +154 -0
- package/dist/marketplace/types.js +9 -0
- package/dist/marketplace/validator.d.ts +13 -0
- package/dist/marketplace/validator.js +131 -0
- package/dist/mcp/auto-registration.d.ts +3 -0
- package/dist/mcp/auto-registration.js +62 -0
- package/dist/mcp/editor-connection.d.ts +50 -0
- package/dist/mcp/editor-connection.js +125 -0
- package/dist/mcp/event-buffer.d.ts +62 -0
- package/dist/mcp/event-buffer.js +150 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/resources.d.ts +14 -0
- package/dist/mcp/resources.js +55 -0
- package/dist/mcp/response-utils.d.ts +63 -0
- package/dist/mcp/response-utils.js +89 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.js +99 -0
- package/dist/mcp/tools-diagram.d.ts +8 -0
- package/dist/mcp/tools-diagram.js +53 -0
- package/dist/mcp/tools-editor.d.ts +5 -0
- package/dist/mcp/tools-editor.js +190 -0
- package/dist/mcp/tools-export.d.ts +9 -0
- package/dist/mcp/tools-export.js +180 -0
- package/dist/mcp/tools-marketplace.d.ts +9 -0
- package/dist/mcp/tools-marketplace.js +132 -0
- package/dist/mcp/tools-pattern.d.ts +3 -0
- package/dist/mcp/tools-pattern.js +783 -0
- package/dist/mcp/tools-query.d.ts +3 -0
- package/dist/mcp/tools-query.js +364 -0
- package/dist/mcp/tools-template.d.ts +10 -0
- package/dist/mcp/tools-template.js +119 -0
- package/dist/mcp/types.d.ts +70 -0
- package/dist/mcp/types.js +8 -0
- package/dist/mcp/workflow-executor.d.ts +47 -0
- package/dist/mcp/workflow-executor.js +133 -0
- package/dist/migration/registry.d.ts +30 -0
- package/dist/migration/registry.js +29 -0
- package/dist/node-types-generator.d.ts +49 -0
- package/dist/node-types-generator.js +139 -0
- package/dist/npm-packages.d.ts +56 -0
- package/dist/npm-packages.js +255 -0
- package/dist/parser.d.ts +204 -0
- package/dist/parser.js +2100 -0
- package/dist/plugin/PluginPanel.d.ts +12 -0
- package/dist/plugin/PluginPanel.js +5 -0
- package/dist/plugin/index.d.ts +13 -0
- package/dist/plugin/index.js +14 -0
- package/dist/plugin/types.d.ts +75 -0
- package/dist/plugin/types.js +8 -0
- package/dist/resolve-package-types.d.ts +17 -0
- package/dist/resolve-package-types.js +123 -0
- package/dist/runtime/CancellationError.d.ts +11 -0
- package/dist/runtime/CancellationError.js +20 -0
- package/dist/runtime/ExecutionContext.d.ts +146 -0
- package/dist/runtime/ExecutionContext.js +235 -0
- package/dist/runtime/builtin-functions.d.ts +8 -0
- package/dist/runtime/builtin-functions.js +549 -0
- package/dist/runtime/events.d.ts +50 -0
- package/dist/runtime/events.js +2 -0
- package/dist/runtime/function-registry.d.ts +59 -0
- package/dist/runtime/function-registry.js +66 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.js +7 -0
- package/dist/runtime/parameter-resolver.d.ts +62 -0
- package/dist/runtime/parameter-resolver.js +113 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +6 -0
- package/dist/server/types.d.ts +93 -0
- package/dist/server/types.js +5 -0
- package/dist/server/webhook-server.d.ts +50 -0
- package/dist/server/webhook-server.js +269 -0
- package/dist/server/workflow-registry.d.ts +61 -0
- package/dist/server/workflow-registry.js +202 -0
- package/dist/shared-project.d.ts +9 -0
- package/dist/shared-project.js +28 -0
- package/dist/sugar-optimizer.d.ts +40 -0
- package/dist/sugar-optimizer.js +387 -0
- package/dist/testing/assertions.d.ts +51 -0
- package/dist/testing/assertions.js +127 -0
- package/dist/testing/index.d.ts +30 -0
- package/dist/testing/index.js +24 -0
- package/dist/testing/mock-approval.d.ts +81 -0
- package/dist/testing/mock-approval.js +98 -0
- package/dist/testing/mock-llm.d.ts +124 -0
- package/dist/testing/mock-llm.js +119 -0
- package/dist/testing/recorder.d.ts +72 -0
- package/dist/testing/recorder.js +70 -0
- package/dist/testing/replayer.d.ts +56 -0
- package/dist/testing/replayer.js +143 -0
- package/dist/testing/token-tracker.d.ts +71 -0
- package/dist/testing/token-tracker.js +94 -0
- package/dist/type-checker.d.ts +42 -0
- package/dist/type-checker.js +190 -0
- package/dist/type-mappings.d.ts +29 -0
- package/dist/type-mappings.js +125 -0
- package/dist/types/branded-ports.d.ts +151 -0
- package/dist/types/branded-ports.js +121 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +5 -0
- package/dist/types.d.ts +139 -0
- package/dist/types.js +15 -0
- package/dist/utils/error-utils.d.ts +15 -0
- package/dist/utils/error-utils.js +27 -0
- package/dist/utils/lru-cache.d.ts +15 -0
- package/dist/utils/lru-cache.js +40 -0
- package/dist/utils/port-ordering.d.ts +26 -0
- package/dist/utils/port-ordering.js +88 -0
- package/dist/utils/port-tag-utils.d.ts +23 -0
- package/dist/utils/port-tag-utils.js +41 -0
- package/dist/utils/string-distance.d.ts +14 -0
- package/dist/utils/string-distance.js +56 -0
- package/dist/validation/agent-detection.d.ts +33 -0
- package/dist/validation/agent-detection.js +115 -0
- package/dist/validation/agent-rules.d.ts +48 -0
- package/dist/validation/agent-rules.js +262 -0
- package/dist/validator.d.ts +92 -0
- package/dist/validator.js +970 -0
- package/package.json +109 -0
|
@@ -0,0 +1,1074 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serverless export orchestrator
|
|
3
|
+
* Generates deployment-ready handlers for various platforms
|
|
4
|
+
*/
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as os from 'os';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
// ESM-compatible __dirname
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
import { getGeneratedBranding } from '../generated-branding.js';
|
|
13
|
+
import { compileWorkflow } from '../api/compile.js';
|
|
14
|
+
import { AnnotationParser } from '../parser.js';
|
|
15
|
+
import { LAMBDA_TEMPLATE, VERCEL_TEMPLATE, CLOUDFLARE_TEMPLATE, INNGEST_TEMPLATE, SAM_TEMPLATE, } from './templates.js';
|
|
16
|
+
import { generateInngestFunction } from '../generator/inngest.js';
|
|
17
|
+
/**
|
|
18
|
+
* Export multiple workflows as a single service
|
|
19
|
+
*/
|
|
20
|
+
export async function exportMultiWorkflow(options) {
|
|
21
|
+
const inputPath = path.resolve(options.input);
|
|
22
|
+
const outputDir = path.resolve(options.output);
|
|
23
|
+
const isDryRun = options.dryRun ?? false;
|
|
24
|
+
// Validate input file exists
|
|
25
|
+
if (!fs.existsSync(inputPath)) {
|
|
26
|
+
throw new Error(`Input file not found: ${inputPath}`);
|
|
27
|
+
}
|
|
28
|
+
// Parse to find workflows
|
|
29
|
+
const parser = new AnnotationParser();
|
|
30
|
+
const parseResult = parser.parse(inputPath);
|
|
31
|
+
if (parseResult.workflows.length === 0) {
|
|
32
|
+
throw new Error(`No workflows found in ${inputPath}`);
|
|
33
|
+
}
|
|
34
|
+
// Filter workflows if specific ones are requested
|
|
35
|
+
let selectedWorkflows = parseResult.workflows;
|
|
36
|
+
if (options.workflows && options.workflows.length > 0) {
|
|
37
|
+
selectedWorkflows = parseResult.workflows.filter((w) => options.workflows.includes(w.name) || options.workflows.includes(w.functionName));
|
|
38
|
+
if (selectedWorkflows.length === 0) {
|
|
39
|
+
const available = parseResult.workflows.map((w) => w.name).join(', ');
|
|
40
|
+
throw new Error(`None of the requested workflows found. Available: ${available}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// For dry-run, use temp directory for compilation
|
|
44
|
+
const workDir = isDryRun
|
|
45
|
+
? path.join(os.tmpdir(), `fw-export-multi-dryrun-${Date.now()}`)
|
|
46
|
+
: outputDir;
|
|
47
|
+
// Create working directory
|
|
48
|
+
fs.mkdirSync(workDir, { recursive: true });
|
|
49
|
+
fs.mkdirSync(path.join(workDir, 'workflows'), { recursive: true });
|
|
50
|
+
fs.mkdirSync(path.join(workDir, 'runtime'), { recursive: true });
|
|
51
|
+
const compiledWorkflows = [];
|
|
52
|
+
try {
|
|
53
|
+
// Compile each workflow
|
|
54
|
+
for (const workflow of selectedWorkflows) {
|
|
55
|
+
const workflowOutputPath = path.join(workDir, 'workflows', `${workflow.name}.ts`);
|
|
56
|
+
// Copy source file
|
|
57
|
+
fs.copyFileSync(inputPath, workflowOutputPath);
|
|
58
|
+
// Compile in-place
|
|
59
|
+
await compileWorkflow(workflowOutputPath, {
|
|
60
|
+
write: true,
|
|
61
|
+
inPlace: true,
|
|
62
|
+
parse: { workflowName: workflow.functionName },
|
|
63
|
+
generate: { production: options.production ?? true },
|
|
64
|
+
});
|
|
65
|
+
const compiledCode = fs.readFileSync(workflowOutputPath, 'utf8');
|
|
66
|
+
compiledWorkflows.push({
|
|
67
|
+
name: workflow.name,
|
|
68
|
+
functionName: workflow.functionName,
|
|
69
|
+
description: workflow.description,
|
|
70
|
+
code: compiledCode,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// Copy runtime files
|
|
74
|
+
const runtimeDir = path.join(workDir, 'runtime');
|
|
75
|
+
const libraryRuntimeDir = path.resolve(__dirname, '../runtime');
|
|
76
|
+
// Copy function registry and builtin functions
|
|
77
|
+
const runtimeFiles = ['function-registry.ts', 'parameter-resolver.ts', 'builtin-functions.ts'];
|
|
78
|
+
for (const file of runtimeFiles) {
|
|
79
|
+
const srcPath = path.join(libraryRuntimeDir, file);
|
|
80
|
+
const destPath = path.join(runtimeDir, file);
|
|
81
|
+
if (fs.existsSync(srcPath)) {
|
|
82
|
+
fs.copyFileSync(srcPath, destPath);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Generate handler and config based on target
|
|
86
|
+
const result = generateMultiHandler(options.target, compiledWorkflows, workDir, options);
|
|
87
|
+
// Write files if not dry-run
|
|
88
|
+
if (!isDryRun) {
|
|
89
|
+
for (const file of result.files) {
|
|
90
|
+
const dirPath = path.dirname(file.path);
|
|
91
|
+
if (!fs.existsSync(dirPath)) {
|
|
92
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
93
|
+
}
|
|
94
|
+
fs.writeFileSync(file.path, file.content);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
target: options.target,
|
|
99
|
+
files: result.files,
|
|
100
|
+
workflow: result.serviceName,
|
|
101
|
+
workflows: compiledWorkflows.map((w) => w.name),
|
|
102
|
+
openApiSpec: result.openApiSpec,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
// Clean up temp directory in dry-run mode
|
|
107
|
+
if (isDryRun) {
|
|
108
|
+
try {
|
|
109
|
+
fs.rmSync(workDir, { recursive: true, force: true });
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Ignore cleanup errors
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Generate multi-workflow handler and config files
|
|
119
|
+
*/
|
|
120
|
+
function generateMultiHandler(target, workflows, outputDir, options) {
|
|
121
|
+
const files = [];
|
|
122
|
+
const serviceName = path.basename(options.input, path.extname(options.input)) + '-service';
|
|
123
|
+
// Generate workflow imports and entries
|
|
124
|
+
const workflowImports = workflows
|
|
125
|
+
.map((w) => `import { ${w.functionName} } from './workflows/${w.name}.js';`)
|
|
126
|
+
.join('\n');
|
|
127
|
+
const workflowEntries = workflows.map((w) => ` '${w.name}': ${w.functionName},`).join('\n');
|
|
128
|
+
// Generate OpenAPI spec
|
|
129
|
+
const openApiSpec = generateMultiWorkflowOpenAPI(workflows, serviceName);
|
|
130
|
+
// Generate based on target
|
|
131
|
+
switch (target) {
|
|
132
|
+
case 'lambda':
|
|
133
|
+
files.push({
|
|
134
|
+
path: path.join(outputDir, 'handler.ts'),
|
|
135
|
+
content: generateLambdaMultiHandler(workflowImports, workflowEntries, serviceName),
|
|
136
|
+
});
|
|
137
|
+
files.push({
|
|
138
|
+
path: path.join(outputDir, 'openapi.ts'),
|
|
139
|
+
content: `// Generated OpenAPI specification\nexport const openApiSpec = ${JSON.stringify(openApiSpec, null, 2)};\n`,
|
|
140
|
+
});
|
|
141
|
+
files.push({
|
|
142
|
+
path: path.join(outputDir, 'template.yaml'),
|
|
143
|
+
content: generateLambdaSAMMultiTemplate(serviceName, workflows.length),
|
|
144
|
+
});
|
|
145
|
+
files.push({
|
|
146
|
+
path: path.join(outputDir, 'package.json'),
|
|
147
|
+
content: JSON.stringify({
|
|
148
|
+
name: `fw-${serviceName}`,
|
|
149
|
+
version: '1.0.0',
|
|
150
|
+
type: 'module',
|
|
151
|
+
main: 'handler.js',
|
|
152
|
+
scripts: {
|
|
153
|
+
build: 'tsc',
|
|
154
|
+
deploy: 'sam build && sam deploy --guided',
|
|
155
|
+
},
|
|
156
|
+
devDependencies: {
|
|
157
|
+
'@types/aws-lambda': '^8.10.0',
|
|
158
|
+
typescript: '^5.0.0',
|
|
159
|
+
},
|
|
160
|
+
}, null, 2),
|
|
161
|
+
});
|
|
162
|
+
files.push({
|
|
163
|
+
path: path.join(outputDir, 'tsconfig.json'),
|
|
164
|
+
content: JSON.stringify({
|
|
165
|
+
compilerOptions: {
|
|
166
|
+
target: 'ES2022',
|
|
167
|
+
module: 'NodeNext',
|
|
168
|
+
moduleResolution: 'NodeNext',
|
|
169
|
+
outDir: './dist',
|
|
170
|
+
strict: true,
|
|
171
|
+
esModuleInterop: true,
|
|
172
|
+
skipLibCheck: true,
|
|
173
|
+
},
|
|
174
|
+
include: ['*.ts', 'workflows/*.ts', 'runtime/*.ts'],
|
|
175
|
+
}, null, 2),
|
|
176
|
+
});
|
|
177
|
+
break;
|
|
178
|
+
case 'vercel':
|
|
179
|
+
files.push({
|
|
180
|
+
path: path.join(outputDir, 'api', '[workflow].ts'),
|
|
181
|
+
content: generateVercelMultiHandler(workflowImports, workflowEntries, serviceName),
|
|
182
|
+
});
|
|
183
|
+
files.push({
|
|
184
|
+
path: path.join(outputDir, 'openapi.ts'),
|
|
185
|
+
content: `// Generated OpenAPI specification\nexport const openApiSpec = ${JSON.stringify(openApiSpec, null, 2)};\n`,
|
|
186
|
+
});
|
|
187
|
+
files.push({
|
|
188
|
+
path: path.join(outputDir, 'vercel.json'),
|
|
189
|
+
content: JSON.stringify({
|
|
190
|
+
functions: {
|
|
191
|
+
'api/[workflow].ts': {
|
|
192
|
+
memory: 1024,
|
|
193
|
+
maxDuration: 60,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
}, null, 2),
|
|
197
|
+
});
|
|
198
|
+
break;
|
|
199
|
+
case 'cloudflare':
|
|
200
|
+
files.push({
|
|
201
|
+
path: path.join(outputDir, 'index.ts'),
|
|
202
|
+
content: generateCloudflareMultiHandler(workflowImports, workflowEntries, serviceName),
|
|
203
|
+
});
|
|
204
|
+
files.push({
|
|
205
|
+
path: path.join(outputDir, 'openapi.ts'),
|
|
206
|
+
content: `// Generated OpenAPI specification\nexport const openApiSpec = ${JSON.stringify(openApiSpec, null, 2)};\n`,
|
|
207
|
+
});
|
|
208
|
+
files.push({
|
|
209
|
+
path: path.join(outputDir, 'wrangler.toml'),
|
|
210
|
+
content: `name = "${serviceName}"\nmain = "dist/index.js"\ncompatibility_date = "2024-01-01"\n\n[build]\ncommand = "npm run build"\n`,
|
|
211
|
+
});
|
|
212
|
+
files.push({
|
|
213
|
+
path: path.join(outputDir, 'package.json'),
|
|
214
|
+
content: JSON.stringify({
|
|
215
|
+
name: `fw-${serviceName}`,
|
|
216
|
+
version: '1.0.0',
|
|
217
|
+
type: 'module',
|
|
218
|
+
scripts: {
|
|
219
|
+
build: 'tsc',
|
|
220
|
+
deploy: 'wrangler deploy',
|
|
221
|
+
dev: 'wrangler dev',
|
|
222
|
+
},
|
|
223
|
+
devDependencies: {
|
|
224
|
+
'@cloudflare/workers-types': '^4.0.0',
|
|
225
|
+
typescript: '^5.0.0',
|
|
226
|
+
wrangler: '^3.0.0',
|
|
227
|
+
},
|
|
228
|
+
}, null, 2),
|
|
229
|
+
});
|
|
230
|
+
files.push({
|
|
231
|
+
path: path.join(outputDir, 'tsconfig.json'),
|
|
232
|
+
content: JSON.stringify({
|
|
233
|
+
compilerOptions: {
|
|
234
|
+
target: 'ES2022',
|
|
235
|
+
module: 'ESNext',
|
|
236
|
+
moduleResolution: 'Bundler',
|
|
237
|
+
outDir: './dist',
|
|
238
|
+
strict: true,
|
|
239
|
+
skipLibCheck: true,
|
|
240
|
+
types: ['@cloudflare/workers-types'],
|
|
241
|
+
},
|
|
242
|
+
include: ['*.ts', 'workflows/*.ts', 'runtime/*.ts'],
|
|
243
|
+
}, null, 2),
|
|
244
|
+
});
|
|
245
|
+
break;
|
|
246
|
+
case 'inngest':
|
|
247
|
+
files.push({
|
|
248
|
+
path: path.join(outputDir, 'handler.ts'),
|
|
249
|
+
content: generateInngestMultiHandler(workflowImports, workflowEntries, serviceName, workflows),
|
|
250
|
+
});
|
|
251
|
+
files.push({
|
|
252
|
+
path: path.join(outputDir, 'openapi.ts'),
|
|
253
|
+
content: `// Generated OpenAPI specification\nexport const openApiSpec = ${JSON.stringify(openApiSpec, null, 2)};\n`,
|
|
254
|
+
});
|
|
255
|
+
files.push({
|
|
256
|
+
path: path.join(outputDir, 'package.json'),
|
|
257
|
+
content: JSON.stringify({
|
|
258
|
+
name: `fw-${serviceName}`,
|
|
259
|
+
version: '1.0.0',
|
|
260
|
+
type: 'module',
|
|
261
|
+
main: 'handler.js',
|
|
262
|
+
scripts: {
|
|
263
|
+
build: 'tsc',
|
|
264
|
+
dev: 'npx inngest-cli@latest dev & npx tsx handler.ts',
|
|
265
|
+
serve: 'npx tsx handler.ts',
|
|
266
|
+
},
|
|
267
|
+
dependencies: {
|
|
268
|
+
inngest: '^3.0.0',
|
|
269
|
+
express: '^4.18.0',
|
|
270
|
+
},
|
|
271
|
+
devDependencies: {
|
|
272
|
+
'@types/express': '^4.17.0',
|
|
273
|
+
typescript: '^5.0.0',
|
|
274
|
+
},
|
|
275
|
+
}, null, 2),
|
|
276
|
+
});
|
|
277
|
+
files.push({
|
|
278
|
+
path: path.join(outputDir, 'tsconfig.json'),
|
|
279
|
+
content: JSON.stringify({
|
|
280
|
+
compilerOptions: {
|
|
281
|
+
target: 'ES2022',
|
|
282
|
+
module: 'NodeNext',
|
|
283
|
+
moduleResolution: 'NodeNext',
|
|
284
|
+
outDir: './dist',
|
|
285
|
+
strict: true,
|
|
286
|
+
esModuleInterop: true,
|
|
287
|
+
skipLibCheck: true,
|
|
288
|
+
},
|
|
289
|
+
include: ['*.ts', 'workflows/*.ts', 'runtime/*.ts'],
|
|
290
|
+
}, null, 2),
|
|
291
|
+
});
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
return { files, serviceName, openApiSpec };
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Generate consolidated OpenAPI spec for multiple workflows
|
|
298
|
+
*/
|
|
299
|
+
function generateMultiWorkflowOpenAPI(workflows, serviceName) {
|
|
300
|
+
const paths = {};
|
|
301
|
+
for (const workflow of workflows) {
|
|
302
|
+
paths[`/api/${workflow.name}`] = {
|
|
303
|
+
post: {
|
|
304
|
+
operationId: `execute_${workflow.functionName}`,
|
|
305
|
+
summary: `Execute ${workflow.name} workflow`,
|
|
306
|
+
description: workflow.description || `Execute the ${workflow.name} workflow`,
|
|
307
|
+
tags: ['workflows'],
|
|
308
|
+
requestBody: {
|
|
309
|
+
description: 'Workflow input parameters',
|
|
310
|
+
required: true,
|
|
311
|
+
content: {
|
|
312
|
+
'application/json': {
|
|
313
|
+
schema: { type: 'object', additionalProperties: true },
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
responses: {
|
|
318
|
+
'200': {
|
|
319
|
+
description: 'Successful workflow execution',
|
|
320
|
+
content: {
|
|
321
|
+
'application/json': {
|
|
322
|
+
schema: {
|
|
323
|
+
type: 'object',
|
|
324
|
+
properties: {
|
|
325
|
+
success: { type: 'boolean' },
|
|
326
|
+
result: { type: 'object' },
|
|
327
|
+
executionTime: { type: 'number' },
|
|
328
|
+
requestId: { type: 'string' },
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
'404': { description: 'Workflow not found' },
|
|
335
|
+
'500': { description: 'Execution error' },
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
// Add functions endpoint
|
|
341
|
+
paths['/api/functions'] = {
|
|
342
|
+
get: {
|
|
343
|
+
operationId: 'list_functions',
|
|
344
|
+
summary: 'List available functions',
|
|
345
|
+
description: 'Returns all registered functions that can be used as parameters',
|
|
346
|
+
tags: ['functions'],
|
|
347
|
+
responses: {
|
|
348
|
+
'200': {
|
|
349
|
+
description: 'List of registered functions',
|
|
350
|
+
content: { 'application/json': { schema: { type: 'array' } } },
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
return {
|
|
356
|
+
openapi: '3.0.3',
|
|
357
|
+
info: {
|
|
358
|
+
title: `${serviceName} API`,
|
|
359
|
+
version: '1.0.0',
|
|
360
|
+
description: `Multi-workflow service with ${workflows.length} workflows`,
|
|
361
|
+
},
|
|
362
|
+
paths,
|
|
363
|
+
tags: [
|
|
364
|
+
{ name: 'workflows', description: 'Workflow execution endpoints' },
|
|
365
|
+
{ name: 'functions', description: 'Function registry endpoints' },
|
|
366
|
+
],
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Generate Lambda multi-workflow handler
|
|
371
|
+
*/
|
|
372
|
+
function generateLambdaMultiHandler(imports, entries, serviceName) {
|
|
373
|
+
return `${getGeneratedBranding().header('export --target lambda --multi')}
|
|
374
|
+
import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2, Context } from 'aws-lambda';
|
|
375
|
+
${imports}
|
|
376
|
+
import { functionRegistry } from './runtime/function-registry.js';
|
|
377
|
+
import './runtime/builtin-functions.js';
|
|
378
|
+
import { openApiSpec } from './openapi.js';
|
|
379
|
+
|
|
380
|
+
const workflows: Record<string, (execute: boolean, params: unknown) => Promise<unknown>> = {
|
|
381
|
+
${entries}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
const SWAGGER_UI_HTML = \`<!DOCTYPE html>
|
|
385
|
+
<html lang="en">
|
|
386
|
+
<head>
|
|
387
|
+
<meta charset="UTF-8">
|
|
388
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
389
|
+
<title>${serviceName} API Documentation</title>
|
|
390
|
+
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
|
|
391
|
+
</head>
|
|
392
|
+
<body>
|
|
393
|
+
<div id="swagger-ui"></div>
|
|
394
|
+
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
|
|
395
|
+
<script>
|
|
396
|
+
SwaggerUIBundle({
|
|
397
|
+
url: './openapi.json',
|
|
398
|
+
dom_id: '#swagger-ui',
|
|
399
|
+
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
|
400
|
+
layout: 'BaseLayout'
|
|
401
|
+
});
|
|
402
|
+
</script>
|
|
403
|
+
</body>
|
|
404
|
+
</html>\`;
|
|
405
|
+
|
|
406
|
+
export const handler = async (
|
|
407
|
+
event: APIGatewayProxyEventV2,
|
|
408
|
+
context: Context
|
|
409
|
+
): Promise<APIGatewayProxyResultV2> => {
|
|
410
|
+
context.callbackWaitsForEmptyEventLoop = false;
|
|
411
|
+
const path = event.rawPath || event.requestContext?.http?.path || '/';
|
|
412
|
+
const method = event.requestContext?.http?.method || 'GET';
|
|
413
|
+
|
|
414
|
+
if (path === '/api/openapi.json' && method === 'GET') {
|
|
415
|
+
return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(openApiSpec) };
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (path === '/api/docs' && method === 'GET') {
|
|
419
|
+
return { statusCode: 200, headers: { 'Content-Type': 'text/html' }, body: SWAGGER_UI_HTML };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (path === '/api/functions' && method === 'GET') {
|
|
423
|
+
const category = event.queryStringParameters?.category;
|
|
424
|
+
const functions = functionRegistry.list(category as any);
|
|
425
|
+
return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(functions) };
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const workflowMatch = path.match(/^\\/api\\/([^\\/]+)$/);
|
|
429
|
+
if (!workflowMatch) {
|
|
430
|
+
return { statusCode: 404, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ error: 'Not found' }) };
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const workflowName = workflowMatch[1];
|
|
434
|
+
const workflow = workflows[workflowName];
|
|
435
|
+
|
|
436
|
+
if (!workflow) {
|
|
437
|
+
return { statusCode: 404, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ error: \`Workflow '\${workflowName}' not found\`, availableWorkflows: Object.keys(workflows) }) };
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (method !== 'POST') {
|
|
441
|
+
return { statusCode: 405, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ error: 'Method not allowed' }) };
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
try {
|
|
445
|
+
const body = typeof event.body === 'string' ? JSON.parse(event.body || '{}') : event.body || {};
|
|
446
|
+
const startTime = Date.now();
|
|
447
|
+
const result = await workflow(true, body);
|
|
448
|
+
|
|
449
|
+
return {
|
|
450
|
+
statusCode: 200,
|
|
451
|
+
headers: { 'Content-Type': 'application/json', 'X-Execution-Time': \`\${Date.now() - startTime}ms\`, 'X-Request-Id': context.awsRequestId },
|
|
452
|
+
body: JSON.stringify({ success: true, result, executionTime: Date.now() - startTime, requestId: context.awsRequestId }),
|
|
453
|
+
};
|
|
454
|
+
} catch (error) {
|
|
455
|
+
return {
|
|
456
|
+
statusCode: 500,
|
|
457
|
+
headers: { 'Content-Type': 'application/json' },
|
|
458
|
+
body: JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error), requestId: context.awsRequestId }),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
`;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Generate Lambda SAM template for multi-workflow
|
|
466
|
+
*/
|
|
467
|
+
function generateLambdaSAMMultiTemplate(serviceName, workflowCount) {
|
|
468
|
+
return `AWSTemplateFormatVersion: '2010-09-09'
|
|
469
|
+
Transform: AWS::Serverless-2016-10-31
|
|
470
|
+
Description: Flow Weaver multi-workflow service - ${serviceName}
|
|
471
|
+
|
|
472
|
+
Globals:
|
|
473
|
+
Function:
|
|
474
|
+
Timeout: 30
|
|
475
|
+
Runtime: nodejs20.x
|
|
476
|
+
MemorySize: 256
|
|
477
|
+
|
|
478
|
+
Resources:
|
|
479
|
+
WorkflowFunction:
|
|
480
|
+
Type: AWS::Serverless::Function
|
|
481
|
+
Properties:
|
|
482
|
+
Handler: handler.handler
|
|
483
|
+
CodeUri: .
|
|
484
|
+
Description: Multi-workflow service with ${workflowCount} workflows
|
|
485
|
+
Events:
|
|
486
|
+
ApiProxy:
|
|
487
|
+
Type: HttpApi
|
|
488
|
+
Properties:
|
|
489
|
+
Path: /api/{proxy+}
|
|
490
|
+
Method: ANY
|
|
491
|
+
|
|
492
|
+
Outputs:
|
|
493
|
+
ApiEndpoint:
|
|
494
|
+
Description: API base URL
|
|
495
|
+
Value: !Sub "https://\${ServerlessHttpApi}.execute-api.\${AWS::Region}.amazonaws.com/api"
|
|
496
|
+
`;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Generate Vercel multi-workflow handler
|
|
500
|
+
*/
|
|
501
|
+
function generateVercelMultiHandler(imports, entries, serviceName) {
|
|
502
|
+
const adjustedImports = imports.replace(/\.\//g, '../');
|
|
503
|
+
return `${getGeneratedBranding().header('export --target vercel --multi')}
|
|
504
|
+
import type { VercelRequest, VercelResponse } from '@vercel/node';
|
|
505
|
+
${adjustedImports}
|
|
506
|
+
import { functionRegistry } from '../runtime/function-registry.js';
|
|
507
|
+
import '../runtime/builtin-functions.js';
|
|
508
|
+
import { openApiSpec } from '../openapi.js';
|
|
509
|
+
|
|
510
|
+
export const config = { runtime: 'nodejs20.x', maxDuration: 60 };
|
|
511
|
+
|
|
512
|
+
const workflows: Record<string, (execute: boolean, params: unknown) => Promise<unknown>> = {
|
|
513
|
+
${entries}
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const SWAGGER_UI_HTML = \`<!DOCTYPE html>
|
|
517
|
+
<html lang="en">
|
|
518
|
+
<head>
|
|
519
|
+
<meta charset="UTF-8">
|
|
520
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
521
|
+
<title>${serviceName} API Documentation</title>
|
|
522
|
+
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
|
|
523
|
+
</head>
|
|
524
|
+
<body>
|
|
525
|
+
<div id="swagger-ui"></div>
|
|
526
|
+
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
|
|
527
|
+
<script>
|
|
528
|
+
SwaggerUIBundle({
|
|
529
|
+
url: '/api/openapi.json',
|
|
530
|
+
dom_id: '#swagger-ui',
|
|
531
|
+
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
|
532
|
+
layout: 'BaseLayout'
|
|
533
|
+
});
|
|
534
|
+
</script>
|
|
535
|
+
</body>
|
|
536
|
+
</html>\`;
|
|
537
|
+
|
|
538
|
+
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
|
539
|
+
const { workflow: workflowName } = req.query;
|
|
540
|
+
const requestId = req.headers['x-vercel-id'] as string || crypto.randomUUID();
|
|
541
|
+
|
|
542
|
+
if (workflowName === 'openapi.json' && req.method === 'GET') {
|
|
543
|
+
return res.status(200).json(openApiSpec);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (workflowName === 'docs' && req.method === 'GET') {
|
|
547
|
+
res.setHeader('Content-Type', 'text/html');
|
|
548
|
+
return res.status(200).send(SWAGGER_UI_HTML);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (workflowName === 'functions' && req.method === 'GET') {
|
|
552
|
+
const category = req.query.category as string | undefined;
|
|
553
|
+
const functions = functionRegistry.list(category as any);
|
|
554
|
+
return res.status(200).json(functions);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const workflow = typeof workflowName === 'string' ? workflows[workflowName] : undefined;
|
|
558
|
+
|
|
559
|
+
if (!workflow) {
|
|
560
|
+
return res.status(404).json({ error: \`Workflow '\${workflowName}' not found\`, availableWorkflows: Object.keys(workflows) });
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (req.method !== 'POST') {
|
|
564
|
+
return res.status(405).json({ error: 'Method not allowed' });
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
try {
|
|
568
|
+
const params = req.body || {};
|
|
569
|
+
const startTime = Date.now();
|
|
570
|
+
const result = await workflow(true, params);
|
|
571
|
+
|
|
572
|
+
return res.setHeader('X-Request-Id', requestId).setHeader('X-Execution-Time', \`\${Date.now() - startTime}ms\`).status(200).json({ success: true, result, executionTime: Date.now() - startTime, requestId });
|
|
573
|
+
} catch (error) {
|
|
574
|
+
return res.setHeader('X-Request-Id', requestId).status(500).json({ success: false, error: { code: 'EXECUTION_ERROR', message: error instanceof Error ? error.message : String(error) }, requestId });
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
`;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Generate Cloudflare multi-workflow handler
|
|
581
|
+
*/
|
|
582
|
+
function generateCloudflareMultiHandler(imports, entries, serviceName) {
|
|
583
|
+
return `${getGeneratedBranding().header('export --target cloudflare --multi')}
|
|
584
|
+
${imports}
|
|
585
|
+
import { functionRegistry } from './runtime/function-registry.js';
|
|
586
|
+
import './runtime/builtin-functions.js';
|
|
587
|
+
import { openApiSpec } from './openapi.js';
|
|
588
|
+
|
|
589
|
+
interface Env {}
|
|
590
|
+
|
|
591
|
+
const workflows: Record<string, (execute: boolean, params: unknown) => Promise<unknown>> = {
|
|
592
|
+
${entries}
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
const SWAGGER_UI_HTML = \`<!DOCTYPE html>
|
|
596
|
+
<html lang="en">
|
|
597
|
+
<head>
|
|
598
|
+
<meta charset="UTF-8">
|
|
599
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
600
|
+
<title>${serviceName} API Documentation</title>
|
|
601
|
+
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
|
|
602
|
+
</head>
|
|
603
|
+
<body>
|
|
604
|
+
<div id="swagger-ui"></div>
|
|
605
|
+
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
|
|
606
|
+
<script>
|
|
607
|
+
SwaggerUIBundle({
|
|
608
|
+
url: '/api/openapi.json',
|
|
609
|
+
dom_id: '#swagger-ui',
|
|
610
|
+
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
|
611
|
+
layout: 'BaseLayout'
|
|
612
|
+
});
|
|
613
|
+
</script>
|
|
614
|
+
</body>
|
|
615
|
+
</html>\`;
|
|
616
|
+
|
|
617
|
+
export default {
|
|
618
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
619
|
+
const url = new URL(request.url);
|
|
620
|
+
const path = url.pathname;
|
|
621
|
+
const method = request.method;
|
|
622
|
+
|
|
623
|
+
if (path === '/api/openapi.json' && method === 'GET') {
|
|
624
|
+
return new Response(JSON.stringify(openApiSpec), { status: 200, headers: { 'Content-Type': 'application/json' } });
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (path === '/api/docs' && method === 'GET') {
|
|
628
|
+
return new Response(SWAGGER_UI_HTML, { status: 200, headers: { 'Content-Type': 'text/html' } });
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (path === '/api/functions' && method === 'GET') {
|
|
632
|
+
const category = url.searchParams.get('category');
|
|
633
|
+
const functions = functionRegistry.list(category as any);
|
|
634
|
+
return new Response(JSON.stringify(functions), { status: 200, headers: { 'Content-Type': 'application/json' } });
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const workflowMatch = path.match(/^\\/api\\/([^\\/]+)$/);
|
|
638
|
+
if (!workflowMatch) {
|
|
639
|
+
return new Response(JSON.stringify({ error: 'Not found' }), { status: 404, headers: { 'Content-Type': 'application/json' } });
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const workflowName = workflowMatch[1];
|
|
643
|
+
const workflow = workflows[workflowName];
|
|
644
|
+
|
|
645
|
+
if (!workflow) {
|
|
646
|
+
return new Response(JSON.stringify({ error: \`Workflow '\${workflowName}' not found\`, availableWorkflows: Object.keys(workflows) }), { status: 404, headers: { 'Content-Type': 'application/json' } });
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (method !== 'POST') {
|
|
650
|
+
return new Response(JSON.stringify({ error: 'Method not allowed' }), { status: 405, headers: { 'Content-Type': 'application/json' } });
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
const requestId = request.headers.get('cf-ray') || crypto.randomUUID();
|
|
654
|
+
|
|
655
|
+
try {
|
|
656
|
+
const body = await request.json() as Record<string, unknown>;
|
|
657
|
+
const startTime = performance.now();
|
|
658
|
+
const result = await workflow(true, body);
|
|
659
|
+
|
|
660
|
+
return new Response(JSON.stringify({ success: true, result, executionTime: Math.round(performance.now() - startTime), requestId }), {
|
|
661
|
+
status: 200,
|
|
662
|
+
headers: { 'Content-Type': 'application/json', 'X-Request-Id': requestId, 'X-Execution-Time': \`\${Math.round(performance.now() - startTime)}ms\` },
|
|
663
|
+
});
|
|
664
|
+
} catch (error) {
|
|
665
|
+
return new Response(JSON.stringify({ success: false, error: { code: 'EXECUTION_ERROR', message: error instanceof Error ? error.message : String(error) }, requestId }), {
|
|
666
|
+
status: 500,
|
|
667
|
+
headers: { 'Content-Type': 'application/json', 'X-Request-Id': requestId },
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
},
|
|
671
|
+
} satisfies ExportedHandler<Env>;
|
|
672
|
+
`;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Generate Inngest multi-workflow handler
|
|
676
|
+
*/
|
|
677
|
+
function generateInngestMultiHandler(imports, entries, serviceName, workflows) {
|
|
678
|
+
const serviceId = serviceName
|
|
679
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
680
|
+
.replace(/[^a-zA-Z0-9-]/g, '-')
|
|
681
|
+
.replace(/-+/g, '-')
|
|
682
|
+
.toLowerCase();
|
|
683
|
+
const functionDefs = workflows.map((w) => {
|
|
684
|
+
const fnId = w.name
|
|
685
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
686
|
+
.replace(/[^a-zA-Z0-9-]/g, '-')
|
|
687
|
+
.replace(/-+/g, '-')
|
|
688
|
+
.toLowerCase();
|
|
689
|
+
const fnVar = `fn_${w.functionName.replace(/[^a-zA-Z0-9_$]/g, '_')}`;
|
|
690
|
+
return `const ${fnVar} = inngest.createFunction(
|
|
691
|
+
{ id: '${fnId}', name: '${w.name}' },
|
|
692
|
+
{ event: 'fw/${fnId}.execute' },
|
|
693
|
+
async ({ event, step }) => {
|
|
694
|
+
const params = event.data ?? {};
|
|
695
|
+
const result = await step.run('execute-workflow', async () => {
|
|
696
|
+
return ${w.functionName}(true, params);
|
|
697
|
+
});
|
|
698
|
+
return { success: true, result };
|
|
699
|
+
}
|
|
700
|
+
);`;
|
|
701
|
+
}).join('\n\n');
|
|
702
|
+
const functionList = workflows
|
|
703
|
+
.map((w) => `fn_${w.functionName.replace(/[^a-zA-Z0-9_$]/g, '_')}`)
|
|
704
|
+
.join(', ');
|
|
705
|
+
return `${getGeneratedBranding().header('export --target inngest --multi')}
|
|
706
|
+
import { Inngest } from 'inngest';
|
|
707
|
+
import { serve } from 'inngest/express';
|
|
708
|
+
import express from 'express';
|
|
709
|
+
${imports}
|
|
710
|
+
import { functionRegistry } from './runtime/function-registry.js';
|
|
711
|
+
import './runtime/builtin-functions.js';
|
|
712
|
+
import { openApiSpec } from './openapi.js';
|
|
713
|
+
|
|
714
|
+
const inngest = new Inngest({ id: '${serviceId}' });
|
|
715
|
+
|
|
716
|
+
${functionDefs}
|
|
717
|
+
|
|
718
|
+
const functions = [${functionList}];
|
|
719
|
+
|
|
720
|
+
type WorkflowHandler = (execute: boolean, params: unknown) => Promise<unknown>;
|
|
721
|
+
const directHandlers: Record<string, WorkflowHandler> = {
|
|
722
|
+
${entries}
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
const app = express();
|
|
726
|
+
app.use(express.json());
|
|
727
|
+
|
|
728
|
+
app.use('/api/inngest', serve({ client: inngest, functions }));
|
|
729
|
+
|
|
730
|
+
app.get('/api/openapi.json', (_req, res) => { res.json(openApiSpec); });
|
|
731
|
+
|
|
732
|
+
app.get('/api/functions', (req, res) => {
|
|
733
|
+
const category = req.query.category as string | undefined;
|
|
734
|
+
res.json(functionRegistry.list(category as any));
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
app.post('/api/invoke/:workflowName', async (req, res) => {
|
|
738
|
+
const workflow = directHandlers[req.params.workflowName];
|
|
739
|
+
if (!workflow) {
|
|
740
|
+
return res.status(404).json({ error: \`Workflow '\${req.params.workflowName}' not found\`, availableWorkflows: Object.keys(directHandlers) });
|
|
741
|
+
}
|
|
742
|
+
try {
|
|
743
|
+
const startTime = Date.now();
|
|
744
|
+
const result = await workflow(true, req.body || {});
|
|
745
|
+
res.json({ success: true, result, executionTime: Date.now() - startTime });
|
|
746
|
+
} catch (error) {
|
|
747
|
+
res.status(500).json({ success: false, error: error instanceof Error ? error.message : String(error) });
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
export const handler = app;
|
|
752
|
+
export default app;
|
|
753
|
+
`;
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Export a workflow for serverless deployment
|
|
757
|
+
*/
|
|
758
|
+
export async function exportWorkflow(options) {
|
|
759
|
+
// If multi mode, use multi-workflow export
|
|
760
|
+
if (options.multi) {
|
|
761
|
+
return exportMultiWorkflow(options);
|
|
762
|
+
}
|
|
763
|
+
const inputPath = path.resolve(options.input);
|
|
764
|
+
const outputDir = path.resolve(options.output);
|
|
765
|
+
const isDryRun = options.dryRun ?? false;
|
|
766
|
+
// Validate input file exists
|
|
767
|
+
if (!fs.existsSync(inputPath)) {
|
|
768
|
+
throw new Error(`Input file not found: ${inputPath}`);
|
|
769
|
+
}
|
|
770
|
+
// Parse to find workflows
|
|
771
|
+
const parser = new AnnotationParser();
|
|
772
|
+
const parseResult = parser.parse(inputPath);
|
|
773
|
+
if (parseResult.workflows.length === 0) {
|
|
774
|
+
throw new Error(`No workflows found in ${inputPath}`);
|
|
775
|
+
}
|
|
776
|
+
// Select workflow
|
|
777
|
+
const workflow = options.workflow
|
|
778
|
+
? parseResult.workflows.find((w) => w.name === options.workflow || w.functionName === options.workflow)
|
|
779
|
+
: parseResult.workflows[0];
|
|
780
|
+
if (!workflow) {
|
|
781
|
+
const available = parseResult.workflows.map((w) => w.name).join(', ');
|
|
782
|
+
throw new Error(`Workflow "${options.workflow}" not found. Available: ${available}`);
|
|
783
|
+
}
|
|
784
|
+
// For dry-run, use temp directory for compilation
|
|
785
|
+
const workDir = isDryRun ? path.join(os.tmpdir(), `fw-export-dryrun-${Date.now()}`) : outputDir;
|
|
786
|
+
// Create working directory
|
|
787
|
+
fs.mkdirSync(workDir, { recursive: true });
|
|
788
|
+
let compiledContent;
|
|
789
|
+
let compiledPath;
|
|
790
|
+
try {
|
|
791
|
+
// Compile workflow to working directory
|
|
792
|
+
compiledPath = await compileToOutput(inputPath, workflow.functionName, workDir, options.production);
|
|
793
|
+
compiledContent = fs.readFileSync(compiledPath, 'utf8');
|
|
794
|
+
}
|
|
795
|
+
finally {
|
|
796
|
+
// Clean up temp directory in dry-run mode
|
|
797
|
+
if (isDryRun) {
|
|
798
|
+
try {
|
|
799
|
+
fs.rmSync(workDir, { recursive: true, force: true });
|
|
800
|
+
}
|
|
801
|
+
catch {
|
|
802
|
+
// Ignore cleanup errors
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
// Generate handler based on target
|
|
807
|
+
let handler;
|
|
808
|
+
if (options.target === 'inngest' && options.durableSteps) {
|
|
809
|
+
// Use deep generator for durable Inngest steps
|
|
810
|
+
const allNodeTypes = [...(workflow.nodeTypes || [])];
|
|
811
|
+
handler = generateInngestFunction(workflow, allNodeTypes, {
|
|
812
|
+
production: options.production ?? true,
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
handler = generateHandler(options.target, compiledPath, workflow.functionName);
|
|
817
|
+
}
|
|
818
|
+
// Determine output file name
|
|
819
|
+
const handlerFileName = getHandlerFileName(options.target, workflow.name);
|
|
820
|
+
const handlerPath = path.join(outputDir, handlerFileName);
|
|
821
|
+
const workflowOutputPath = path.join(outputDir, 'workflow.ts');
|
|
822
|
+
// Generate config files (use outputDir for paths even in dry-run)
|
|
823
|
+
const configFiles = generateConfigFiles(options.target, workflow.name, outputDir, workflow.description);
|
|
824
|
+
// Only write files if not a dry-run
|
|
825
|
+
if (!isDryRun) {
|
|
826
|
+
// Create output directory
|
|
827
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
828
|
+
// Write handler file (ensure parent directory exists for api/ subdirectory)
|
|
829
|
+
const handlerDir = path.dirname(handlerPath);
|
|
830
|
+
if (!fs.existsSync(handlerDir)) {
|
|
831
|
+
fs.mkdirSync(handlerDir, { recursive: true });
|
|
832
|
+
}
|
|
833
|
+
fs.writeFileSync(handlerPath, handler);
|
|
834
|
+
// Write config files
|
|
835
|
+
for (const file of configFiles) {
|
|
836
|
+
fs.writeFileSync(file.path, file.content);
|
|
837
|
+
}
|
|
838
|
+
// Write compiled workflow
|
|
839
|
+
fs.writeFileSync(workflowOutputPath, compiledContent);
|
|
840
|
+
}
|
|
841
|
+
const files = [
|
|
842
|
+
{ path: handlerPath, content: handler },
|
|
843
|
+
...configFiles,
|
|
844
|
+
{ path: workflowOutputPath, content: compiledContent },
|
|
845
|
+
];
|
|
846
|
+
return {
|
|
847
|
+
target: options.target,
|
|
848
|
+
files,
|
|
849
|
+
workflow: workflow.name,
|
|
850
|
+
description: workflow.description,
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Compile workflow to output directory
|
|
855
|
+
*/
|
|
856
|
+
async function compileToOutput(inputPath, functionName, outputDir, production) {
|
|
857
|
+
const outputPath = path.join(outputDir, 'workflow.ts');
|
|
858
|
+
// Copy source file to output
|
|
859
|
+
fs.copyFileSync(inputPath, outputPath);
|
|
860
|
+
// Compile in-place in the output directory
|
|
861
|
+
await compileWorkflow(outputPath, {
|
|
862
|
+
write: true,
|
|
863
|
+
inPlace: true,
|
|
864
|
+
parse: { workflowName: functionName },
|
|
865
|
+
generate: { production: production ?? true },
|
|
866
|
+
});
|
|
867
|
+
return outputPath;
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Generate handler code from template
|
|
871
|
+
*/
|
|
872
|
+
function generateHandler(target, workflowPath, functionName) {
|
|
873
|
+
const template = getTemplate(target);
|
|
874
|
+
// Vercel handlers live in api/ subdirectory, so import from parent
|
|
875
|
+
const relativePath = target === 'vercel'
|
|
876
|
+
? `../${path.basename(workflowPath).replace('.ts', '.js')}`
|
|
877
|
+
: `./${path.basename(workflowPath).replace('.ts', '.js')}`;
|
|
878
|
+
return template
|
|
879
|
+
.replace('{{GENERATED_HEADER}}', getGeneratedBranding().header(`export --target ${target}`))
|
|
880
|
+
.replace('{{WORKFLOW_IMPORT}}', `import { ${functionName} } from '${relativePath}';`)
|
|
881
|
+
.replace(/\{\{FUNCTION_NAME\}\}/g, functionName)
|
|
882
|
+
.replace('{{MAX_DURATION}}', '60');
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Get template for target platform
|
|
886
|
+
*/
|
|
887
|
+
function getTemplate(target) {
|
|
888
|
+
switch (target) {
|
|
889
|
+
case 'lambda':
|
|
890
|
+
return LAMBDA_TEMPLATE;
|
|
891
|
+
case 'vercel':
|
|
892
|
+
return VERCEL_TEMPLATE;
|
|
893
|
+
case 'cloudflare':
|
|
894
|
+
return CLOUDFLARE_TEMPLATE;
|
|
895
|
+
case 'inngest':
|
|
896
|
+
return INNGEST_TEMPLATE;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Get handler file name for target platform
|
|
901
|
+
*/
|
|
902
|
+
function getHandlerFileName(target, workflowName) {
|
|
903
|
+
switch (target) {
|
|
904
|
+
case 'lambda':
|
|
905
|
+
return 'handler.ts';
|
|
906
|
+
case 'vercel':
|
|
907
|
+
// Vercel uses file-based routing under api/
|
|
908
|
+
return `api/${workflowName}.ts`;
|
|
909
|
+
case 'cloudflare':
|
|
910
|
+
return 'index.ts';
|
|
911
|
+
case 'inngest':
|
|
912
|
+
return 'handler.ts';
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Generate config files for target platform
|
|
917
|
+
*/
|
|
918
|
+
function generateConfigFiles(target, workflowName, outputDir, description) {
|
|
919
|
+
const files = [];
|
|
920
|
+
switch (target) {
|
|
921
|
+
case 'lambda':
|
|
922
|
+
// Generate SAM template
|
|
923
|
+
files.push({
|
|
924
|
+
path: path.join(outputDir, 'template.yaml'),
|
|
925
|
+
content: SAM_TEMPLATE.replace(/\{\{WORKFLOW_NAME\}\}/g, workflowName)
|
|
926
|
+
.replace('{{WORKFLOW_DESCRIPTION}}', description || `Flow Weaver workflow: ${workflowName}`)
|
|
927
|
+
.replace(/\{\{WORKFLOW_PATH\}\}/g, workflowName),
|
|
928
|
+
});
|
|
929
|
+
// Generate package.json for Lambda
|
|
930
|
+
files.push({
|
|
931
|
+
path: path.join(outputDir, 'package.json'),
|
|
932
|
+
content: JSON.stringify({
|
|
933
|
+
name: `fw-${workflowName}`,
|
|
934
|
+
version: '1.0.0',
|
|
935
|
+
type: 'module',
|
|
936
|
+
main: 'handler.js',
|
|
937
|
+
scripts: {
|
|
938
|
+
build: 'tsc',
|
|
939
|
+
deploy: 'sam build && sam deploy --guided',
|
|
940
|
+
},
|
|
941
|
+
devDependencies: {
|
|
942
|
+
'@types/aws-lambda': '^8.10.0',
|
|
943
|
+
typescript: '^5.0.0',
|
|
944
|
+
},
|
|
945
|
+
}, null, 2),
|
|
946
|
+
});
|
|
947
|
+
// Generate tsconfig.json
|
|
948
|
+
files.push({
|
|
949
|
+
path: path.join(outputDir, 'tsconfig.json'),
|
|
950
|
+
content: JSON.stringify({
|
|
951
|
+
compilerOptions: {
|
|
952
|
+
target: 'ES2022',
|
|
953
|
+
module: 'NodeNext',
|
|
954
|
+
moduleResolution: 'NodeNext',
|
|
955
|
+
outDir: './dist',
|
|
956
|
+
strict: true,
|
|
957
|
+
esModuleInterop: true,
|
|
958
|
+
skipLibCheck: true,
|
|
959
|
+
},
|
|
960
|
+
include: ['*.ts'],
|
|
961
|
+
}, null, 2),
|
|
962
|
+
});
|
|
963
|
+
break;
|
|
964
|
+
case 'vercel':
|
|
965
|
+
// Generate vercel.json
|
|
966
|
+
files.push({
|
|
967
|
+
path: path.join(outputDir, 'vercel.json'),
|
|
968
|
+
content: JSON.stringify({
|
|
969
|
+
functions: {
|
|
970
|
+
[`api/${workflowName}.ts`]: {
|
|
971
|
+
memory: 1024,
|
|
972
|
+
maxDuration: 60,
|
|
973
|
+
},
|
|
974
|
+
},
|
|
975
|
+
}, null, 2),
|
|
976
|
+
});
|
|
977
|
+
break;
|
|
978
|
+
case 'cloudflare':
|
|
979
|
+
// Generate wrangler.toml
|
|
980
|
+
files.push({
|
|
981
|
+
path: path.join(outputDir, 'wrangler.toml'),
|
|
982
|
+
content: `name = "${workflowName}"
|
|
983
|
+
main = "dist/index.js"
|
|
984
|
+
compatibility_date = "2024-01-01"
|
|
985
|
+
|
|
986
|
+
[build]
|
|
987
|
+
command = "npm run build"
|
|
988
|
+
`,
|
|
989
|
+
});
|
|
990
|
+
// Generate package.json for Cloudflare
|
|
991
|
+
files.push({
|
|
992
|
+
path: path.join(outputDir, 'package.json'),
|
|
993
|
+
content: JSON.stringify({
|
|
994
|
+
name: `fw-${workflowName}`,
|
|
995
|
+
version: '1.0.0',
|
|
996
|
+
type: 'module',
|
|
997
|
+
scripts: {
|
|
998
|
+
build: 'tsc',
|
|
999
|
+
deploy: 'wrangler deploy',
|
|
1000
|
+
dev: 'wrangler dev',
|
|
1001
|
+
},
|
|
1002
|
+
devDependencies: {
|
|
1003
|
+
'@cloudflare/workers-types': '^4.0.0',
|
|
1004
|
+
typescript: '^5.0.0',
|
|
1005
|
+
wrangler: '^3.0.0',
|
|
1006
|
+
},
|
|
1007
|
+
}, null, 2),
|
|
1008
|
+
});
|
|
1009
|
+
// Generate tsconfig.json
|
|
1010
|
+
files.push({
|
|
1011
|
+
path: path.join(outputDir, 'tsconfig.json'),
|
|
1012
|
+
content: JSON.stringify({
|
|
1013
|
+
compilerOptions: {
|
|
1014
|
+
target: 'ES2022',
|
|
1015
|
+
module: 'ESNext',
|
|
1016
|
+
moduleResolution: 'Bundler',
|
|
1017
|
+
outDir: './dist',
|
|
1018
|
+
strict: true,
|
|
1019
|
+
skipLibCheck: true,
|
|
1020
|
+
types: ['@cloudflare/workers-types'],
|
|
1021
|
+
},
|
|
1022
|
+
include: ['*.ts'],
|
|
1023
|
+
}, null, 2),
|
|
1024
|
+
});
|
|
1025
|
+
break;
|
|
1026
|
+
case 'inngest':
|
|
1027
|
+
// Generate package.json for Inngest
|
|
1028
|
+
files.push({
|
|
1029
|
+
path: path.join(outputDir, 'package.json'),
|
|
1030
|
+
content: JSON.stringify({
|
|
1031
|
+
name: `fw-${workflowName}`,
|
|
1032
|
+
version: '1.0.0',
|
|
1033
|
+
type: 'module',
|
|
1034
|
+
main: 'handler.js',
|
|
1035
|
+
scripts: {
|
|
1036
|
+
build: 'tsc',
|
|
1037
|
+
dev: 'npx inngest-cli@latest dev & npx tsx handler.ts',
|
|
1038
|
+
serve: 'npx tsx handler.ts',
|
|
1039
|
+
},
|
|
1040
|
+
dependencies: {
|
|
1041
|
+
inngest: '^3.0.0',
|
|
1042
|
+
},
|
|
1043
|
+
devDependencies: {
|
|
1044
|
+
typescript: '^5.0.0',
|
|
1045
|
+
},
|
|
1046
|
+
}, null, 2),
|
|
1047
|
+
});
|
|
1048
|
+
// Generate tsconfig.json
|
|
1049
|
+
files.push({
|
|
1050
|
+
path: path.join(outputDir, 'tsconfig.json'),
|
|
1051
|
+
content: JSON.stringify({
|
|
1052
|
+
compilerOptions: {
|
|
1053
|
+
target: 'ES2022',
|
|
1054
|
+
module: 'NodeNext',
|
|
1055
|
+
moduleResolution: 'NodeNext',
|
|
1056
|
+
outDir: './dist',
|
|
1057
|
+
strict: true,
|
|
1058
|
+
esModuleInterop: true,
|
|
1059
|
+
skipLibCheck: true,
|
|
1060
|
+
},
|
|
1061
|
+
include: ['*.ts'],
|
|
1062
|
+
}, null, 2),
|
|
1063
|
+
});
|
|
1064
|
+
break;
|
|
1065
|
+
}
|
|
1066
|
+
return files;
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* List supported export targets
|
|
1070
|
+
*/
|
|
1071
|
+
export function getSupportedTargets() {
|
|
1072
|
+
return ['lambda', 'vercel', 'cloudflare', 'inngest'];
|
|
1073
|
+
}
|
|
1074
|
+
//# sourceMappingURL=index.js.map
|