@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,568 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orthogonal connection router for SVG diagram rendering.
|
|
3
|
+
*
|
|
4
|
+
* Ported from the original React-based editor's orthogonalRouter.ts.
|
|
5
|
+
* Removed gl-matrix dependency — uses plain [number, number] tuples.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - L-shape and S-shape routing with rounded corners
|
|
9
|
+
* - Node collision avoidance via inflated bounding boxes
|
|
10
|
+
* - Track allocator prevents parallel connections from overlapping
|
|
11
|
+
* - Crossing minimization (evaluates up to 11 candidates per allocation)
|
|
12
|
+
* - Per-port-index stub spacing
|
|
13
|
+
* - Waypoint simplification (collinear removal, jog collapse)
|
|
14
|
+
* - Backward/self connection escape routing
|
|
15
|
+
*/
|
|
16
|
+
// Minimum spacing between parallel horizontal segments (px)
|
|
17
|
+
const TRACK_SPACING = 15;
|
|
18
|
+
// Clearance from inflated box edges when routing around nodes (px).
|
|
19
|
+
const EDGE_OFFSET = 5;
|
|
20
|
+
// ─── Track allocator ───
|
|
21
|
+
// Maximum free candidates to evaluate in each direction for crossing minimization.
|
|
22
|
+
const MAX_CANDIDATES = 5;
|
|
23
|
+
export class TrackAllocator {
|
|
24
|
+
claims = [];
|
|
25
|
+
verticalClaims = [];
|
|
26
|
+
/** Check if a Y value is too close to any claimed segment whose X range overlaps. */
|
|
27
|
+
isOccupied(xMin, xMax, y) {
|
|
28
|
+
for (const c of this.claims) {
|
|
29
|
+
if (c.xMin < xMax && c.xMax > xMin && Math.abs(c.y - y) < TRACK_SPACING) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
/** Check if an X value is too close to any claimed vertical segment whose Y range overlaps. */
|
|
36
|
+
isOccupiedVertical(yMin, yMax, x) {
|
|
37
|
+
for (const c of this.verticalClaims) {
|
|
38
|
+
if (c.yMin < yMax && c.yMax > yMin && Math.abs(c.x - x) < TRACK_SPACING) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
/** Check if a horizontal segment at Y passes through any inflated node box. */
|
|
45
|
+
isBlockedByNode(xMin, xMax, y, boxes) {
|
|
46
|
+
for (const box of boxes) {
|
|
47
|
+
if (xMin < box.right && xMax > box.left && y >= box.top && y <= box.bottom) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
/** Check if a vertical segment at X passes through any inflated node box. */
|
|
54
|
+
isBlockedByNodeVertical(yMin, yMax, x, boxes) {
|
|
55
|
+
for (const box of boxes) {
|
|
56
|
+
if (x >= box.left && x <= box.right && yMin < box.bottom && yMax > box.top) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
/** Count claimed vertical segments that a horizontal segment at Y would cross. */
|
|
63
|
+
countHorizontalCrossings(xMin, xMax, y) {
|
|
64
|
+
let count = 0;
|
|
65
|
+
for (const c of this.verticalClaims) {
|
|
66
|
+
if (c.x > xMin && c.x < xMax && y >= c.yMin && y <= c.yMax) {
|
|
67
|
+
count++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return count;
|
|
71
|
+
}
|
|
72
|
+
/** Count claimed horizontal segments that a vertical segment at X would cross. */
|
|
73
|
+
countVerticalCrossings(yMin, yMax, x) {
|
|
74
|
+
let count = 0;
|
|
75
|
+
for (const c of this.claims) {
|
|
76
|
+
if (c.y > yMin && c.y < yMax && x >= c.xMin && x <= c.xMax) {
|
|
77
|
+
count++;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return count;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Find the nearest free Y to candidateY in the given X range, preferring fewer crossings.
|
|
84
|
+
* When nodeBoxes is provided, candidates inside inflated node boxes are rejected (hard constraint).
|
|
85
|
+
*/
|
|
86
|
+
findFreeY(xMin, xMax, candidateY, nodeBoxes) {
|
|
87
|
+
const isFree = (y) => !this.isOccupied(xMin, xMax, y) &&
|
|
88
|
+
(!nodeBoxes || !this.isBlockedByNode(xMin, xMax, y, nodeBoxes));
|
|
89
|
+
if (isFree(candidateY))
|
|
90
|
+
return candidateY;
|
|
91
|
+
const candidates = [];
|
|
92
|
+
for (let offset = TRACK_SPACING; offset < 800 && candidates.length < MAX_CANDIDATES * 2; offset += TRACK_SPACING) {
|
|
93
|
+
const above = candidateY - offset;
|
|
94
|
+
if (isFree(above)) {
|
|
95
|
+
candidates.push({ y: above, dist: offset });
|
|
96
|
+
}
|
|
97
|
+
const below = candidateY + offset;
|
|
98
|
+
if (isFree(below)) {
|
|
99
|
+
candidates.push({ y: below, dist: offset });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (candidates.length === 0)
|
|
103
|
+
return candidateY;
|
|
104
|
+
let bestY = candidates[0].y;
|
|
105
|
+
let bestCrossings = this.countHorizontalCrossings(xMin, xMax, candidates[0].y);
|
|
106
|
+
let bestDist = candidates[0].dist;
|
|
107
|
+
for (let i = 1; i < candidates.length; i++) {
|
|
108
|
+
const c = candidates[i];
|
|
109
|
+
const crossings = this.countHorizontalCrossings(xMin, xMax, c.y);
|
|
110
|
+
if (crossings < bestCrossings || (crossings === bestCrossings && c.dist < bestDist)) {
|
|
111
|
+
bestY = c.y;
|
|
112
|
+
bestCrossings = crossings;
|
|
113
|
+
bestDist = c.dist;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return bestY;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Find the nearest free X to candidateX in the given Y range, preferring fewer crossings.
|
|
120
|
+
* When nodeBoxes is provided, candidates inside inflated node boxes are rejected (hard constraint).
|
|
121
|
+
*/
|
|
122
|
+
findFreeX(yMin, yMax, candidateX, nodeBoxes) {
|
|
123
|
+
const isFree = (x) => !this.isOccupiedVertical(yMin, yMax, x) &&
|
|
124
|
+
(!nodeBoxes || !this.isBlockedByNodeVertical(yMin, yMax, x, nodeBoxes));
|
|
125
|
+
if (isFree(candidateX))
|
|
126
|
+
return candidateX;
|
|
127
|
+
const candidates = [];
|
|
128
|
+
for (let offset = TRACK_SPACING; offset < 800 && candidates.length < MAX_CANDIDATES * 2; offset += TRACK_SPACING) {
|
|
129
|
+
const left = candidateX - offset;
|
|
130
|
+
if (isFree(left)) {
|
|
131
|
+
candidates.push({ x: left, dist: offset });
|
|
132
|
+
}
|
|
133
|
+
const right = candidateX + offset;
|
|
134
|
+
if (isFree(right)) {
|
|
135
|
+
candidates.push({ x: right, dist: offset });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (candidates.length === 0)
|
|
139
|
+
return candidateX;
|
|
140
|
+
let bestX = candidates[0].x;
|
|
141
|
+
let bestCrossings = this.countVerticalCrossings(yMin, yMax, candidates[0].x);
|
|
142
|
+
let bestDist = candidates[0].dist;
|
|
143
|
+
for (let i = 1; i < candidates.length; i++) {
|
|
144
|
+
const c = candidates[i];
|
|
145
|
+
const crossings = this.countVerticalCrossings(yMin, yMax, c.x);
|
|
146
|
+
if (crossings < bestCrossings || (crossings === bestCrossings && c.dist < bestDist)) {
|
|
147
|
+
bestX = c.x;
|
|
148
|
+
bestCrossings = crossings;
|
|
149
|
+
bestDist = c.dist;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return bestX;
|
|
153
|
+
}
|
|
154
|
+
/** Claim a horizontal segment so later connections avoid it. */
|
|
155
|
+
claim(xMin, xMax, y) {
|
|
156
|
+
this.claims.push({ xMin, xMax, y });
|
|
157
|
+
}
|
|
158
|
+
/** Claim a vertical segment so later connections avoid it. */
|
|
159
|
+
claimVertical(yMin, yMax, x) {
|
|
160
|
+
this.verticalClaims.push({ yMin, yMax, x });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// ─── Node avoidance helpers ───
|
|
164
|
+
function inflateBox(box, padding) {
|
|
165
|
+
return {
|
|
166
|
+
left: box.x - padding,
|
|
167
|
+
right: box.x + box.width + padding,
|
|
168
|
+
top: box.y - padding,
|
|
169
|
+
bottom: box.y + box.height + padding,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function segmentOverlapsBox(xMin, xMax, y, box) {
|
|
173
|
+
return xMin < box.right && xMax > box.left && y >= box.top && y <= box.bottom;
|
|
174
|
+
}
|
|
175
|
+
/** Check if a vertical segment at a given X is clear of all inflated boxes. */
|
|
176
|
+
function verticalSegmentClear(x, yMin, yMax, boxes) {
|
|
177
|
+
return !boxes.some((box) => x >= box.left && x <= box.right && yMin < box.bottom && yMax > box.top);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Find a Y clear of node boxes for a horizontal segment spanning [xMin, xMax].
|
|
181
|
+
*/
|
|
182
|
+
function findClearY(xMin, xMax, candidateY, boxes) {
|
|
183
|
+
const isBlocked = (y) => boxes.some((box) => segmentOverlapsBox(xMin, xMax, y, box));
|
|
184
|
+
if (!isBlocked(candidateY))
|
|
185
|
+
return candidateY;
|
|
186
|
+
const edges = [];
|
|
187
|
+
for (const box of boxes) {
|
|
188
|
+
if (xMin < box.right && xMax > box.left) {
|
|
189
|
+
edges.push(box.top);
|
|
190
|
+
edges.push(box.bottom);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (edges.length === 0)
|
|
194
|
+
return candidateY;
|
|
195
|
+
edges.sort((a, b) => a - b);
|
|
196
|
+
let bestY = candidateY;
|
|
197
|
+
let bestDist = Infinity;
|
|
198
|
+
for (const edge of edges) {
|
|
199
|
+
for (const y of [edge - EDGE_OFFSET, edge + EDGE_OFFSET]) {
|
|
200
|
+
if (!isBlocked(y)) {
|
|
201
|
+
const dist = Math.abs(y - candidateY);
|
|
202
|
+
if (dist < bestDist) {
|
|
203
|
+
bestDist = dist;
|
|
204
|
+
bestY = y;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (bestDist === Infinity) {
|
|
210
|
+
const allMin = Math.min(...edges) - EDGE_OFFSET * 2;
|
|
211
|
+
const allMax = Math.max(...edges) + EDGE_OFFSET * 2;
|
|
212
|
+
bestY = Math.abs(allMin - candidateY) <= Math.abs(allMax - candidateY) ? allMin : allMax;
|
|
213
|
+
if (isBlocked(bestY)) {
|
|
214
|
+
for (let offset = TRACK_SPACING; offset < 800; offset += TRACK_SPACING) {
|
|
215
|
+
if (!isBlocked(bestY - offset)) {
|
|
216
|
+
bestY -= offset;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
if (!isBlocked(bestY + offset)) {
|
|
220
|
+
bestY += offset;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return bestY;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Find an X clear of node boxes for a vertical segment spanning [yMin, yMax].
|
|
230
|
+
*/
|
|
231
|
+
function findClearX(yMin, yMax, candidateX, boxes) {
|
|
232
|
+
const isBlocked = (x) => boxes.some((box) => x >= box.left && x <= box.right && yMin < box.bottom && yMax > box.top);
|
|
233
|
+
if (!isBlocked(candidateX))
|
|
234
|
+
return candidateX;
|
|
235
|
+
const edges = [];
|
|
236
|
+
for (const box of boxes) {
|
|
237
|
+
if (yMin < box.bottom && yMax > box.top) {
|
|
238
|
+
edges.push(box.left);
|
|
239
|
+
edges.push(box.right);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (edges.length === 0)
|
|
243
|
+
return candidateX;
|
|
244
|
+
edges.sort((a, b) => a - b);
|
|
245
|
+
let bestX = candidateX;
|
|
246
|
+
let bestDist = Infinity;
|
|
247
|
+
for (const edge of edges) {
|
|
248
|
+
for (const x of [edge - EDGE_OFFSET, edge + EDGE_OFFSET]) {
|
|
249
|
+
if (!isBlocked(x)) {
|
|
250
|
+
const dist = Math.abs(x - candidateX);
|
|
251
|
+
if (dist < bestDist) {
|
|
252
|
+
bestDist = dist;
|
|
253
|
+
bestX = x;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (bestDist === Infinity) {
|
|
259
|
+
const allMin = Math.min(...edges) - EDGE_OFFSET * 2;
|
|
260
|
+
const allMax = Math.max(...edges) + EDGE_OFFSET * 2;
|
|
261
|
+
bestX = Math.abs(allMin - candidateX) <= Math.abs(allMax - candidateX) ? allMin : allMax;
|
|
262
|
+
if (isBlocked(bestX)) {
|
|
263
|
+
for (let offset = TRACK_SPACING; offset < 800; offset += TRACK_SPACING) {
|
|
264
|
+
if (!isBlocked(bestX - offset)) {
|
|
265
|
+
bestX -= offset;
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
if (!isBlocked(bestX + offset)) {
|
|
269
|
+
bestX += offset;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return bestX;
|
|
276
|
+
}
|
|
277
|
+
// ─── Waypoint utilities ───
|
|
278
|
+
const MIN_SEGMENT_LENGTH = 3;
|
|
279
|
+
const JOG_THRESHOLD = 10;
|
|
280
|
+
/** Remove collinear, duplicate, tiny-jog, and very-short-segment waypoints. */
|
|
281
|
+
function simplifyWaypoints(waypoints) {
|
|
282
|
+
if (waypoints.length <= 2)
|
|
283
|
+
return waypoints;
|
|
284
|
+
// Pass 1: Collapse small rectangular jogs.
|
|
285
|
+
let pts = waypoints;
|
|
286
|
+
let jogFound = true;
|
|
287
|
+
while (jogFound) {
|
|
288
|
+
jogFound = false;
|
|
289
|
+
for (let i = 0; i < pts.length - 3; i++) {
|
|
290
|
+
const a = pts[i], b = pts[i + 1], c = pts[i + 2], d = pts[i + 3];
|
|
291
|
+
// Small vertical jog
|
|
292
|
+
const jogH = Math.abs(b[1] - c[1]);
|
|
293
|
+
if (Math.abs(a[1] - b[1]) < 0.5 &&
|
|
294
|
+
Math.abs(b[0] - c[0]) < 0.5 &&
|
|
295
|
+
Math.abs(c[1] - d[1]) < 0.5 &&
|
|
296
|
+
jogH > 0.5 && jogH < JOG_THRESHOLD) {
|
|
297
|
+
const jogMid = (b[1] + c[1]) / 2;
|
|
298
|
+
const snapY = Math.abs(a[1] - jogMid) <= Math.abs(d[1] - jogMid) ? a[1] : d[1];
|
|
299
|
+
const newPts = pts.slice();
|
|
300
|
+
newPts[i + 1] = [b[0], snapY];
|
|
301
|
+
newPts[i + 2] = [c[0], snapY];
|
|
302
|
+
pts = newPts;
|
|
303
|
+
jogFound = true;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
// Small horizontal jog
|
|
307
|
+
const jogW = Math.abs(b[0] - c[0]);
|
|
308
|
+
if (Math.abs(a[0] - b[0]) < 0.5 &&
|
|
309
|
+
Math.abs(b[1] - c[1]) < 0.5 &&
|
|
310
|
+
Math.abs(c[0] - d[0]) < 0.5 &&
|
|
311
|
+
jogW > 0.5 && jogW < JOG_THRESHOLD) {
|
|
312
|
+
const jogMid = (b[0] + c[0]) / 2;
|
|
313
|
+
const snapX = Math.abs(a[0] - jogMid) <= Math.abs(d[0] - jogMid) ? a[0] : d[0];
|
|
314
|
+
const newPts = pts.slice();
|
|
315
|
+
newPts[i + 1] = [snapX, b[1]];
|
|
316
|
+
newPts[i + 2] = [snapX, c[1]];
|
|
317
|
+
pts = newPts;
|
|
318
|
+
jogFound = true;
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// Pass 2: Remove near-duplicates and collinear points
|
|
324
|
+
const result = [pts[0]];
|
|
325
|
+
for (let i = 1; i < pts.length - 1; i++) {
|
|
326
|
+
const prev = result[result.length - 1];
|
|
327
|
+
const curr = pts[i];
|
|
328
|
+
const next = pts[i + 1];
|
|
329
|
+
const distToPrev = Math.abs(prev[0] - curr[0]) + Math.abs(prev[1] - curr[1]);
|
|
330
|
+
if (distToPrev < MIN_SEGMENT_LENGTH)
|
|
331
|
+
continue;
|
|
332
|
+
const sameX = Math.abs(prev[0] - curr[0]) < 0.01 && Math.abs(curr[0] - next[0]) < 0.01;
|
|
333
|
+
const sameY = Math.abs(prev[1] - curr[1]) < 0.01 && Math.abs(curr[1] - next[1]) < 0.01;
|
|
334
|
+
if (!sameX && !sameY) {
|
|
335
|
+
result.push(curr);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
result.push(pts[pts.length - 1]);
|
|
339
|
+
return result;
|
|
340
|
+
}
|
|
341
|
+
/** Convert waypoints to an SVG path with rounded corners. */
|
|
342
|
+
function waypointsToSvgPath(waypoints, cornerRadius) {
|
|
343
|
+
if (waypoints.length < 2)
|
|
344
|
+
return '';
|
|
345
|
+
if (waypoints.length === 2) {
|
|
346
|
+
return `M ${waypoints[0][0]},${waypoints[0][1]} L ${waypoints[1][0]},${waypoints[1][1]}`;
|
|
347
|
+
}
|
|
348
|
+
// Pre-compute arc radii so adjacent corners sharing a segment never overlap
|
|
349
|
+
const radii = new Array(waypoints.length).fill(0);
|
|
350
|
+
for (let i = 1; i < waypoints.length - 1; i++) {
|
|
351
|
+
const prev = waypoints[i - 1];
|
|
352
|
+
const curr = waypoints[i];
|
|
353
|
+
const next = waypoints[i + 1];
|
|
354
|
+
const lenPrev = Math.sqrt((prev[0] - curr[0]) ** 2 + (prev[1] - curr[1]) ** 2);
|
|
355
|
+
const lenNext = Math.sqrt((next[0] - curr[0]) ** 2 + (next[1] - curr[1]) ** 2);
|
|
356
|
+
radii[i] =
|
|
357
|
+
lenPrev < 0.01 || lenNext < 0.01 ? 0 : Math.min(cornerRadius, lenPrev / 2, lenNext / 2);
|
|
358
|
+
}
|
|
359
|
+
// Shrink radii so two corners sharing a segment together consume at most the full segment length
|
|
360
|
+
for (let i = 1; i < waypoints.length - 2; i++) {
|
|
361
|
+
const curr = waypoints[i];
|
|
362
|
+
const next = waypoints[i + 1];
|
|
363
|
+
const segLen = Math.sqrt((next[0] - curr[0]) ** 2 + (next[1] - curr[1]) ** 2);
|
|
364
|
+
const total = radii[i] + radii[i + 1];
|
|
365
|
+
if (total > segLen && total > 0) {
|
|
366
|
+
const scale = segLen / total;
|
|
367
|
+
radii[i] *= scale;
|
|
368
|
+
radii[i + 1] *= scale;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
let path = `M ${waypoints[0][0]},${waypoints[0][1]}`;
|
|
372
|
+
for (let i = 1; i < waypoints.length - 1; i++) {
|
|
373
|
+
const prev = waypoints[i - 1];
|
|
374
|
+
const curr = waypoints[i];
|
|
375
|
+
const next = waypoints[i + 1];
|
|
376
|
+
const r = radii[i];
|
|
377
|
+
if (r < 2) {
|
|
378
|
+
path += ` L ${curr[0]},${curr[1]}`;
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const dPrev = [prev[0] - curr[0], prev[1] - curr[1]];
|
|
382
|
+
const dNext = [next[0] - curr[0], next[1] - curr[1]];
|
|
383
|
+
const lenPrev = Math.sqrt(dPrev[0] * dPrev[0] + dPrev[1] * dPrev[1]);
|
|
384
|
+
const lenNext = Math.sqrt(dNext[0] * dNext[0] + dNext[1] * dNext[1]);
|
|
385
|
+
const uPrev = [dPrev[0] / lenPrev, dPrev[1] / lenPrev];
|
|
386
|
+
const uNext = [dNext[0] / lenNext, dNext[1] / lenNext];
|
|
387
|
+
const arcStart = [curr[0] + uPrev[0] * r, curr[1] + uPrev[1] * r];
|
|
388
|
+
const arcEnd = [curr[0] + uNext[0] * r, curr[1] + uNext[1] * r];
|
|
389
|
+
const cross = dPrev[0] * dNext[1] - dPrev[1] * dNext[0];
|
|
390
|
+
const sweep = cross > 0 ? 0 : 1;
|
|
391
|
+
path += ` L ${arcStart[0]},${arcStart[1]}`;
|
|
392
|
+
path += ` A ${r} ${r} 0 0 ${sweep} ${arcEnd[0]},${arcEnd[1]}`;
|
|
393
|
+
}
|
|
394
|
+
const last = waypoints[waypoints.length - 1];
|
|
395
|
+
path += ` L ${last[0]},${last[1]}`;
|
|
396
|
+
return path;
|
|
397
|
+
}
|
|
398
|
+
// ─── Waypoint computation ───
|
|
399
|
+
function computeWaypoints(from, to, nodeBoxes, sourceNodeId, targetNodeId, padding, exitStub, entryStub, allocator) {
|
|
400
|
+
const isSelfConnection = sourceNodeId === targetNodeId;
|
|
401
|
+
const inflatedBoxes = nodeBoxes
|
|
402
|
+
.filter((box) => (isSelfConnection ? true : box.id !== sourceNodeId && box.id !== targetNodeId))
|
|
403
|
+
.map((box) => inflateBox(box, padding));
|
|
404
|
+
const stubExit = [from[0] + exitStub, from[1]];
|
|
405
|
+
const stubEntry = [to[0] - entryStub, to[1]];
|
|
406
|
+
const xMin = Math.min(stubExit[0], stubEntry[0]);
|
|
407
|
+
const xMax = Math.max(stubExit[0], stubEntry[0]);
|
|
408
|
+
if (!isSelfConnection && to[0] > from[0]) {
|
|
409
|
+
// Forward connection
|
|
410
|
+
let candidateY = (from[1] + to[1]) / 2;
|
|
411
|
+
const intermediateBoxes = inflatedBoxes.filter((box) => box.left < xMax && box.right > xMin);
|
|
412
|
+
if (intermediateBoxes.length >= 2) {
|
|
413
|
+
const clusterTop = Math.min(...intermediateBoxes.map((b) => b.top));
|
|
414
|
+
const clusterBottom = Math.max(...intermediateBoxes.map((b) => b.bottom));
|
|
415
|
+
if (candidateY > clusterTop && candidateY < clusterBottom) {
|
|
416
|
+
const distToTop = candidateY - clusterTop;
|
|
417
|
+
const distToBottom = clusterBottom - candidateY;
|
|
418
|
+
candidateY = distToTop <= distToBottom
|
|
419
|
+
? clusterTop - padding
|
|
420
|
+
: clusterBottom + padding;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
let clearY = findClearY(xMin, xMax, candidateY, inflatedBoxes);
|
|
424
|
+
if (Math.abs(from[1] - to[1]) < JOG_THRESHOLD && Math.abs(clearY - from[1]) < JOG_THRESHOLD) {
|
|
425
|
+
return null; // Fall back to bezier
|
|
426
|
+
}
|
|
427
|
+
// Try center-corner: single vertical turn at the midpoint
|
|
428
|
+
const midX = (stubExit[0] + stubEntry[0]) / 2;
|
|
429
|
+
const yMin = Math.min(from[1], to[1]);
|
|
430
|
+
const yMax = Math.max(from[1], to[1]);
|
|
431
|
+
const clearMidX = findClearX(yMin, yMax, midX, inflatedBoxes);
|
|
432
|
+
const freeMidX = allocator.findFreeX(yMin, yMax, clearMidX, inflatedBoxes);
|
|
433
|
+
if (yMax - yMin >= JOG_THRESHOLD &&
|
|
434
|
+
freeMidX > stubExit[0] &&
|
|
435
|
+
freeMidX < stubEntry[0] &&
|
|
436
|
+
verticalSegmentClear(freeMidX, yMin, yMax, inflatedBoxes) &&
|
|
437
|
+
allocator.findFreeY(from[0], freeMidX, from[1], inflatedBoxes) === from[1] &&
|
|
438
|
+
allocator.findFreeY(freeMidX, to[0], to[1], inflatedBoxes) === to[1]) {
|
|
439
|
+
allocator.claim(from[0], freeMidX, from[1]);
|
|
440
|
+
allocator.claim(freeMidX, to[0], to[1]);
|
|
441
|
+
allocator.claimVertical(yMin, yMax, freeMidX);
|
|
442
|
+
return simplifyWaypoints([from, [freeMidX, from[1]], [freeMidX, to[1]], to]);
|
|
443
|
+
}
|
|
444
|
+
// S-shape with horizontal channel
|
|
445
|
+
clearY = allocator.findFreeY(xMin, xMax, clearY, inflatedBoxes);
|
|
446
|
+
if (Math.abs(clearY - from[1]) < JOG_THRESHOLD &&
|
|
447
|
+
!inflatedBoxes.some((box) => segmentOverlapsBox(xMin, xMax, from[1], box))) {
|
|
448
|
+
clearY = from[1];
|
|
449
|
+
}
|
|
450
|
+
else if (Math.abs(clearY - to[1]) < JOG_THRESHOLD &&
|
|
451
|
+
!inflatedBoxes.some((box) => segmentOverlapsBox(xMin, xMax, to[1], box))) {
|
|
452
|
+
clearY = to[1];
|
|
453
|
+
}
|
|
454
|
+
allocator.claim(xMin, xMax, clearY);
|
|
455
|
+
// Validate vertical segments
|
|
456
|
+
const exitYMin = Math.min(from[1], clearY);
|
|
457
|
+
const exitYMax = Math.max(from[1], clearY);
|
|
458
|
+
let exitX = findClearX(exitYMin, exitYMax, stubExit[0], inflatedBoxes);
|
|
459
|
+
exitX = allocator.findFreeX(exitYMin, exitYMax, exitX, inflatedBoxes);
|
|
460
|
+
if (exitX < from[0]) {
|
|
461
|
+
exitX = stubExit[0];
|
|
462
|
+
if (!verticalSegmentClear(exitX, exitYMin, exitYMax, inflatedBoxes)) {
|
|
463
|
+
exitX = findClearX(exitYMin, exitYMax, stubExit[0] + TRACK_SPACING, inflatedBoxes);
|
|
464
|
+
exitX = allocator.findFreeX(exitYMin, exitYMax, exitX, inflatedBoxes);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
allocator.claimVertical(exitYMin, exitYMax, exitX);
|
|
468
|
+
const entryYMin = Math.min(to[1], clearY);
|
|
469
|
+
const entryYMax = Math.max(to[1], clearY);
|
|
470
|
+
let entryX = findClearX(entryYMin, entryYMax, stubEntry[0], inflatedBoxes);
|
|
471
|
+
entryX = allocator.findFreeX(entryYMin, entryYMax, entryX, inflatedBoxes);
|
|
472
|
+
if (entryX > to[0]) {
|
|
473
|
+
entryX = stubEntry[0];
|
|
474
|
+
if (!verticalSegmentClear(entryX, entryYMin, entryYMax, inflatedBoxes)) {
|
|
475
|
+
entryX = findClearX(entryYMin, entryYMax, stubEntry[0] - TRACK_SPACING, inflatedBoxes);
|
|
476
|
+
entryX = allocator.findFreeX(entryYMin, entryYMax, entryX, inflatedBoxes);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
allocator.claimVertical(entryYMin, entryYMax, entryX);
|
|
480
|
+
return simplifyWaypoints([
|
|
481
|
+
from,
|
|
482
|
+
[exitX, from[1]],
|
|
483
|
+
[exitX, clearY],
|
|
484
|
+
[entryX, clearY],
|
|
485
|
+
[entryX, to[1]],
|
|
486
|
+
to,
|
|
487
|
+
]);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
// Backward connection or self-connection — escape vertically, loop around
|
|
491
|
+
const sourceBox = nodeBoxes.find((b) => b.id === sourceNodeId);
|
|
492
|
+
const targetBox = nodeBoxes.find((b) => b.id === targetNodeId);
|
|
493
|
+
const corridorBoxes = inflatedBoxes.filter((box) => box.left < xMax && box.right > xMin);
|
|
494
|
+
const bottoms = corridorBoxes.map((b) => b.bottom);
|
|
495
|
+
const tops = corridorBoxes.map((b) => b.top);
|
|
496
|
+
if (sourceBox) {
|
|
497
|
+
bottoms.push(sourceBox.y + sourceBox.height + padding);
|
|
498
|
+
tops.push(sourceBox.y - padding);
|
|
499
|
+
}
|
|
500
|
+
if (targetBox) {
|
|
501
|
+
bottoms.push(targetBox.y + targetBox.height + padding);
|
|
502
|
+
tops.push(targetBox.y - padding);
|
|
503
|
+
}
|
|
504
|
+
const maxBottom = Math.max(...bottoms, from[1] + 50, to[1] + 50);
|
|
505
|
+
const minTop = Math.min(...tops, from[1] - 50, to[1] - 50);
|
|
506
|
+
const avgY = (from[1] + to[1]) / 2;
|
|
507
|
+
const escapeBelow = maxBottom + padding;
|
|
508
|
+
const escapeAbove = minTop - padding;
|
|
509
|
+
let escapeY = Math.abs(escapeAbove - avgY) <= Math.abs(escapeBelow - avgY) ? escapeAbove : escapeBelow;
|
|
510
|
+
escapeY = findClearY(xMin, xMax, escapeY, inflatedBoxes);
|
|
511
|
+
escapeY = allocator.findFreeY(xMin, xMax, escapeY, inflatedBoxes);
|
|
512
|
+
allocator.claim(xMin, xMax, escapeY);
|
|
513
|
+
const bwExitYMin = Math.min(from[1], escapeY);
|
|
514
|
+
const bwExitYMax = Math.max(from[1], escapeY);
|
|
515
|
+
let bwExitX = findClearX(bwExitYMin, bwExitYMax, stubExit[0], inflatedBoxes);
|
|
516
|
+
bwExitX = allocator.findFreeX(bwExitYMin, bwExitYMax, bwExitX, inflatedBoxes);
|
|
517
|
+
allocator.claimVertical(bwExitYMin, bwExitYMax, bwExitX);
|
|
518
|
+
const bwEntryYMin = Math.min(to[1], escapeY);
|
|
519
|
+
const bwEntryYMax = Math.max(to[1], escapeY);
|
|
520
|
+
let bwEntryX = findClearX(bwEntryYMin, bwEntryYMax, stubEntry[0], inflatedBoxes);
|
|
521
|
+
bwEntryX = allocator.findFreeX(bwEntryYMin, bwEntryYMax, bwEntryX, inflatedBoxes);
|
|
522
|
+
allocator.claimVertical(bwEntryYMin, bwEntryYMax, bwEntryX);
|
|
523
|
+
return simplifyWaypoints([
|
|
524
|
+
from,
|
|
525
|
+
[bwExitX, from[1]],
|
|
526
|
+
[bwExitX, escapeY],
|
|
527
|
+
[bwEntryX, escapeY],
|
|
528
|
+
[bwEntryX, to[1]],
|
|
529
|
+
to,
|
|
530
|
+
]);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
// ─── Public API ───
|
|
534
|
+
/**
|
|
535
|
+
* Calculate an orthogonal SVG path between two ports.
|
|
536
|
+
* Returns null if the path should fall back to bezier (e.g. nearly aligned ports).
|
|
537
|
+
*/
|
|
538
|
+
export function calculateOrthogonalPath(from, to, nodeBoxes, sourceNodeId, targetNodeId, options, allocator) {
|
|
539
|
+
const cornerRadius = options?.cornerRadius ?? 10;
|
|
540
|
+
const padding = options?.padding ?? 15;
|
|
541
|
+
const stubLength = options?.stubLength ?? 20;
|
|
542
|
+
const stubSpacing = options?.stubSpacing ?? 12;
|
|
543
|
+
const maxStubLength = options?.maxStubLength ?? 80;
|
|
544
|
+
const fromPortIndex = options?.fromPortIndex ?? 0;
|
|
545
|
+
const toPortIndex = options?.toPortIndex ?? 0;
|
|
546
|
+
const exitStub = Math.min(stubLength + fromPortIndex * stubSpacing, maxStubLength);
|
|
547
|
+
const entryStub = Math.min(stubLength + toPortIndex * stubSpacing, maxStubLength);
|
|
548
|
+
const alloc = allocator ?? new TrackAllocator();
|
|
549
|
+
const waypoints = computeWaypoints(from, to, nodeBoxes, sourceNodeId, targetNodeId, padding, exitStub, entryStub, alloc);
|
|
550
|
+
if (!waypoints)
|
|
551
|
+
return null;
|
|
552
|
+
return waypointsToSvgPath(waypoints, cornerRadius);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Safe wrapper — returns null if routing fails, caller falls back to bezier.
|
|
556
|
+
*/
|
|
557
|
+
export function calculateOrthogonalPathSafe(from, to, nodeBoxes, sourceNodeId, targetNodeId, options, allocator) {
|
|
558
|
+
try {
|
|
559
|
+
const path = calculateOrthogonalPath(from, to, nodeBoxes, sourceNodeId, targetNodeId, options, allocator);
|
|
560
|
+
if (!path || path.length < 5)
|
|
561
|
+
return null;
|
|
562
|
+
return path;
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
//# sourceMappingURL=orthogonal-router.js.map
|