callman-core 1.28.1 → 1.30.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/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/outputSchemas.d.ts +3 -0
- package/dist/ai/outputSchemas.d.ts.map +1 -1
- package/dist/ai/outputSchemas.js +1 -0
- package/dist/ai/outputSchemas.js.map +1 -1
- package/dist/ai/parse/diagram.d.ts.map +1 -1
- package/dist/ai/parse/diagram.js +6 -3
- package/dist/ai/parse/diagram.js.map +1 -1
- package/dist/ai/prompts/diagram.d.ts +7 -3
- package/dist/ai/prompts/diagram.d.ts.map +1 -1
- package/dist/ai/prompts/diagram.js +61 -5
- package/dist/ai/prompts/diagram.js.map +1 -1
- package/dist/ai/types.d.ts +6 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/diagram/bpmn/derive.d.ts +74 -0
- package/dist/diagram/bpmn/derive.d.ts.map +1 -0
- package/dist/diagram/bpmn/derive.js +392 -0
- package/dist/diagram/bpmn/derive.js.map +1 -0
- package/dist/diagram/bpmn/index.d.ts +7 -0
- package/dist/diagram/bpmn/index.d.ts.map +1 -0
- package/dist/diagram/bpmn/index.js +12 -0
- package/dist/diagram/bpmn/index.js.map +1 -0
- package/dist/diagram/bpmn/patch.d.ts +14 -0
- package/dist/diagram/bpmn/patch.d.ts.map +1 -0
- package/dist/diagram/bpmn/patch.js +770 -0
- package/dist/diagram/bpmn/patch.js.map +1 -0
- package/dist/diagram/bpmn/place.d.ts +4 -0
- package/dist/diagram/bpmn/place.d.ts.map +1 -0
- package/dist/diagram/bpmn/place.js +65 -0
- package/dist/diagram/bpmn/place.js.map +1 -0
- package/dist/diagram/bpmn/serialize.d.ts +12 -0
- package/dist/diagram/bpmn/serialize.d.ts.map +1 -0
- package/dist/diagram/bpmn/serialize.js +292 -0
- package/dist/diagram/bpmn/serialize.js.map +1 -0
- package/dist/diagram/bpmn/types.d.ts +42 -0
- package/dist/diagram/bpmn/types.d.ts.map +1 -0
- package/dist/diagram/bpmn/types.js +84 -0
- package/dist/diagram/bpmn/types.js.map +1 -0
- package/dist/diagram/bpmn/xml.d.ts +60 -0
- package/dist/diagram/bpmn/xml.d.ts.map +1 -0
- package/dist/diagram/bpmn/xml.js +342 -0
- package/dist/diagram/bpmn/xml.js.map +1 -0
- package/dist/diagram/componentCatalog.d.ts +3 -0
- package/dist/diagram/componentCatalog.d.ts.map +1 -1
- package/dist/diagram/componentCatalog.js +5 -1
- package/dist/diagram/componentCatalog.js.map +1 -1
- package/dist/diagram/database/derive.d.ts +14 -0
- package/dist/diagram/database/derive.d.ts.map +1 -0
- package/dist/diagram/database/derive.js +114 -0
- package/dist/diagram/database/derive.js.map +1 -0
- package/dist/diagram/database/diff.d.ts +48 -0
- package/dist/diagram/database/diff.d.ts.map +1 -0
- package/dist/diagram/database/diff.js +109 -0
- package/dist/diagram/database/diff.js.map +1 -0
- package/dist/diagram/database/edit.d.ts +113 -0
- package/dist/diagram/database/edit.d.ts.map +1 -0
- package/dist/diagram/database/edit.js +359 -0
- package/dist/diagram/database/edit.js.map +1 -0
- package/dist/diagram/database/fromSchema.d.ts +12 -0
- package/dist/diagram/database/fromSchema.d.ts.map +1 -0
- package/dist/diagram/database/fromSchema.js +182 -0
- package/dist/diagram/database/fromSchema.js.map +1 -0
- package/dist/diagram/database/index.d.ts +9 -0
- package/dist/diagram/database/index.d.ts.map +1 -0
- package/dist/diagram/database/index.js +14 -0
- package/dist/diagram/database/index.js.map +1 -0
- package/dist/diagram/database/model.d.ts +93 -0
- package/dist/diagram/database/model.d.ts.map +1 -0
- package/dist/diagram/database/model.js +294 -0
- package/dist/diagram/database/model.js.map +1 -0
- package/dist/diagram/database/patch.d.ts +14 -0
- package/dist/diagram/database/patch.d.ts.map +1 -0
- package/dist/diagram/database/patch.js +186 -0
- package/dist/diagram/database/patch.js.map +1 -0
- package/dist/diagram/database/place.d.ts +4 -0
- package/dist/diagram/database/place.d.ts.map +1 -0
- package/dist/diagram/database/place.js +22 -0
- package/dist/diagram/database/place.js.map +1 -0
- package/dist/diagram/database/types.d.ts +50 -0
- package/dist/diagram/database/types.d.ts.map +1 -0
- package/dist/diagram/database/types.js +106 -0
- package/dist/diagram/database/types.js.map +1 -0
- package/dist/diagram/elkGraph.d.ts +1 -3
- package/dist/diagram/elkGraph.d.ts.map +1 -1
- package/dist/diagram/elkGraph.js +1 -0
- package/dist/diagram/elkGraph.js.map +1 -1
- package/dist/diagram/fixtures.d.ts +10 -0
- package/dist/diagram/fixtures.d.ts.map +1 -0
- package/dist/diagram/fixtures.js +113 -0
- package/dist/diagram/fixtures.js.map +1 -0
- package/dist/diagram/geometry.d.ts +27 -0
- package/dist/diagram/geometry.d.ts.map +1 -0
- package/dist/diagram/geometry.js +122 -0
- package/dist/diagram/geometry.js.map +1 -0
- package/dist/diagram/history.d.ts +36 -0
- package/dist/diagram/history.d.ts.map +1 -0
- package/dist/diagram/history.js +54 -0
- package/dist/diagram/history.js.map +1 -0
- package/dist/diagram/ids.d.ts +5 -0
- package/dist/diagram/ids.d.ts.map +1 -0
- package/dist/diagram/ids.js +52 -0
- package/dist/diagram/ids.js.map +1 -0
- package/dist/diagram/index.d.ts +15 -2
- package/dist/diagram/index.d.ts.map +1 -1
- package/dist/diagram/index.js +21 -8
- package/dist/diagram/index.js.map +1 -1
- package/dist/diagram/layout.d.ts +108 -0
- package/dist/diagram/layout.d.ts.map +1 -0
- package/dist/diagram/layout.js +357 -0
- package/dist/diagram/layout.js.map +1 -0
- package/dist/diagram/mermaid/derive.d.ts +55 -0
- package/dist/diagram/mermaid/derive.d.ts.map +1 -0
- package/dist/diagram/mermaid/derive.js +343 -0
- package/dist/diagram/mermaid/derive.js.map +1 -0
- package/dist/diagram/mermaid/index.d.ts +8 -0
- package/dist/diagram/mermaid/index.d.ts.map +1 -0
- package/dist/diagram/mermaid/index.js +24 -0
- package/dist/diagram/mermaid/index.js.map +1 -0
- package/dist/diagram/mermaid/parse.d.ts +96 -0
- package/dist/diagram/mermaid/parse.d.ts.map +1 -0
- package/dist/diagram/mermaid/parse.js +672 -0
- package/dist/diagram/mermaid/parse.js.map +1 -0
- package/dist/diagram/mermaid/patch.d.ts +16 -0
- package/dist/diagram/mermaid/patch.d.ts.map +1 -0
- package/dist/diagram/mermaid/patch.js +463 -0
- package/dist/diagram/mermaid/patch.js.map +1 -0
- package/dist/diagram/mermaid/serialize.d.ts +14 -0
- package/dist/diagram/mermaid/serialize.d.ts.map +1 -0
- package/dist/diagram/mermaid/serialize.js +125 -0
- package/dist/diagram/mermaid/serialize.js.map +1 -0
- package/dist/diagram/mermaid/shapes.d.ts +11 -0
- package/dist/diagram/mermaid/shapes.d.ts.map +1 -0
- package/dist/diagram/mermaid/shapes.js +320 -0
- package/dist/diagram/mermaid/shapes.js.map +1 -0
- package/dist/diagram/migrations.d.ts +1 -0
- package/dist/diagram/migrations.d.ts.map +1 -1
- package/dist/diagram/migrations.js +7 -2
- package/dist/diagram/migrations.js.map +1 -1
- package/dist/diagram/normalize.d.ts +9 -1
- package/dist/diagram/normalize.d.ts.map +1 -1
- package/dist/diagram/normalize.js +194 -0
- package/dist/diagram/normalize.js.map +1 -1
- package/dist/diagram/ops.d.ts +146 -0
- package/dist/diagram/ops.d.ts.map +1 -0
- package/dist/diagram/ops.js +865 -0
- package/dist/diagram/ops.js.map +1 -0
- package/dist/diagram/opsReference.d.ts +3 -0
- package/dist/diagram/opsReference.d.ts.map +1 -0
- package/dist/diagram/opsReference.js +60 -0
- package/dist/diagram/opsReference.js.map +1 -0
- package/dist/diagram/patchInput.d.ts +257 -0
- package/dist/diagram/patchInput.d.ts.map +1 -0
- package/dist/diagram/patchInput.js +1024 -0
- package/dist/diagram/patchInput.js.map +1 -0
- package/dist/diagram/routing/batch.d.ts +45 -0
- package/dist/diagram/routing/batch.d.ts.map +1 -0
- package/dist/diagram/routing/batch.js +136 -0
- package/dist/diagram/routing/batch.js.map +1 -0
- package/dist/diagram/routing/curves.d.ts +7 -0
- package/dist/diagram/routing/curves.d.ts.map +1 -0
- package/dist/diagram/routing/curves.js +120 -0
- package/dist/diagram/routing/curves.js.map +1 -0
- package/dist/diagram/routing/grid.d.ts +15 -0
- package/dist/diagram/routing/grid.d.ts.map +1 -0
- package/dist/diagram/routing/grid.js +245 -0
- package/dist/diagram/routing/grid.js.map +1 -0
- package/dist/diagram/routing/index.d.ts +10 -0
- package/dist/diagram/routing/index.d.ts.map +1 -0
- package/dist/diagram/routing/index.js +10 -0
- package/dist/diagram/routing/index.js.map +1 -0
- package/dist/diagram/routing/legacy.d.ts +6 -0
- package/dist/diagram/routing/legacy.d.ts.map +1 -0
- package/dist/diagram/routing/legacy.js +27 -0
- package/dist/diagram/routing/legacy.js.map +1 -0
- package/dist/diagram/routing/nudge.d.ts +4 -0
- package/dist/diagram/routing/nudge.d.ts.map +1 -0
- package/dist/diagram/routing/nudge.js +96 -0
- package/dist/diagram/routing/nudge.js.map +1 -0
- package/dist/diagram/routing/orthogonal.d.ts +6 -0
- package/dist/diagram/routing/orthogonal.d.ts.map +1 -0
- package/dist/diagram/routing/orthogonal.js +56 -0
- package/dist/diagram/routing/orthogonal.js.map +1 -0
- package/dist/diagram/routing/path.d.ts +16 -0
- package/dist/diagram/routing/path.d.ts.map +1 -0
- package/dist/diagram/routing/path.js +128 -0
- package/dist/diagram/routing/path.js.map +1 -0
- package/dist/diagram/routing/sides.d.ts +22 -0
- package/dist/diagram/routing/sides.d.ts.map +1 -0
- package/dist/diagram/routing/sides.js +74 -0
- package/dist/diagram/routing/sides.js.map +1 -0
- package/dist/diagram/routing/types.d.ts +46 -0
- package/dist/diagram/routing/types.d.ts.map +1 -0
- package/dist/diagram/routing/types.js +11 -0
- package/dist/diagram/routing/types.js.map +1 -0
- package/dist/diagram/schema.d.ts +71 -38
- package/dist/diagram/schema.d.ts.map +1 -1
- package/dist/diagram/schema.js +62 -8
- package/dist/diagram/schema.js.map +1 -1
- package/dist/diagram/styleInput.d.ts +41 -0
- package/dist/diagram/styleInput.d.ts.map +1 -0
- package/dist/diagram/styleInput.js +105 -0
- package/dist/diagram/styleInput.js.map +1 -0
- package/dist/diagram/views.d.ts +22 -0
- package/dist/diagram/views.d.ts.map +1 -0
- package/dist/diagram/views.js +91 -0
- package/dist/diagram/views.js.map +1 -0
- package/dist/host/db/introspection/index.d.ts +9 -0
- package/dist/host/db/introspection/index.d.ts.map +1 -0
- package/dist/host/db/introspection/index.js +35 -0
- package/dist/host/db/introspection/index.js.map +1 -0
- package/dist/host/db/introspection/mongo.d.ts +7 -0
- package/dist/host/db/introspection/mongo.d.ts.map +1 -0
- package/dist/host/db/introspection/mongo.js +183 -0
- package/dist/host/db/introspection/mongo.js.map +1 -0
- package/dist/host/db/introspection/mssql.d.ts +6 -0
- package/dist/host/db/introspection/mssql.d.ts.map +1 -0
- package/dist/host/db/introspection/mssql.js +211 -0
- package/dist/host/db/introspection/mssql.js.map +1 -0
- package/dist/host/db/introspection/mysql.d.ts +5 -0
- package/dist/host/db/introspection/mysql.d.ts.map +1 -0
- package/dist/host/db/introspection/mysql.js +163 -0
- package/dist/host/db/introspection/mysql.js.map +1 -0
- package/dist/host/db/introspection/oracle.d.ts +12 -0
- package/dist/host/db/introspection/oracle.d.ts.map +1 -0
- package/dist/host/db/introspection/oracle.js +225 -0
- package/dist/host/db/introspection/oracle.js.map +1 -0
- package/dist/host/db/introspection/postgres.d.ts +5 -0
- package/dist/host/db/introspection/postgres.d.ts.map +1 -0
- package/dist/host/db/introspection/postgres.js +172 -0
- package/dist/host/db/introspection/postgres.js.map +1 -0
- package/dist/host/db/introspection/shared.d.ts +29 -0
- package/dist/host/db/introspection/shared.d.ts.map +1 -0
- package/dist/host/db/introspection/shared.js +119 -0
- package/dist/host/db/introspection/shared.js.map +1 -0
- package/dist/host/db/introspection/types.d.ts +58 -0
- package/dist/host/db/introspection/types.d.ts.map +1 -0
- package/dist/host/db/introspection/types.js +6 -0
- package/dist/host/db/introspection/types.js.map +1 -0
- package/dist/host/db/mongoAdapter.d.ts +1 -0
- package/dist/host/db/mongoAdapter.d.ts.map +1 -1
- package/dist/host/db/mongoAdapter.js +13 -0
- package/dist/host/db/mongoAdapter.js.map +1 -1
- package/dist/host/db/mssqlAdapter.d.ts +1 -0
- package/dist/host/db/mssqlAdapter.d.ts.map +1 -1
- package/dist/host/db/mssqlAdapter.js +3 -1
- package/dist/host/db/mssqlAdapter.js.map +1 -1
- package/dist/host/db/mysqlAdapter.d.ts +1 -0
- package/dist/host/db/mysqlAdapter.d.ts.map +1 -1
- package/dist/host/db/mysqlAdapter.js +11 -0
- package/dist/host/db/mysqlAdapter.js.map +1 -1
- package/dist/host/db/oracleAdapter.d.ts +1 -0
- package/dist/host/db/oracleAdapter.d.ts.map +1 -1
- package/dist/host/db/oracleAdapter.js +22 -0
- package/dist/host/db/oracleAdapter.js.map +1 -1
- package/dist/host/db/postgresAdapter.d.ts +1 -0
- package/dist/host/db/postgresAdapter.d.ts.map +1 -1
- package/dist/host/db/postgresAdapter.js +13 -0
- package/dist/host/db/postgresAdapter.js.map +1 -1
- package/dist/host/db/queryExecutor.d.ts +2 -1
- package/dist/host/db/queryExecutor.d.ts.map +1 -1
- package/dist/host/db/queryExecutor.js +1 -1
- package/dist/host/db/queryExecutor.js.map +1 -1
- package/dist/host/index.d.ts +7 -0
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.js +9 -0
- package/dist/host/index.js.map +1 -1
- package/dist-cjs/ai/index.js.map +1 -1
- package/dist-cjs/ai/outputSchemas.js +1 -0
- package/dist-cjs/ai/outputSchemas.js.map +1 -1
- package/dist-cjs/ai/parse/diagram.js +6 -3
- package/dist-cjs/ai/parse/diagram.js.map +1 -1
- package/dist-cjs/ai/prompts/diagram.js +61 -5
- package/dist-cjs/ai/prompts/diagram.js.map +1 -1
- package/dist-cjs/diagram/bpmn/derive.js +398 -0
- package/dist-cjs/diagram/bpmn/derive.js.map +1 -0
- package/dist-cjs/diagram/bpmn/index.js +31 -0
- package/dist-cjs/diagram/bpmn/index.js.map +1 -0
- package/dist-cjs/diagram/bpmn/patch.js +774 -0
- package/dist-cjs/diagram/bpmn/patch.js.map +1 -0
- package/dist-cjs/diagram/bpmn/place.js +69 -0
- package/dist-cjs/diagram/bpmn/place.js.map +1 -0
- package/dist-cjs/diagram/bpmn/serialize.js +299 -0
- package/dist-cjs/diagram/bpmn/serialize.js.map +1 -0
- package/dist-cjs/diagram/bpmn/types.js +99 -0
- package/dist-cjs/diagram/bpmn/types.js.map +1 -0
- package/dist-cjs/diagram/bpmn/xml.js +367 -0
- package/dist-cjs/diagram/bpmn/xml.js.map +1 -0
- package/dist-cjs/diagram/componentCatalog.js +5 -1
- package/dist-cjs/diagram/componentCatalog.js.map +1 -1
- package/dist-cjs/diagram/database/derive.js +119 -0
- package/dist-cjs/diagram/database/derive.js.map +1 -0
- package/dist-cjs/diagram/database/diff.js +115 -0
- package/dist-cjs/diagram/database/diff.js.map +1 -0
- package/dist-cjs/diagram/database/edit.js +366 -0
- package/dist-cjs/diagram/database/edit.js.map +1 -0
- package/dist-cjs/diagram/database/fromSchema.js +188 -0
- package/dist-cjs/diagram/database/fromSchema.js.map +1 -0
- package/dist-cjs/diagram/database/index.js +32 -0
- package/dist-cjs/diagram/database/index.js.map +1 -0
- package/dist-cjs/diagram/database/model.js +311 -0
- package/dist-cjs/diagram/database/model.js.map +1 -0
- package/dist-cjs/diagram/database/patch.js +190 -0
- package/dist-cjs/diagram/database/patch.js.map +1 -0
- package/dist-cjs/diagram/database/place.js +26 -0
- package/dist-cjs/diagram/database/place.js.map +1 -0
- package/dist-cjs/diagram/database/types.js +122 -0
- package/dist-cjs/diagram/database/types.js.map +1 -0
- package/dist-cjs/diagram/elkGraph.js +1 -0
- package/dist-cjs/diagram/elkGraph.js.map +1 -1
- package/dist-cjs/diagram/fixtures.js +117 -0
- package/dist-cjs/diagram/fixtures.js.map +1 -0
- package/dist-cjs/diagram/geometry.js +143 -0
- package/dist-cjs/diagram/geometry.js.map +1 -0
- package/dist-cjs/diagram/history.js +65 -0
- package/dist-cjs/diagram/history.js.map +1 -0
- package/dist-cjs/diagram/ids.js +58 -0
- package/dist-cjs/diagram/ids.js.map +1 -0
- package/dist-cjs/diagram/index.js +24 -8
- package/dist-cjs/diagram/index.js.map +1 -1
- package/dist-cjs/diagram/layout.js +365 -0
- package/dist-cjs/diagram/layout.js.map +1 -0
- package/dist-cjs/diagram/mermaid/derive.js +353 -0
- package/dist-cjs/diagram/mermaid/derive.js.map +1 -0
- package/dist-cjs/diagram/mermaid/index.js +44 -0
- package/dist-cjs/diagram/mermaid/index.js.map +1 -0
- package/dist-cjs/diagram/mermaid/parse.js +681 -0
- package/dist-cjs/diagram/mermaid/parse.js.map +1 -0
- package/dist-cjs/diagram/mermaid/patch.js +468 -0
- package/dist-cjs/diagram/mermaid/patch.js.map +1 -0
- package/dist-cjs/diagram/mermaid/serialize.js +133 -0
- package/dist-cjs/diagram/mermaid/serialize.js.map +1 -0
- package/dist-cjs/diagram/mermaid/shapes.js +327 -0
- package/dist-cjs/diagram/mermaid/shapes.js.map +1 -0
- package/dist-cjs/diagram/migrations.js +9 -3
- package/dist-cjs/diagram/migrations.js.map +1 -1
- package/dist-cjs/diagram/normalize.js +198 -1
- package/dist-cjs/diagram/normalize.js.map +1 -1
- package/dist-cjs/diagram/ops.js +871 -0
- package/dist-cjs/diagram/ops.js.map +1 -0
- package/dist-cjs/diagram/opsReference.js +64 -0
- package/dist-cjs/diagram/opsReference.js.map +1 -0
- package/dist-cjs/diagram/patchInput.js +1039 -0
- package/dist-cjs/diagram/patchInput.js.map +1 -0
- package/dist-cjs/diagram/routing/batch.js +142 -0
- package/dist-cjs/diagram/routing/batch.js.map +1 -0
- package/dist-cjs/diagram/routing/curves.js +127 -0
- package/dist-cjs/diagram/routing/curves.js.map +1 -0
- package/dist-cjs/diagram/routing/grid.js +250 -0
- package/dist-cjs/diagram/routing/grid.js.map +1 -0
- package/dist-cjs/diagram/routing/index.js +29 -0
- package/dist-cjs/diagram/routing/index.js.map +1 -0
- package/dist-cjs/diagram/routing/legacy.js +32 -0
- package/dist-cjs/diagram/routing/legacy.js.map +1 -0
- package/dist-cjs/diagram/routing/nudge.js +100 -0
- package/dist-cjs/diagram/routing/nudge.js.map +1 -0
- package/dist-cjs/diagram/routing/orthogonal.js +62 -0
- package/dist-cjs/diagram/routing/orthogonal.js.map +1 -0
- package/dist-cjs/diagram/routing/path.js +137 -0
- package/dist-cjs/diagram/routing/path.js.map +1 -0
- package/dist-cjs/diagram/routing/sides.js +82 -0
- package/dist-cjs/diagram/routing/sides.js.map +1 -0
- package/dist-cjs/diagram/routing/types.js +15 -0
- package/dist-cjs/diagram/routing/types.js.map +1 -0
- package/dist-cjs/diagram/schema.js +64 -9
- package/dist-cjs/diagram/schema.js.map +1 -1
- package/dist-cjs/diagram/styleInput.js +113 -0
- package/dist-cjs/diagram/styleInput.js.map +1 -0
- package/dist-cjs/diagram/views.js +96 -0
- package/dist-cjs/diagram/views.js.map +1 -0
- package/dist-cjs/host/db/introspection/index.js +59 -0
- package/dist-cjs/host/db/introspection/index.js.map +1 -0
- package/dist-cjs/host/db/introspection/mongo.js +189 -0
- package/dist-cjs/host/db/introspection/mongo.js.map +1 -0
- package/dist-cjs/host/db/introspection/mssql.js +216 -0
- package/dist-cjs/host/db/introspection/mssql.js.map +1 -0
- package/dist-cjs/host/db/introspection/mysql.js +167 -0
- package/dist-cjs/host/db/introspection/mysql.js.map +1 -0
- package/dist-cjs/host/db/introspection/oracle.js +230 -0
- package/dist-cjs/host/db/introspection/oracle.js.map +1 -0
- package/dist-cjs/host/db/introspection/postgres.js +176 -0
- package/dist-cjs/host/db/introspection/postgres.js.map +1 -0
- package/dist-cjs/host/db/introspection/shared.js +133 -0
- package/dist-cjs/host/db/introspection/shared.js.map +1 -0
- package/dist-cjs/host/db/introspection/types.js +7 -0
- package/dist-cjs/host/db/introspection/types.js.map +1 -0
- package/dist-cjs/host/db/mongoAdapter.js +15 -1
- package/dist-cjs/host/db/mongoAdapter.js.map +1 -1
- package/dist-cjs/host/db/mssqlAdapter.js +5 -2
- package/dist-cjs/host/db/mssqlAdapter.js.map +1 -1
- package/dist-cjs/host/db/mysqlAdapter.js +13 -1
- package/dist-cjs/host/db/mysqlAdapter.js.map +1 -1
- package/dist-cjs/host/db/oracleAdapter.js +24 -1
- package/dist-cjs/host/db/oracleAdapter.js.map +1 -1
- package/dist-cjs/host/db/postgresAdapter.js +15 -1
- package/dist-cjs/host/db/postgresAdapter.js.map +1 -1
- package/dist-cjs/host/db/queryExecutor.js +5 -4
- package/dist-cjs/host/db/queryExecutor.js.map +1 -1
- package/dist-cjs/host/index.js +24 -1
- package/dist-cjs/host/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,1039 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assessOpsRisk = exports.placeNewNodesOps = exports.ungroupOps = exports.groupNodesOps = exports.buildDiagramFromInput = exports.lowerPatchOps = exports.edgeStyleFor = exports.assertNotConnector = exports.parentWarning = exports.containerTypes = exports.isContainerType = exports.suggestComponentTypes = void 0;
|
|
4
|
+
// The AUTHORING vocabulary — the compact shape AI models and MCP clients
|
|
5
|
+
// write (`parent` not `parentId`, a `semantic` instead of a dash tuple, CSS
|
|
6
|
+
// colors, optional positions) — lowered onto the canonical ops of ops.ts.
|
|
7
|
+
// One implementation of the merge rules, type checks and suggestions, shared
|
|
8
|
+
// by the MCP server (behind its zod schemas), the AI EDIT mode and imports.
|
|
9
|
+
// Moved from the MCP server's build.ts / patch.ts.
|
|
10
|
+
const types_js_1 = require("./bpmn/types.js");
|
|
11
|
+
const index_js_1 = require("./database/index.js");
|
|
12
|
+
const componentCatalog_js_1 = require("./componentCatalog.js");
|
|
13
|
+
const edgeSemantics_js_1 = require("./edgeSemantics.js");
|
|
14
|
+
const geometry_js_1 = require("./geometry.js");
|
|
15
|
+
const ids_js_1 = require("./ids.js");
|
|
16
|
+
const normalize_js_1 = require("./normalize.js");
|
|
17
|
+
const ops_js_1 = require("./ops.js");
|
|
18
|
+
const schema_js_1 = require("./schema.js");
|
|
19
|
+
const styleInput_js_1 = require("./styleInput.js");
|
|
20
|
+
// --- catalog helpers ---------------------------------------------------------------
|
|
21
|
+
const suggestComponentTypes = (type, limit = 5) => {
|
|
22
|
+
const seen = new Set();
|
|
23
|
+
const out = [];
|
|
24
|
+
const push = (candidate) => {
|
|
25
|
+
if (!seen.has(candidate) && out.length < limit) {
|
|
26
|
+
seen.add(candidate);
|
|
27
|
+
out.push(candidate);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
for (const entry of (0, componentCatalog_js_1.searchDiagramComponents)(type))
|
|
31
|
+
push(entry.type);
|
|
32
|
+
// A typo usually sits at the END of the last segment ("db.postgresqlx"):
|
|
33
|
+
// shrink it until something in the catalog contains it.
|
|
34
|
+
const tail = (type.split(".").pop() ?? type).toLowerCase();
|
|
35
|
+
for (let length = tail.length; length >= 3 && out.length < limit; length -= 1) {
|
|
36
|
+
const needle = tail.slice(0, length);
|
|
37
|
+
for (const entry of componentCatalog_js_1.DIAGRAM_COMPONENT_CATALOG) {
|
|
38
|
+
const haystack = [entry.type, entry.label, ...(entry.aliases ?? [])].join(" ").toLowerCase();
|
|
39
|
+
if (haystack.includes(needle))
|
|
40
|
+
push(entry.type);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Still nothing: offer the same namespace ("db.*", "aws.*").
|
|
44
|
+
const namespace = type.includes(".") ? `${type.split(".")[0].toLowerCase()}.` : null;
|
|
45
|
+
if (namespace) {
|
|
46
|
+
for (const entry of componentCatalog_js_1.DIAGRAM_COMPONENT_CATALOG)
|
|
47
|
+
if (entry.type.toLowerCase().startsWith(namespace))
|
|
48
|
+
push(entry.type);
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
};
|
|
52
|
+
exports.suggestComponentTypes = suggestComponentTypes;
|
|
53
|
+
// Containers hold children through `parent`: frames and swimlane pools.
|
|
54
|
+
const isContainerType = (type) => {
|
|
55
|
+
const def = type ? (0, componentCatalog_js_1.getDiagramComponent)(type) : undefined;
|
|
56
|
+
return Boolean(def?.container || def?.swimlane);
|
|
57
|
+
};
|
|
58
|
+
exports.isContainerType = isContainerType;
|
|
59
|
+
const containerTypes = () => componentCatalog_js_1.DIAGRAM_COMPONENT_CATALOG.filter((entry) => entry.container || entry.swimlane).map((entry) => entry.type);
|
|
60
|
+
exports.containerTypes = containerTypes;
|
|
61
|
+
const parentWarning = (id, parentId, parentType, kind = "canvas") => {
|
|
62
|
+
if (kind === "database")
|
|
63
|
+
return `Node ${id} sits inside "${parentId}" — database diagrams have no containers; the parent is ignored.`;
|
|
64
|
+
if (kind === "bpmn") {
|
|
65
|
+
return (0, types_js_1.isBpmnContainerType)(parentType)
|
|
66
|
+
? null
|
|
67
|
+
: `Node ${id} sits inside "${parentId}" (${parentType ?? "unknown"}), which is not a BPMN container — use ${types_js_1.BPMN_CONTAINER_TYPES.join(", ")}.`;
|
|
68
|
+
}
|
|
69
|
+
return (0, exports.isContainerType)(parentType)
|
|
70
|
+
? null
|
|
71
|
+
: `Node ${id} sits inside "${parentId}" (${parentType ?? "unknown"}), which is not a container — use ${(0, exports.containerTypes)().join(", ")} to group nodes.`;
|
|
72
|
+
};
|
|
73
|
+
exports.parentWarning = parentWarning;
|
|
74
|
+
// line / arrow / line.dashed are palette connectors (0-height), not nodes.
|
|
75
|
+
const assertNotConnector = (type, id, opIndex = -1) => {
|
|
76
|
+
if ((0, componentCatalog_js_1.getDiagramComponent)(type)?.variant === "line") {
|
|
77
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_CONNECTOR_NOT_NODE", `"${type}" on ${id} is a connector, not a node — draw it as an edge between two nodes.`, opIndex);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
exports.assertNotConnector = assertNotConnector;
|
|
81
|
+
// Edge input → the stored edge's visual fields: the semantic's line tuple
|
|
82
|
+
// plus an optional color.
|
|
83
|
+
const edgeStyleFor = (semantic, color) => {
|
|
84
|
+
const base = semantic ? (0, edgeSemantics_js_1.semanticStyle)(semantic) : undefined;
|
|
85
|
+
if (!color)
|
|
86
|
+
return base;
|
|
87
|
+
return { ...(base ?? {}), stroke: (0, styleInput_js_1.toTokenRef)(color) };
|
|
88
|
+
};
|
|
89
|
+
exports.edgeStyleFor = edgeStyleFor;
|
|
90
|
+
const resolveType = (type, id, strict, warnings, opIndex, kind = "canvas") => {
|
|
91
|
+
const trimmed = type.trim();
|
|
92
|
+
if (kind === "database") {
|
|
93
|
+
if (index_js_1.DB_NODE_TYPES.includes(trimmed))
|
|
94
|
+
return { type: trimmed, known: true };
|
|
95
|
+
const suggestions = (0, index_js_1.suggestDatabaseTypes)(trimmed);
|
|
96
|
+
if (strict) {
|
|
97
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_UNKNOWN_COMPONENT_TYPE", `Unknown database type "${trimmed}" on ${id}. A database diagram has db.table, db.view and db.collection (prefer the DATABASE OPS: addTable, addColumn, addRelationship …), or pass strictTypes:false to draw it as a table.`, opIndex, { unknownTypes: [{ type: trimmed, suggestions }] });
|
|
98
|
+
}
|
|
99
|
+
warnings.push(`Unknown database type "${trimmed}" on ${id} → drawn as a table`);
|
|
100
|
+
return { type: "db.table", known: false };
|
|
101
|
+
}
|
|
102
|
+
if (kind === "bpmn") {
|
|
103
|
+
if ((0, types_js_1.getBpmnType)(trimmed))
|
|
104
|
+
return { type: trimmed, known: true };
|
|
105
|
+
const suggestions = (0, types_js_1.suggestBpmnTypes)(trimmed);
|
|
106
|
+
if (strict) {
|
|
107
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_UNKNOWN_COMPONENT_TYPE", `Unknown BPMN type "${trimmed}" on ${id}. Use one of the bpmn.* types (e.g. ${suggestions.join(", ") || "bpmn.user-task, bpmn.exclusive-gateway"}), or pass strictTypes:false to draw it as a task.`, opIndex, { unknownTypes: [{ type: trimmed, suggestions }] });
|
|
108
|
+
}
|
|
109
|
+
warnings.push(`Unknown BPMN type "${trimmed}" on ${id} → drawn as a task (suggestions: ${suggestions.join(", ") || "none"})`);
|
|
110
|
+
return { type: "bpmn.task", known: false };
|
|
111
|
+
}
|
|
112
|
+
if ((0, componentCatalog_js_1.getDiagramComponent)(trimmed)) {
|
|
113
|
+
(0, exports.assertNotConnector)(trimmed, id, opIndex);
|
|
114
|
+
return { type: trimmed, known: true };
|
|
115
|
+
}
|
|
116
|
+
const suggestions = (0, exports.suggestComponentTypes)(trimmed);
|
|
117
|
+
if (strict) {
|
|
118
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_UNKNOWN_COMPONENT_TYPE", `Unknown component type "${trimmed}" on ${id}. Read callman://diagram/components for the catalog, or pass strictTypes:false to draw it as a rectangle.`, opIndex, { unknownTypes: [{ type: trimmed, suggestions }] });
|
|
119
|
+
}
|
|
120
|
+
warnings.push(`Unknown component type "${trimmed}" on ${id} → drawn as a rectangle (suggestions: ${suggestions.join(", ") || "none"})`);
|
|
121
|
+
return { type: "rect", known: false };
|
|
122
|
+
};
|
|
123
|
+
const nodeFromInput = (input, id, strict, warnings, opIndex, kind = "canvas") => {
|
|
124
|
+
const { type, known } = resolveType(input.type, id, strict, warnings, opIndex, kind);
|
|
125
|
+
const def = kind === "canvas" ? (0, componentCatalog_js_1.getDiagramComponent)(type) : undefined;
|
|
126
|
+
const bpmn = kind === "bpmn" ? (0, types_js_1.getBpmnType)(type) : undefined;
|
|
127
|
+
const dbRaw = kind === "database" ? (input.data?.db ?? {}) : undefined;
|
|
128
|
+
const label = kind === "database"
|
|
129
|
+
? (typeof dbRaw?.name === "string" && dbRaw.name.trim()) || input.label || id
|
|
130
|
+
: input.label !== undefined || !known
|
|
131
|
+
? (input.label ?? input.type)
|
|
132
|
+
: def?.defaultLabel;
|
|
133
|
+
// A BPMN node always knows which element it stands for; a database node its
|
|
134
|
+
// table name and kind (its `columns` stay the authoring input until the
|
|
135
|
+
// model absorbs them).
|
|
136
|
+
const data = kind === "bpmn"
|
|
137
|
+
? { ...(input.data ?? {}), bpmn: { ...(input.data?.bpmn ?? {}), element: (0, types_js_1.bpmnElementForType)(type) ?? "task" } }
|
|
138
|
+
: kind === "database"
|
|
139
|
+
? { ...(input.data ?? {}), db: { ...dbRaw, name: label, kind: (0, index_js_1.kindForDatabaseType)(type) } }
|
|
140
|
+
: input.data;
|
|
141
|
+
const dbColumns = Array.isArray(dbRaw?.columns) ? dbRaw.columns : [];
|
|
142
|
+
const dbSize = kind === "database"
|
|
143
|
+
? (0, index_js_1.databaseEntitySize)({
|
|
144
|
+
name: String(label),
|
|
145
|
+
...(typeof dbRaw?.schema === "string" ? { schema: dbRaw.schema } : {}),
|
|
146
|
+
columns: dbColumns.map((column) => {
|
|
147
|
+
const raw = (column ?? {});
|
|
148
|
+
return { name: typeof raw.name === "string" ? raw.name : "", dataType: typeof raw.dataType === "string" ? raw.dataType : typeof raw.type === "string" ? raw.type : "" };
|
|
149
|
+
}),
|
|
150
|
+
})
|
|
151
|
+
: undefined;
|
|
152
|
+
const node = {
|
|
153
|
+
id,
|
|
154
|
+
type,
|
|
155
|
+
position: input.position ?? { x: 0, y: 0 },
|
|
156
|
+
size: input.size ?? bpmn?.size ?? dbSize ?? def?.defaultSize ?? { width: 140, height: 60 },
|
|
157
|
+
...(label !== undefined ? { label } : {}),
|
|
158
|
+
...(input.parent ? { parentId: input.parent } : {}),
|
|
159
|
+
...(input.style ? { style: (0, styleInput_js_1.applyStyleInput)(undefined, input.style) } : {}),
|
|
160
|
+
...(input.rotation ? { rotation: input.rotation } : {}),
|
|
161
|
+
...(input.locked ? { locked: true } : {}),
|
|
162
|
+
...(input.hidden ? { hidden: true } : {}),
|
|
163
|
+
...(input.collapsed ? { collapsed: true } : {}),
|
|
164
|
+
...(data ? { data } : {}),
|
|
165
|
+
};
|
|
166
|
+
if (node.style === undefined)
|
|
167
|
+
delete node.style;
|
|
168
|
+
return node;
|
|
169
|
+
};
|
|
170
|
+
const edgeFromInput = (input, id, typeOf, kind = "canvas") => {
|
|
171
|
+
let semantic = input.semantic;
|
|
172
|
+
// A fresh edge into a broker reads as a bus line — the studio's own rule.
|
|
173
|
+
if (kind === "canvas" && !semantic && ((0, edgeSemantics_js_1.isBusComponentType)(typeOf(input.source)) || (0, edgeSemantics_js_1.isBusComponentType)(typeOf(input.target))))
|
|
174
|
+
semantic = "bus";
|
|
175
|
+
// A BPMN flow is a sequence flow unless said otherwise; a database edge is
|
|
176
|
+
// a relationship (manual, N:1 unless said otherwise) with crow's-foot ends.
|
|
177
|
+
const dbRaw = kind === "database" ? (input.data?.db ?? {}) : undefined;
|
|
178
|
+
const cardinality = (0, index_js_1.isValidCardinality)(dbRaw?.cardinality) ? dbRaw.cardinality : "N:1";
|
|
179
|
+
const data = kind === "bpmn"
|
|
180
|
+
? { ...(input.data ?? {}), bpmn: { flow: "sequence", ...(input.data?.bpmn ?? {}) } }
|
|
181
|
+
: kind === "database"
|
|
182
|
+
? { ...(input.data ?? {}), db: { kind: "manual", sourceColumns: [], targetColumns: [], ...dbRaw, cardinality } }
|
|
183
|
+
: input.data;
|
|
184
|
+
const dbMarkers = kind === "database" ? (0, index_js_1.markersForCardinality)(cardinality) : undefined;
|
|
185
|
+
const style = (0, exports.edgeStyleFor)(semantic, input.color);
|
|
186
|
+
const markerStart = input.markerStart ?? dbMarkers?.markerStart;
|
|
187
|
+
return {
|
|
188
|
+
id,
|
|
189
|
+
source: input.source,
|
|
190
|
+
target: input.target,
|
|
191
|
+
...(input.label ? { label: input.label } : {}),
|
|
192
|
+
...(input.routing ? { routing: input.routing } : {}),
|
|
193
|
+
markerEnd: input.markerEnd ?? dbMarkers?.markerEnd ?? "classicThin",
|
|
194
|
+
...(markerStart && markerStart !== "none" ? { markerStart } : {}),
|
|
195
|
+
...(input.sourceSide ? { sourceHandle: input.sourceSide } : {}),
|
|
196
|
+
...(input.targetSide ? { targetHandle: input.targetSide } : {}),
|
|
197
|
+
...(style && (!(0, edgeSemantics_js_1.isDefaultEdgeStyle)(style) || semantic === "sync" || input.color) ? { style } : {}),
|
|
198
|
+
...(data ? { data } : {}),
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
// --- lowering -----------------------------------------------------------------------
|
|
202
|
+
const lowerPatchOps = (doc, input, options = {}) => {
|
|
203
|
+
const strict = options.strictTypes !== false;
|
|
204
|
+
const kind = options.kind ?? (doc.source?.format === "bpmn" ? "bpmn" : doc.source?.format === "database" ? "database" : "canvas");
|
|
205
|
+
if (kind === "database")
|
|
206
|
+
return lowerDatabasePatchOps(doc, input, { ...options, strict });
|
|
207
|
+
const warnings = [];
|
|
208
|
+
const unpositionedNodeIds = [];
|
|
209
|
+
const idMap = {};
|
|
210
|
+
const ops = [];
|
|
211
|
+
let relayout;
|
|
212
|
+
// A working view of ids/types/parents so later ops in the same batch can
|
|
213
|
+
// reference nodes added earlier — the ops themselves stay canonical.
|
|
214
|
+
const nodes = new Map(doc.nodes.map((node) => [node.id, { ...node }]));
|
|
215
|
+
const edges = new Map(doc.edges.map((edge) => [edge.id, { ...edge }]));
|
|
216
|
+
const takenIds = () => [...nodes.keys(), ...edges.keys()];
|
|
217
|
+
const genNodeId = options.genNodeId ?? (0, ids_js_1.slugIdFactory)(takenIds(), "n");
|
|
218
|
+
const genEdgeId = options.genEdgeId ?? (0, ids_js_1.sequentialIdFactory)("e", takenIds());
|
|
219
|
+
const typeOf = (id) => nodes.get(id)?.type;
|
|
220
|
+
const mapId = (id) => idMap[id] ?? id;
|
|
221
|
+
const requireNode = (id, index) => {
|
|
222
|
+
const node = nodes.get(mapId(id));
|
|
223
|
+
if (!node)
|
|
224
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_NODE_NOT_FOUND", `Node "${id}" does not exist.`, index);
|
|
225
|
+
return node;
|
|
226
|
+
};
|
|
227
|
+
input.forEach((op, index) => {
|
|
228
|
+
switch (op.op) {
|
|
229
|
+
case "setTitle":
|
|
230
|
+
ops.push({ op: "setTitle", title: op.title });
|
|
231
|
+
return;
|
|
232
|
+
case "addNode": {
|
|
233
|
+
const requested = op.node.id?.trim();
|
|
234
|
+
let id = requested || genNodeId(op.node.label ?? op.node.type);
|
|
235
|
+
if (requested && (nodes.has(requested) || edges.has(requested))) {
|
|
236
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_DUPLICATE_NODE_ID", `A node with id "${requested}" already exists.`, index);
|
|
237
|
+
}
|
|
238
|
+
if (!requested && (nodes.has(id) || edges.has(id)))
|
|
239
|
+
id = genNodeId();
|
|
240
|
+
const parent = op.node.parent ? mapId(op.node.parent) : undefined;
|
|
241
|
+
if (parent && !nodes.has(parent))
|
|
242
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_PARENT_NOT_FOUND", `Parent "${op.node.parent}" does not exist.`, index);
|
|
243
|
+
const node = nodeFromInput({ ...op.node, parent }, id, strict, warnings, index, kind);
|
|
244
|
+
if (parent) {
|
|
245
|
+
const warning = (0, exports.parentWarning)(id, parent, typeOf(parent), kind);
|
|
246
|
+
if (warning)
|
|
247
|
+
warnings.push(warning);
|
|
248
|
+
}
|
|
249
|
+
nodes.set(id, node);
|
|
250
|
+
if (requested && requested !== id)
|
|
251
|
+
idMap[requested] = id;
|
|
252
|
+
if (!op.node.position)
|
|
253
|
+
unpositionedNodeIds.push(id);
|
|
254
|
+
ops.push({ op: "addNode", node });
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
case "updateNode": {
|
|
258
|
+
const id = mapId(op.id);
|
|
259
|
+
const node = requireNode(id, index);
|
|
260
|
+
const changes = op.changes;
|
|
261
|
+
const nodeChanges = {};
|
|
262
|
+
if (changes.type !== undefined)
|
|
263
|
+
nodeChanges.type = resolveType(changes.type, id, strict, warnings, index, kind).type;
|
|
264
|
+
if (changes.label !== undefined)
|
|
265
|
+
nodeChanges.label = changes.label;
|
|
266
|
+
if (changes.rotation !== undefined)
|
|
267
|
+
nodeChanges.rotation = changes.rotation;
|
|
268
|
+
if (changes.locked !== undefined)
|
|
269
|
+
nodeChanges.locked = changes.locked;
|
|
270
|
+
if (changes.hidden !== undefined)
|
|
271
|
+
nodeChanges.hidden = changes.hidden;
|
|
272
|
+
if (changes.collapsed !== undefined)
|
|
273
|
+
nodeChanges.collapsed = changes.collapsed;
|
|
274
|
+
if (changes.style !== undefined)
|
|
275
|
+
nodeChanges.style = changes.style === null ? null : (0, styleInput_js_1.styleInputToChanges)(node.style, changes.style);
|
|
276
|
+
if (changes.data !== undefined)
|
|
277
|
+
nodeChanges.data = changes.data;
|
|
278
|
+
if (Object.keys(nodeChanges).length > 0) {
|
|
279
|
+
ops.push({ op: "updateNode", id, changes: nodeChanges });
|
|
280
|
+
const next = { ...node };
|
|
281
|
+
if (nodeChanges.type)
|
|
282
|
+
next.type = nodeChanges.type;
|
|
283
|
+
nodes.set(id, next);
|
|
284
|
+
}
|
|
285
|
+
if (changes.size !== undefined) {
|
|
286
|
+
ops.push({ op: "resizeNode", id, size: changes.size });
|
|
287
|
+
nodes.set(id, { ...nodes.get(id), size: changes.size });
|
|
288
|
+
}
|
|
289
|
+
if (changes.parent !== undefined) {
|
|
290
|
+
const parent = changes.parent ? mapId(changes.parent) : null;
|
|
291
|
+
if (parent && !nodes.has(parent))
|
|
292
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_PARENT_NOT_FOUND", `Parent "${changes.parent}" does not exist.`, index);
|
|
293
|
+
if (parent === id)
|
|
294
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_PARENT_CYCLE", `Node "${id}" cannot contain itself.`, index);
|
|
295
|
+
const byId = (0, geometry_js_1.indexNodes)([...nodes.values()]);
|
|
296
|
+
const position = changes.position ?? (0, geometry_js_1.toParentRelative)((0, geometry_js_1.absolutePosition)(nodes.get(id), byId), parent, byId);
|
|
297
|
+
ops.push({ op: "reparent", id, parentId: parent, position });
|
|
298
|
+
if (parent) {
|
|
299
|
+
const warning = (0, exports.parentWarning)(id, parent, typeOf(parent), kind);
|
|
300
|
+
if (warning)
|
|
301
|
+
warnings.push(warning);
|
|
302
|
+
}
|
|
303
|
+
const next = { ...nodes.get(id), position };
|
|
304
|
+
if (parent)
|
|
305
|
+
next.parentId = parent;
|
|
306
|
+
else
|
|
307
|
+
delete next.parentId;
|
|
308
|
+
nodes.set(id, next);
|
|
309
|
+
}
|
|
310
|
+
else if (changes.position !== undefined) {
|
|
311
|
+
ops.push({ op: "moveNodes", moves: [{ id, position: changes.position }] });
|
|
312
|
+
nodes.set(id, { ...nodes.get(id), position: changes.position });
|
|
313
|
+
}
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
case "removeNode": {
|
|
317
|
+
const id = mapId(op.id);
|
|
318
|
+
requireNode(id, index);
|
|
319
|
+
ops.push({ op: "removeNode", id, children: "lift" });
|
|
320
|
+
nodes.delete(id);
|
|
321
|
+
for (const [edgeId, edge] of [...edges])
|
|
322
|
+
if (edge.source === id || edge.target === id)
|
|
323
|
+
edges.delete(edgeId);
|
|
324
|
+
for (const node of nodes.values())
|
|
325
|
+
if (node.parentId === id)
|
|
326
|
+
delete node.parentId;
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
case "addEdge": {
|
|
330
|
+
const requested = op.edge.id?.trim();
|
|
331
|
+
let id = requested || genEdgeId();
|
|
332
|
+
if (requested && (edges.has(requested) || nodes.has(requested))) {
|
|
333
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_DUPLICATE_EDGE_ID", `An edge with id "${requested}" already exists.`, index);
|
|
334
|
+
}
|
|
335
|
+
if (!requested && (edges.has(id) || nodes.has(id)))
|
|
336
|
+
id = genEdgeId();
|
|
337
|
+
const source = mapId(op.edge.source);
|
|
338
|
+
const target = mapId(op.edge.target);
|
|
339
|
+
for (const endpoint of [source, target]) {
|
|
340
|
+
if (!nodes.has(endpoint))
|
|
341
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_EDGE_ENDPOINT_NOT_FOUND", `Edge endpoint "${endpoint}" does not exist.`, index);
|
|
342
|
+
}
|
|
343
|
+
const edge = edgeFromInput({ ...op.edge, source, target }, id, typeOf, kind);
|
|
344
|
+
edges.set(id, edge);
|
|
345
|
+
ops.push({ op: "addEdge", edge });
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
case "updateEdge": {
|
|
349
|
+
const id = mapId(op.id);
|
|
350
|
+
const edge = edges.get(id);
|
|
351
|
+
if (!edge)
|
|
352
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_EDGE_NOT_FOUND", `Edge "${op.id}" does not exist.`, index);
|
|
353
|
+
const changes = op.changes;
|
|
354
|
+
const edgeChanges = {};
|
|
355
|
+
if (changes.source !== undefined)
|
|
356
|
+
edgeChanges.source = mapId(changes.source);
|
|
357
|
+
if (changes.target !== undefined)
|
|
358
|
+
edgeChanges.target = mapId(changes.target);
|
|
359
|
+
if (changes.label !== undefined)
|
|
360
|
+
edgeChanges.label = changes.label === "" ? null : changes.label;
|
|
361
|
+
if (changes.routing !== undefined)
|
|
362
|
+
edgeChanges.routing = changes.routing;
|
|
363
|
+
if (changes.markerEnd !== undefined)
|
|
364
|
+
edgeChanges.markerEnd = changes.markerEnd;
|
|
365
|
+
if (changes.markerStart !== undefined)
|
|
366
|
+
edgeChanges.markerStart = changes.markerStart === "none" ? null : changes.markerStart;
|
|
367
|
+
if (changes.sourceSide !== undefined)
|
|
368
|
+
edgeChanges.sourceHandle = changes.sourceSide;
|
|
369
|
+
if (changes.targetSide !== undefined)
|
|
370
|
+
edgeChanges.targetHandle = changes.targetSide;
|
|
371
|
+
if (changes.data !== undefined)
|
|
372
|
+
edgeChanges.data = changes.data;
|
|
373
|
+
// The semantic owns the line tuple (dash + width); the color is kept
|
|
374
|
+
// unless it is changed explicitly.
|
|
375
|
+
if (changes.semantic !== undefined || changes.color !== undefined) {
|
|
376
|
+
const style = {};
|
|
377
|
+
if (changes.semantic !== undefined) {
|
|
378
|
+
const line = (0, edgeSemantics_js_1.semanticStyle)(changes.semantic);
|
|
379
|
+
style.dashed = line.dashed ?? null;
|
|
380
|
+
style.dashPattern = line.dashPattern ?? null;
|
|
381
|
+
style.strokeWidth = line.strokeWidth ?? null;
|
|
382
|
+
}
|
|
383
|
+
if (changes.color !== undefined)
|
|
384
|
+
style.stroke = changes.color === null ? null : (0, styleInput_js_1.toTokenRef)(changes.color);
|
|
385
|
+
edgeChanges.style = style;
|
|
386
|
+
}
|
|
387
|
+
for (const endpoint of [edgeChanges.source, edgeChanges.target]) {
|
|
388
|
+
if (endpoint !== undefined && !nodes.has(endpoint)) {
|
|
389
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_EDGE_ENDPOINT_NOT_FOUND", `Edge endpoint "${endpoint}" does not exist.`, index);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (Object.keys(edgeChanges).length > 0) {
|
|
393
|
+
ops.push({ op: "updateEdge", id, changes: edgeChanges });
|
|
394
|
+
edges.set(id, { ...edge, ...(edgeChanges.source ? { source: edgeChanges.source } : {}), ...(edgeChanges.target ? { target: edgeChanges.target } : {}) });
|
|
395
|
+
}
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
case "removeEdge": {
|
|
399
|
+
const id = mapId(op.id);
|
|
400
|
+
if (!edges.has(id))
|
|
401
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_EDGE_NOT_FOUND", `Edge "${op.id}" does not exist.`, index);
|
|
402
|
+
edges.delete(id);
|
|
403
|
+
ops.push({ op: "removeEdge", id });
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
case "moveNode": {
|
|
407
|
+
const id = mapId(op.id);
|
|
408
|
+
requireNode(id, index);
|
|
409
|
+
ops.push({ op: "moveNodes", moves: [{ id, position: op.position }] });
|
|
410
|
+
nodes.set(id, { ...nodes.get(id), position: op.position });
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
case "reparent": {
|
|
414
|
+
const id = mapId(op.id);
|
|
415
|
+
const node = requireNode(id, index);
|
|
416
|
+
const parent = op.parent ? mapId(op.parent) : null;
|
|
417
|
+
if (parent && !nodes.has(parent))
|
|
418
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_PARENT_NOT_FOUND", `Parent "${op.parent}" does not exist.`, index);
|
|
419
|
+
const byId = (0, geometry_js_1.indexNodes)([...nodes.values()]);
|
|
420
|
+
const position = op.position ?? (0, geometry_js_1.toParentRelative)((0, geometry_js_1.absolutePosition)(node, byId), parent, byId);
|
|
421
|
+
ops.push({ op: "reparent", id, parentId: parent, position });
|
|
422
|
+
const next = { ...node, position };
|
|
423
|
+
if (parent)
|
|
424
|
+
next.parentId = parent;
|
|
425
|
+
else
|
|
426
|
+
delete next.parentId;
|
|
427
|
+
nodes.set(id, next);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
case "setEdgeRoute": {
|
|
431
|
+
const id = mapId(op.id);
|
|
432
|
+
if (!edges.has(id))
|
|
433
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_EDGE_NOT_FOUND", `Edge "${op.id}" does not exist.`, index);
|
|
434
|
+
const changes = {};
|
|
435
|
+
if (op.routing !== undefined)
|
|
436
|
+
changes.routing = op.routing;
|
|
437
|
+
if (op.sourceSide !== undefined)
|
|
438
|
+
changes.sourceHandle = op.sourceSide;
|
|
439
|
+
if (op.targetSide !== undefined)
|
|
440
|
+
changes.targetHandle = op.targetSide;
|
|
441
|
+
if (op.waypoints !== undefined)
|
|
442
|
+
changes.waypoints = op.waypoints;
|
|
443
|
+
// "Reset routing" when nothing else is asked.
|
|
444
|
+
if (Object.keys(changes).length === 0) {
|
|
445
|
+
changes.waypoints = null;
|
|
446
|
+
changes.sourceAnchor = null;
|
|
447
|
+
changes.targetAnchor = null;
|
|
448
|
+
}
|
|
449
|
+
ops.push({ op: "updateEdge", id, changes });
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
case "reorder": {
|
|
453
|
+
const id = mapId(op.id);
|
|
454
|
+
const node = requireNode(id, index);
|
|
455
|
+
const siblings = [...nodes.values()].filter((candidate) => (candidate.parentId ?? undefined) === (node.parentId ?? undefined));
|
|
456
|
+
const target = op.index === "front" ? siblings.length - 1 : op.index === "back" ? 0 : op.index;
|
|
457
|
+
ops.push({ op: "reorder", kind: "node", id, index: target });
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
case "setCanvas":
|
|
461
|
+
ops.push({ op: "setCanvas", changes: op.canvas });
|
|
462
|
+
return;
|
|
463
|
+
case "group": {
|
|
464
|
+
const memberIds = op.ids.map(mapId);
|
|
465
|
+
for (const memberId of memberIds)
|
|
466
|
+
requireNode(memberId, index);
|
|
467
|
+
const type = op.type ?? "frame";
|
|
468
|
+
if (!(0, exports.isContainerType)(type)) {
|
|
469
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_INVALID_OP", `"${type}" is not a container type — use ${(0, exports.containerTypes)().join(", ")}.`, index);
|
|
470
|
+
}
|
|
471
|
+
const requested = op.id?.trim();
|
|
472
|
+
const groupId = requested || genNodeId(op.label ?? "group");
|
|
473
|
+
if (nodes.has(groupId) || edges.has(groupId))
|
|
474
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_DUPLICATE_NODE_ID", `A node with id "${groupId}" already exists.`, index);
|
|
475
|
+
const grouped = (0, exports.groupNodesOps)({ ...doc, nodes: [...nodes.values()], edges: [...edges.values()] }, memberIds, { id: groupId, type, label: op.label });
|
|
476
|
+
ops.push(...grouped.ops);
|
|
477
|
+
nodes.set(groupId, grouped.container);
|
|
478
|
+
for (const [memberId, position] of Object.entries(grouped.memberPositions)) {
|
|
479
|
+
nodes.set(memberId, { ...nodes.get(memberId), parentId: groupId, position });
|
|
480
|
+
}
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
case "ungroup": {
|
|
484
|
+
const id = mapId(op.id);
|
|
485
|
+
requireNode(id, index);
|
|
486
|
+
ops.push({ op: "removeNode", id, children: "lift" });
|
|
487
|
+
nodes.delete(id);
|
|
488
|
+
for (const node of nodes.values())
|
|
489
|
+
if (node.parentId === id)
|
|
490
|
+
delete node.parentId;
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
case "relayout":
|
|
494
|
+
relayout = { scope: op.scope, ...(op.direction ? { direction: op.direction } : {}) };
|
|
495
|
+
return;
|
|
496
|
+
case "addTable":
|
|
497
|
+
case "renameTable":
|
|
498
|
+
case "removeTable":
|
|
499
|
+
case "setTableComment":
|
|
500
|
+
case "addColumn":
|
|
501
|
+
case "alterColumn":
|
|
502
|
+
case "removeColumn":
|
|
503
|
+
case "setPrimaryKey":
|
|
504
|
+
case "addRelationship":
|
|
505
|
+
case "updateRelationship":
|
|
506
|
+
case "removeRelationship":
|
|
507
|
+
case "hideTable":
|
|
508
|
+
case "showTable":
|
|
509
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_INVALID_OP", `"${op.op}" is a database-diagram op; this diagram is a ${kind} diagram.`, index);
|
|
510
|
+
default:
|
|
511
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_INVALID_OP", `Unknown op "${op.op}"`, index);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
return { ops, warnings, unpositionedNodeIds, ...(relayout ? { relayout } : {}), idMap };
|
|
515
|
+
};
|
|
516
|
+
exports.lowerPatchOps = lowerPatchOps;
|
|
517
|
+
// --- database diagrams -------------------------------------------------------------
|
|
518
|
+
//
|
|
519
|
+
// Every structural op (semantic or generic) becomes an edit of the database
|
|
520
|
+
// model; the batch then yields ONE setSource op (the model re-derives the
|
|
521
|
+
// nodes/edges) followed by the presentation ops (positions, visibility,
|
|
522
|
+
// routing) that address nodes by their entity ids.
|
|
523
|
+
const DATABASE_ERROR_CODES = {
|
|
524
|
+
DIAGRAM_TABLE_NOT_FOUND: "DIAGRAM_TABLE_NOT_FOUND",
|
|
525
|
+
DIAGRAM_COLUMN_NOT_FOUND: "DIAGRAM_COLUMN_NOT_FOUND",
|
|
526
|
+
DIAGRAM_RELATIONSHIP_NOT_FOUND: "DIAGRAM_RELATIONSHIP_NOT_FOUND",
|
|
527
|
+
DIAGRAM_DUPLICATE_TABLE: "DIAGRAM_DUPLICATE_TABLE",
|
|
528
|
+
DIAGRAM_DUPLICATE_COLUMN: "DIAGRAM_DUPLICATE_COLUMN",
|
|
529
|
+
DIAGRAM_INVALID_OP: "DIAGRAM_INVALID_OP",
|
|
530
|
+
};
|
|
531
|
+
const columnInputsOf = (value) => {
|
|
532
|
+
if (!Array.isArray(value))
|
|
533
|
+
return undefined;
|
|
534
|
+
return value
|
|
535
|
+
.filter((item) => Boolean(item) && typeof item === "object" && typeof item.name === "string")
|
|
536
|
+
.map((item) => ({
|
|
537
|
+
...(typeof item.id === "string" ? { id: item.id } : {}),
|
|
538
|
+
name: String(item.name),
|
|
539
|
+
dataType: typeof item.dataType === "string" ? item.dataType : typeof item.type === "string" ? item.type : "",
|
|
540
|
+
...(typeof item.nullable === "boolean" ? { nullable: item.nullable } : {}),
|
|
541
|
+
...(typeof item.primaryKey === "boolean" ? { primaryKey: item.primaryKey } : {}),
|
|
542
|
+
...(typeof item.unique === "boolean" ? { unique: item.unique } : {}),
|
|
543
|
+
...(item.defaultValue !== undefined && item.defaultValue !== null ? { defaultValue: String(item.defaultValue) } : {}),
|
|
544
|
+
...(typeof item.autoIncrement === "boolean" ? { autoIncrement: item.autoIncrement } : {}),
|
|
545
|
+
...(typeof item.comment === "string" ? { comment: item.comment } : {}),
|
|
546
|
+
}));
|
|
547
|
+
};
|
|
548
|
+
const lowerDatabasePatchOps = (doc, input, options) => {
|
|
549
|
+
const warnings = [];
|
|
550
|
+
const idMap = {};
|
|
551
|
+
const presentation = [];
|
|
552
|
+
const positioned = new Map();
|
|
553
|
+
const unpositionedNodeIds = [];
|
|
554
|
+
let relayout;
|
|
555
|
+
const parsed = doc.source?.format === "database" ? (0, index_js_1.parseDatabaseModel)(doc.source.text) : null;
|
|
556
|
+
if (parsed && !parsed.ok)
|
|
557
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_DOCUMENT_INVALID", `The database model cannot be read: ${parsed.errors.join("; ")}`);
|
|
558
|
+
let model = parsed?.model ?? (0, index_js_1.emptyDatabaseModel)();
|
|
559
|
+
let changed = false;
|
|
560
|
+
const mapId = (id) => idMap[id] ?? id;
|
|
561
|
+
const run = (edits, index) => {
|
|
562
|
+
try {
|
|
563
|
+
const result = (0, index_js_1.applyDatabaseEdits)(model, edits);
|
|
564
|
+
model = result.model;
|
|
565
|
+
changed = changed || result.changed;
|
|
566
|
+
warnings.push(...result.warnings);
|
|
567
|
+
Object.assign(idMap, result.idMap);
|
|
568
|
+
return result;
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
if (error instanceof index_js_1.DatabaseEditError)
|
|
572
|
+
throw new ops_js_1.DiagramOpError(DATABASE_ERROR_CODES[error.code], error.message, index);
|
|
573
|
+
throw error;
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
const entityIdOf = (ref, index) => {
|
|
577
|
+
const entity = (0, index_js_1.findEntity)(model, mapId(ref));
|
|
578
|
+
if (!entity)
|
|
579
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_TABLE_NOT_FOUND", `Table "${ref}" does not exist.`, index);
|
|
580
|
+
return entity.id;
|
|
581
|
+
};
|
|
582
|
+
const relationshipIdOf = (ref) => mapId(ref);
|
|
583
|
+
const noContainers = (index) => {
|
|
584
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_INVALID_OP", "Database diagrams have no containers (group / ungroup / reparent do not apply).", index);
|
|
585
|
+
};
|
|
586
|
+
const endInput = (value) => (typeof value === "string" ? value : { ...value, table: mapId(value.table) });
|
|
587
|
+
input.forEach((op, index) => {
|
|
588
|
+
switch (op.op) {
|
|
589
|
+
case "setTitle":
|
|
590
|
+
presentation.push({ op: "setTitle", title: op.title });
|
|
591
|
+
return;
|
|
592
|
+
case "addTable": {
|
|
593
|
+
const result = run([{ kind: "addTable", table: op.table }], index);
|
|
594
|
+
const id = result.addedEntityIds[0];
|
|
595
|
+
if (op.position)
|
|
596
|
+
positioned.set(id, op.position);
|
|
597
|
+
else
|
|
598
|
+
unpositionedNodeIds.push(id);
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
case "renameTable":
|
|
602
|
+
run([{ kind: "renameTable", table: mapId(op.table), name: op.name, ...(op.schema !== undefined ? { schema: op.schema } : {}) }], index);
|
|
603
|
+
return;
|
|
604
|
+
case "removeTable":
|
|
605
|
+
run([{ kind: "removeTable", table: mapId(op.table) }], index);
|
|
606
|
+
return;
|
|
607
|
+
case "setTableComment":
|
|
608
|
+
run([{ kind: "setTableComment", table: mapId(op.table), comment: op.comment }], index);
|
|
609
|
+
return;
|
|
610
|
+
case "addColumn":
|
|
611
|
+
run([{ kind: "addColumn", table: mapId(op.table), column: op.column, ...(op.after !== undefined ? { after: op.after } : {}) }], index);
|
|
612
|
+
return;
|
|
613
|
+
case "alterColumn":
|
|
614
|
+
run([{ kind: "alterColumn", table: mapId(op.table), column: op.column, changes: op.changes }], index);
|
|
615
|
+
return;
|
|
616
|
+
case "removeColumn":
|
|
617
|
+
run([{ kind: "removeColumn", table: mapId(op.table), column: op.column }], index);
|
|
618
|
+
return;
|
|
619
|
+
case "setPrimaryKey":
|
|
620
|
+
run([{ kind: "setPrimaryKey", table: mapId(op.table), columns: op.columns }], index);
|
|
621
|
+
return;
|
|
622
|
+
case "addRelationship":
|
|
623
|
+
run([
|
|
624
|
+
{
|
|
625
|
+
kind: "addRelationship",
|
|
626
|
+
...(op.id ? { id: op.id } : {}),
|
|
627
|
+
source: endInput(op.source),
|
|
628
|
+
target: endInput(op.target),
|
|
629
|
+
...(op.cardinality ? { cardinality: op.cardinality } : {}),
|
|
630
|
+
...(op.kind ? { relationshipKind: op.kind } : {}),
|
|
631
|
+
...(op.name ? { name: op.name } : {}),
|
|
632
|
+
...(op.label ? { label: op.label } : {}),
|
|
633
|
+
},
|
|
634
|
+
], index);
|
|
635
|
+
return;
|
|
636
|
+
case "updateRelationship": {
|
|
637
|
+
const { kind: relationshipKind, source, target, ...rest } = op.changes;
|
|
638
|
+
run([
|
|
639
|
+
{
|
|
640
|
+
kind: "updateRelationship",
|
|
641
|
+
relationship: relationshipIdOf(op.relationship),
|
|
642
|
+
changes: { ...rest, ...(source !== undefined ? { source: endInput(source) } : {}), ...(target !== undefined ? { target: endInput(target) } : {}), ...(relationshipKind ? { relationshipKind } : {}) },
|
|
643
|
+
},
|
|
644
|
+
], index);
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
case "removeRelationship":
|
|
648
|
+
run([{ kind: "removeRelationship", relationship: relationshipIdOf(op.relationship) }], index);
|
|
649
|
+
return;
|
|
650
|
+
case "hideTable":
|
|
651
|
+
presentation.push({ op: "updateNode", id: entityIdOf(op.table, index), changes: { hidden: true } });
|
|
652
|
+
return;
|
|
653
|
+
case "showTable":
|
|
654
|
+
presentation.push({ op: "updateNode", id: entityIdOf(op.table, index), changes: { hidden: false } });
|
|
655
|
+
return;
|
|
656
|
+
case "addNode": {
|
|
657
|
+
const { type } = resolveType(op.node.type, op.node.id ?? op.node.label ?? "node", options.strict, warnings, index, "database");
|
|
658
|
+
if (op.node.parent)
|
|
659
|
+
warnings.push((0, exports.parentWarning)(op.node.id ?? "node", op.node.parent, undefined, "database") ?? "");
|
|
660
|
+
const raw = op.node.data?.db ?? {};
|
|
661
|
+
const name = (typeof raw.name === "string" && raw.name.trim()) || (op.node.label ?? "").trim() || op.node.id?.trim() || "table";
|
|
662
|
+
const result = run([
|
|
663
|
+
{
|
|
664
|
+
kind: "addTable",
|
|
665
|
+
table: {
|
|
666
|
+
...(op.node.id?.trim() ? { id: op.node.id.trim() } : {}),
|
|
667
|
+
name,
|
|
668
|
+
...(typeof raw.schema === "string" && raw.schema.trim() ? { schema: raw.schema.trim() } : {}),
|
|
669
|
+
kind: (0, index_js_1.kindForDatabaseType)(type),
|
|
670
|
+
...(columnInputsOf(raw.columns ?? raw.columnInputs) ? { columns: columnInputsOf(raw.columns ?? raw.columnInputs) } : {}),
|
|
671
|
+
...(typeof raw.comment === "string" && raw.comment.trim() ? { comment: raw.comment.trim() } : {}),
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
], index);
|
|
675
|
+
const id = result.addedEntityIds[0];
|
|
676
|
+
if (op.node.position)
|
|
677
|
+
positioned.set(id, op.node.position);
|
|
678
|
+
else
|
|
679
|
+
unpositionedNodeIds.push(id);
|
|
680
|
+
if (op.node.hidden)
|
|
681
|
+
presentation.push({ op: "updateNode", id, changes: { hidden: true } });
|
|
682
|
+
if (op.node.collapsed)
|
|
683
|
+
presentation.push({ op: "updateNode", id, changes: { collapsed: true } });
|
|
684
|
+
if (op.node.locked)
|
|
685
|
+
presentation.push({ op: "updateNode", id, changes: { locked: true } });
|
|
686
|
+
if (op.node.style)
|
|
687
|
+
presentation.push({ op: "updateNode", id, changes: { style: (0, styleInput_js_1.styleInputToChanges)(undefined, op.node.style) } });
|
|
688
|
+
if (op.node.size)
|
|
689
|
+
presentation.push({ op: "resizeNode", id, size: op.node.size });
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
case "updateNode": {
|
|
693
|
+
const id = entityIdOf(op.id, index);
|
|
694
|
+
const changes = op.changes;
|
|
695
|
+
if (changes.parent)
|
|
696
|
+
noContainers(index);
|
|
697
|
+
const edits = [];
|
|
698
|
+
if (changes.type !== undefined) {
|
|
699
|
+
const { type } = resolveType(changes.type, id, options.strict, warnings, index, "database");
|
|
700
|
+
edits.push({ kind: "setTableKind", table: id, entityKind: (0, index_js_1.kindForDatabaseType)(type) });
|
|
701
|
+
}
|
|
702
|
+
const raw = changes.data && typeof changes.data.db === "object" && changes.data.db ? changes.data.db : undefined;
|
|
703
|
+
const requestedName = typeof raw?.name === "string" ? raw.name : typeof changes.label === "string" ? changes.label : undefined;
|
|
704
|
+
if (requestedName !== undefined) {
|
|
705
|
+
const dot = requestedName.lastIndexOf(".");
|
|
706
|
+
const schema = typeof raw?.schema === "string" ? raw.schema : dot > 0 ? requestedName.slice(0, dot) : undefined;
|
|
707
|
+
edits.push({ kind: "renameTable", table: id, name: dot > 0 && typeof raw?.name !== "string" ? requestedName.slice(dot + 1) : requestedName, ...(schema !== undefined ? { schema } : {}) });
|
|
708
|
+
}
|
|
709
|
+
else if (typeof raw?.schema === "string") {
|
|
710
|
+
const entity = (0, index_js_1.findEntity)(model, id);
|
|
711
|
+
if (entity)
|
|
712
|
+
edits.push({ kind: "renameTable", table: id, name: entity.name, schema: raw.schema || null });
|
|
713
|
+
}
|
|
714
|
+
if (raw && "comment" in raw)
|
|
715
|
+
edits.push({ kind: "setTableComment", table: id, comment: typeof raw.comment === "string" ? raw.comment : null });
|
|
716
|
+
const columns = raw ? columnInputsOf(raw.columns ?? raw.columnInputs) : undefined;
|
|
717
|
+
if (columns)
|
|
718
|
+
edits.push({ kind: "setColumns", table: id, columns });
|
|
719
|
+
if (edits.length > 0)
|
|
720
|
+
run(edits, index);
|
|
721
|
+
const nodeChanges = {};
|
|
722
|
+
if (changes.rotation !== undefined)
|
|
723
|
+
nodeChanges.rotation = changes.rotation;
|
|
724
|
+
if (changes.locked !== undefined)
|
|
725
|
+
nodeChanges.locked = changes.locked;
|
|
726
|
+
if (changes.hidden !== undefined)
|
|
727
|
+
nodeChanges.hidden = changes.hidden;
|
|
728
|
+
if (changes.collapsed !== undefined)
|
|
729
|
+
nodeChanges.collapsed = changes.collapsed;
|
|
730
|
+
if (changes.style !== undefined)
|
|
731
|
+
nodeChanges.style = changes.style === null ? null : (0, styleInput_js_1.styleInputToChanges)(doc.nodes.find((node) => node.id === id)?.style, changes.style);
|
|
732
|
+
if (Object.keys(nodeChanges).length > 0)
|
|
733
|
+
presentation.push({ op: "updateNode", id, changes: nodeChanges });
|
|
734
|
+
if (changes.size !== undefined)
|
|
735
|
+
presentation.push({ op: "resizeNode", id, size: changes.size });
|
|
736
|
+
if (changes.position !== undefined)
|
|
737
|
+
presentation.push({ op: "moveNodes", moves: [{ id, position: changes.position }] });
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
case "removeNode":
|
|
741
|
+
run([{ kind: "removeTable", table: entityIdOf(op.id, index) }], index);
|
|
742
|
+
return;
|
|
743
|
+
case "addEdge": {
|
|
744
|
+
const raw = op.edge.data?.db ?? {};
|
|
745
|
+
const refs = (value) => (Array.isArray(value) ? value.filter((item) => typeof item === "string") : []);
|
|
746
|
+
const result = run([
|
|
747
|
+
{
|
|
748
|
+
kind: "addRelationship",
|
|
749
|
+
...(op.edge.id?.trim() ? { id: op.edge.id.trim() } : {}),
|
|
750
|
+
source: { table: entityIdOf(op.edge.source, index), columns: refs(raw.sourceColumns) },
|
|
751
|
+
target: { table: entityIdOf(op.edge.target, index), columns: refs(raw.targetColumns) },
|
|
752
|
+
...((0, index_js_1.isValidCardinality)(raw.cardinality) ? { cardinality: raw.cardinality } : {}),
|
|
753
|
+
relationshipKind: raw.kind === "foreignKey" ? "foreignKey" : "manual",
|
|
754
|
+
...(typeof raw.name === "string" ? { name: raw.name } : {}),
|
|
755
|
+
...(op.edge.label ? { label: op.edge.label } : {}),
|
|
756
|
+
},
|
|
757
|
+
], index);
|
|
758
|
+
const id = result.addedRelationshipIds[0];
|
|
759
|
+
if (id && (op.edge.routing || op.edge.sourceSide || op.edge.targetSide || op.edge.color)) {
|
|
760
|
+
const edgeChanges = {};
|
|
761
|
+
if (op.edge.routing)
|
|
762
|
+
edgeChanges.routing = op.edge.routing;
|
|
763
|
+
if (op.edge.sourceSide)
|
|
764
|
+
edgeChanges.sourceHandle = op.edge.sourceSide;
|
|
765
|
+
if (op.edge.targetSide)
|
|
766
|
+
edgeChanges.targetHandle = op.edge.targetSide;
|
|
767
|
+
if (op.edge.color)
|
|
768
|
+
edgeChanges.style = { stroke: (0, styleInput_js_1.toTokenRef)(op.edge.color) };
|
|
769
|
+
presentation.push({ op: "updateEdge", id, changes: edgeChanges });
|
|
770
|
+
}
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
case "updateEdge": {
|
|
774
|
+
const id = relationshipIdOf(op.id);
|
|
775
|
+
const changes = op.changes;
|
|
776
|
+
const raw = changes.data && typeof changes.data.db === "object" && changes.data.db ? changes.data.db : undefined;
|
|
777
|
+
const refs = (value) => (Array.isArray(value) ? value.filter((item) => typeof item === "string") : undefined);
|
|
778
|
+
const relationshipChanges = {};
|
|
779
|
+
if (changes.source !== undefined || refs(raw?.sourceColumns))
|
|
780
|
+
relationshipChanges.source = { table: changes.source !== undefined ? entityIdOf(changes.source, index) : ((0, index_js_1.findEntity)(model, id) ? model.relationships.find((r) => r.id === id)?.source.entityId ?? "" : ""), columns: refs(raw?.sourceColumns) ?? (changes.source !== undefined ? [] : undefined) };
|
|
781
|
+
if (changes.target !== undefined || refs(raw?.targetColumns))
|
|
782
|
+
relationshipChanges.target = { table: changes.target !== undefined ? entityIdOf(changes.target, index) : model.relationships.find((r) => r.id === id)?.target.entityId ?? "", columns: refs(raw?.targetColumns) ?? (changes.target !== undefined ? [] : undefined) };
|
|
783
|
+
if ((0, index_js_1.isValidCardinality)(raw?.cardinality))
|
|
784
|
+
relationshipChanges.cardinality = raw.cardinality;
|
|
785
|
+
if (raw && (raw.kind === "manual" || raw.kind === "foreignKey"))
|
|
786
|
+
relationshipChanges.relationshipKind = raw.kind;
|
|
787
|
+
if (raw && "name" in raw)
|
|
788
|
+
relationshipChanges.name = typeof raw.name === "string" ? raw.name : null;
|
|
789
|
+
if (changes.label !== undefined)
|
|
790
|
+
relationshipChanges.label = changes.label === "" ? null : changes.label;
|
|
791
|
+
if (Object.keys(relationshipChanges).length > 0)
|
|
792
|
+
run([{ kind: "updateRelationship", relationship: id, changes: relationshipChanges }], index);
|
|
793
|
+
const edgeChanges = {};
|
|
794
|
+
if (changes.routing !== undefined)
|
|
795
|
+
edgeChanges.routing = changes.routing;
|
|
796
|
+
if (changes.sourceSide !== undefined)
|
|
797
|
+
edgeChanges.sourceHandle = changes.sourceSide;
|
|
798
|
+
if (changes.targetSide !== undefined)
|
|
799
|
+
edgeChanges.targetHandle = changes.targetSide;
|
|
800
|
+
if (changes.color !== undefined)
|
|
801
|
+
edgeChanges.style = { stroke: changes.color === null ? null : (0, styleInput_js_1.toTokenRef)(changes.color) };
|
|
802
|
+
if (Object.keys(edgeChanges).length > 0)
|
|
803
|
+
presentation.push({ op: "updateEdge", id, changes: edgeChanges });
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
case "removeEdge":
|
|
807
|
+
run([{ kind: "removeRelationship", relationship: relationshipIdOf(op.id) }], index);
|
|
808
|
+
return;
|
|
809
|
+
case "moveNode":
|
|
810
|
+
presentation.push({ op: "moveNodes", moves: [{ id: entityIdOf(op.id, index), position: op.position }] });
|
|
811
|
+
return;
|
|
812
|
+
case "setEdgeRoute": {
|
|
813
|
+
const changes = {};
|
|
814
|
+
if (op.routing !== undefined)
|
|
815
|
+
changes.routing = op.routing;
|
|
816
|
+
if (op.sourceSide !== undefined)
|
|
817
|
+
changes.sourceHandle = op.sourceSide;
|
|
818
|
+
if (op.targetSide !== undefined)
|
|
819
|
+
changes.targetHandle = op.targetSide;
|
|
820
|
+
if (op.waypoints !== undefined)
|
|
821
|
+
changes.waypoints = op.waypoints;
|
|
822
|
+
if (Object.keys(changes).length === 0) {
|
|
823
|
+
changes.waypoints = null;
|
|
824
|
+
changes.sourceAnchor = null;
|
|
825
|
+
changes.targetAnchor = null;
|
|
826
|
+
}
|
|
827
|
+
presentation.push({ op: "updateEdge", id: relationshipIdOf(op.id), changes });
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
case "reorder": {
|
|
831
|
+
const id = entityIdOf(op.id, index);
|
|
832
|
+
const count = doc.nodes.filter((node) => !node.parentId).length;
|
|
833
|
+
presentation.push({ op: "reorder", kind: "node", id, index: op.index === "front" ? Math.max(0, count - 1) : op.index === "back" ? 0 : op.index });
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
case "setCanvas":
|
|
837
|
+
presentation.push({ op: "setCanvas", changes: op.canvas });
|
|
838
|
+
return;
|
|
839
|
+
case "relayout":
|
|
840
|
+
relayout = { scope: op.scope, ...(op.direction ? { direction: op.direction } : {}) };
|
|
841
|
+
return;
|
|
842
|
+
case "reparent":
|
|
843
|
+
case "group":
|
|
844
|
+
case "ungroup":
|
|
845
|
+
noContainers(index);
|
|
846
|
+
return;
|
|
847
|
+
default:
|
|
848
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_INVALID_OP", `Unknown op "${op.op}"`, index);
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
const ops = [];
|
|
852
|
+
if (changed) {
|
|
853
|
+
ops.push({
|
|
854
|
+
op: "setSource",
|
|
855
|
+
source: { format: "database", text: (0, index_js_1.serializeDatabaseModel)(model), diagramType: "database", grammar: index_js_1.DATABASE_GRAMMAR_VERSION, valid: true },
|
|
856
|
+
resync: true,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
for (const [id, position] of positioned)
|
|
860
|
+
ops.push({ op: "moveNodes", moves: [{ id, position }] });
|
|
861
|
+
ops.push(...presentation);
|
|
862
|
+
return { ops, warnings: warnings.filter(Boolean), unpositionedNodeIds, ...(relayout ? { relayout } : {}), idMap };
|
|
863
|
+
};
|
|
864
|
+
const buildDiagramFromInput = (input, options = {}) => {
|
|
865
|
+
const kind = options.kind ?? "canvas";
|
|
866
|
+
const strict = options.strictTypes !== false;
|
|
867
|
+
const warnings = [];
|
|
868
|
+
const explicitIds = input.nodes.map((node) => node.id?.trim()).filter((id) => Boolean(id));
|
|
869
|
+
const duplicates = explicitIds.filter((id, index) => explicitIds.indexOf(id) !== index);
|
|
870
|
+
if (duplicates.length > 0) {
|
|
871
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_DUPLICATE_NODE_ID", `Duplicate node ids: ${[...new Set(duplicates)].join(", ")}`);
|
|
872
|
+
}
|
|
873
|
+
const genNodeId = options.idStrategy === "sequential" ? (0, ids_js_1.sequentialIdFactory)("n", explicitIds) : (0, ids_js_1.slugIdFactory)(explicitIds, "n");
|
|
874
|
+
const genEdgeId = (0, ids_js_1.sequentialIdFactory)("e", (input.edges ?? []).map((edge) => edge.id).filter((id) => Boolean(id)));
|
|
875
|
+
// Ids first so parents/edges can reference nodes declared later.
|
|
876
|
+
const ids = input.nodes.map((node) => node.id?.trim() || genNodeId(node.label ?? node.type));
|
|
877
|
+
const idSet = new Set(ids);
|
|
878
|
+
const unknown = [];
|
|
879
|
+
const nodes = input.nodes.map((node, index) => {
|
|
880
|
+
const id = ids[index];
|
|
881
|
+
if (node.parent && !idSet.has(node.parent)) {
|
|
882
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_PARENT_NOT_FOUND", `Node ${id} references parent "${node.parent}" which is not in nodes.`, index);
|
|
883
|
+
}
|
|
884
|
+
try {
|
|
885
|
+
return nodeFromInput(node, id, strict, warnings, index, kind);
|
|
886
|
+
}
|
|
887
|
+
catch (error) {
|
|
888
|
+
if (error instanceof ops_js_1.DiagramOpError && error.code === "DIAGRAM_UNKNOWN_COMPONENT_TYPE") {
|
|
889
|
+
const entry = error.data?.unknownTypes?.[0];
|
|
890
|
+
if (entry)
|
|
891
|
+
unknown.push(entry);
|
|
892
|
+
return nodeFromInput({ ...node, type: kind === "bpmn" ? "bpmn.task" : kind === "database" ? "db.table" : "rect", label: node.label ?? node.type }, id, false, [], index, kind);
|
|
893
|
+
}
|
|
894
|
+
throw error;
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
if (unknown.length > 0) {
|
|
898
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_UNKNOWN_COMPONENT_TYPE", `Unknown component type(s): ${unknown.map((entry) => entry.type).join(", ")}. Read callman://diagram/components for the catalog, or pass strictTypes:false to draw them as rectangles.`, -1, { unknownTypes: unknown });
|
|
899
|
+
}
|
|
900
|
+
const typeOf = (id) => nodes.find((node) => node.id === id)?.type;
|
|
901
|
+
for (const node of nodes) {
|
|
902
|
+
const warning = node.parentId ? (0, exports.parentWarning)(node.id, node.parentId, typeOf(node.parentId), kind) : null;
|
|
903
|
+
if (warning)
|
|
904
|
+
warnings.push(warning);
|
|
905
|
+
}
|
|
906
|
+
const edgeIds = new Set();
|
|
907
|
+
const edges = (input.edges ?? []).map((edge, index) => {
|
|
908
|
+
const id = edge.id?.trim() || genEdgeId();
|
|
909
|
+
if (edgeIds.has(id) || idSet.has(id))
|
|
910
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_DUPLICATE_EDGE_ID", `Duplicate edge id: ${id}`, index);
|
|
911
|
+
edgeIds.add(id);
|
|
912
|
+
for (const endpoint of [edge.source, edge.target]) {
|
|
913
|
+
if (!idSet.has(endpoint)) {
|
|
914
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_EDGE_ENDPOINT_NOT_FOUND", `Edge ${id} references "${endpoint}" which is not a node id.`, index);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
return edgeFromInput(edge, id, typeOf, kind);
|
|
918
|
+
});
|
|
919
|
+
const timestamp = options.createdAt ?? (0, schema_js_1.nowIso)();
|
|
920
|
+
const document = (0, normalize_js_1.normalizeDiagramStyles)({
|
|
921
|
+
schemaVersion: schema_js_1.SCHEMA_VERSION,
|
|
922
|
+
id: options.existingId ?? `doc_${Math.random().toString(36).slice(2, 10)}`,
|
|
923
|
+
meta: { title: input.title.trim(), createdAt: timestamp, updatedAt: options.now ?? (0, schema_js_1.nowIso)() },
|
|
924
|
+
canvas: {
|
|
925
|
+
background: input.canvas?.background ?? "dots",
|
|
926
|
+
gridSize: input.canvas?.gridSize ?? 16,
|
|
927
|
+
...(input.canvas?.defaultRouting ? { defaultRouting: input.canvas.defaultRouting } : {}),
|
|
928
|
+
},
|
|
929
|
+
nodes,
|
|
930
|
+
edges,
|
|
931
|
+
});
|
|
932
|
+
const parsed = (0, schema_js_1.safeParseDiagramDocument)(document);
|
|
933
|
+
if (!parsed.ok) {
|
|
934
|
+
throw new ops_js_1.DiagramOpError("DIAGRAM_DOCUMENT_INVALID", `The diagram document is invalid: ${parsed.errors.join("; ")}`, -1, { errors: parsed.errors });
|
|
935
|
+
}
|
|
936
|
+
return {
|
|
937
|
+
document: parsed.document,
|
|
938
|
+
warnings,
|
|
939
|
+
unpositionedNodeIds: input.nodes.filter((node) => !node.position).map((_node, index) => ids[index]),
|
|
940
|
+
};
|
|
941
|
+
};
|
|
942
|
+
exports.buildDiagramFromInput = buildDiagramFromInput;
|
|
943
|
+
// A container around the members' bounding box, members re-parented into it
|
|
944
|
+
// with their positions converted so nothing moves on the canvas.
|
|
945
|
+
const groupNodesOps = (doc, memberIds, options) => {
|
|
946
|
+
const byId = (0, geometry_js_1.indexNodes)(doc.nodes);
|
|
947
|
+
const members = memberIds.map((id) => byId.get(id)).filter((node) => Boolean(node));
|
|
948
|
+
const padding = options.padding ?? 24;
|
|
949
|
+
const titleHeight = options.titleHeight ?? 32;
|
|
950
|
+
const rects = members.map((node) => (0, geometry_js_1.absoluteRect)(node, byId));
|
|
951
|
+
const box = (0, geometry_js_1.boundingBox)(rects) ?? { x: 0, y: 0, width: 200, height: 120 };
|
|
952
|
+
// The container joins the first member's parent so nested groups stay nested.
|
|
953
|
+
const parentId = members[0]?.parentId;
|
|
954
|
+
const type = options.type ?? "frame";
|
|
955
|
+
const def = (0, componentCatalog_js_1.getDiagramComponent)(type);
|
|
956
|
+
const containerAbs = { x: box.x - padding, y: box.y - padding - titleHeight };
|
|
957
|
+
const container = {
|
|
958
|
+
id: options.id,
|
|
959
|
+
type,
|
|
960
|
+
position: (0, geometry_js_1.toParentRelative)(containerAbs, parentId, byId),
|
|
961
|
+
size: { width: box.width + padding * 2, height: box.height + padding * 2 + titleHeight },
|
|
962
|
+
label: options.label ?? def?.defaultLabel ?? "Group",
|
|
963
|
+
...(parentId ? { parentId } : {}),
|
|
964
|
+
};
|
|
965
|
+
const ops = [{ op: "addNode", node: container }];
|
|
966
|
+
const memberPositions = {};
|
|
967
|
+
members.forEach((member, index) => {
|
|
968
|
+
const abs = rects[index];
|
|
969
|
+
const position = { x: abs.x - containerAbs.x, y: abs.y - containerAbs.y };
|
|
970
|
+
memberPositions[member.id] = position;
|
|
971
|
+
ops.push({ op: "reparent", id: member.id, parentId: options.id, position });
|
|
972
|
+
});
|
|
973
|
+
return { ops, container, memberPositions };
|
|
974
|
+
};
|
|
975
|
+
exports.groupNodesOps = groupNodesOps;
|
|
976
|
+
const ungroupOps = (containerId) => [{ op: "removeNode", id: containerId, children: "lift" }];
|
|
977
|
+
exports.ungroupOps = ungroupOps;
|
|
978
|
+
// Place ONLY the given nodes (new ones from a patch) below the current
|
|
979
|
+
// bounding box, in rows — nothing that already has a position moves. Nodes
|
|
980
|
+
// inside a container are placed inside it, below its current content.
|
|
981
|
+
const placeNewNodesOps = (doc, nodeIds, gap = 40) => {
|
|
982
|
+
const wanted = new Set(nodeIds);
|
|
983
|
+
if (wanted.size === 0)
|
|
984
|
+
return [];
|
|
985
|
+
const byParent = new Map();
|
|
986
|
+
for (const node of doc.nodes) {
|
|
987
|
+
if (!wanted.has(node.id))
|
|
988
|
+
continue;
|
|
989
|
+
const list = byParent.get(node.parentId) ?? [];
|
|
990
|
+
list.push(node);
|
|
991
|
+
byParent.set(node.parentId, list);
|
|
992
|
+
}
|
|
993
|
+
const moves = [];
|
|
994
|
+
for (const [parentId, newcomers] of byParent) {
|
|
995
|
+
const placed = doc.nodes.filter((node) => !wanted.has(node.id) && (node.parentId ?? undefined) === parentId);
|
|
996
|
+
const maxY = placed.reduce((max, node) => Math.max(max, node.position.y + node.size.height), parentId ? 48 : 0);
|
|
997
|
+
const minX = placed.reduce((min, node) => Math.min(min, node.position.x), placed.length > 0 ? Infinity : parentId ? 24 : 0);
|
|
998
|
+
const startX = Number.isFinite(minX) ? minX : 0;
|
|
999
|
+
let cursorX = startX;
|
|
1000
|
+
let cursorY = placed.length > 0 ? maxY + gap * 2 : maxY;
|
|
1001
|
+
let rowHeight = 0;
|
|
1002
|
+
const rowLimit = 1200;
|
|
1003
|
+
for (const node of newcomers) {
|
|
1004
|
+
if (cursorX + node.size.width > rowLimit && cursorX > startX) {
|
|
1005
|
+
cursorX = startX;
|
|
1006
|
+
cursorY += rowHeight + gap;
|
|
1007
|
+
rowHeight = 0;
|
|
1008
|
+
}
|
|
1009
|
+
moves.push({ id: node.id, position: { x: cursorX, y: cursorY } });
|
|
1010
|
+
cursorX += node.size.width + gap;
|
|
1011
|
+
rowHeight = Math.max(rowHeight, node.size.height);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return moves.length > 0 ? [{ op: "moveNodes", moves }] : [];
|
|
1015
|
+
};
|
|
1016
|
+
exports.placeNewNodesOps = placeNewNodesOps;
|
|
1017
|
+
// Whether an ops batch (typically from a model) deletes a large part of the
|
|
1018
|
+
// diagram — hosts confirm with the user before applying such a batch.
|
|
1019
|
+
const assessOpsRisk = (doc, ops, threshold = 0.3, minimum = 3) => {
|
|
1020
|
+
const removes = new Set();
|
|
1021
|
+
const collect = (list) => {
|
|
1022
|
+
for (const op of list) {
|
|
1023
|
+
if (op.op === "removeNode")
|
|
1024
|
+
removes.add(op.id);
|
|
1025
|
+
else if (op.op === "batch")
|
|
1026
|
+
collect(op.ops);
|
|
1027
|
+
else if (op.op === "replaceDocument")
|
|
1028
|
+
for (const node of doc.nodes)
|
|
1029
|
+
if (!op.document.nodes.some((n) => n.id === node.id))
|
|
1030
|
+
removes.add(node.id);
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
collect(ops);
|
|
1034
|
+
const totalNodes = doc.nodes.length;
|
|
1035
|
+
const ratio = totalNodes === 0 ? 0 : removes.size / totalNodes;
|
|
1036
|
+
return { removesNodes: removes.size, totalNodes, ratio, destructive: removes.size >= minimum && ratio > threshold };
|
|
1037
|
+
};
|
|
1038
|
+
exports.assessOpsRisk = assessOpsRisk;
|
|
1039
|
+
//# sourceMappingURL=patchInput.js.map
|