@buun_group/plotwork-mcp 0.1.0-beta.7 → 0.1.0-beta.8
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/THIRD-PARTY-NOTICES.md +1 -1
- package/package.json +1 -1
- package/plotwork-mcp.mjs +700 -164
package/plotwork-mcp.mjs
CHANGED
|
@@ -51,7 +51,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
51
51
|
var package_default;
|
|
52
52
|
var init_package = __esm({
|
|
53
53
|
"package.json"() {
|
|
54
|
-
package_default = { version: "0.1.0-beta.
|
|
54
|
+
package_default = { version: "0.1.0-beta.8" };
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
|
|
@@ -160,6 +160,71 @@ var init_flow_node_types = __esm({
|
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
+
// ../../packages/diagrams/src/constants/auto-group-types.ts
|
|
164
|
+
var AUTO_GROUP_TYPES, REGION_CODE, AZURE_REGION_NAMES;
|
|
165
|
+
var init_auto_group_types = __esm({
|
|
166
|
+
"../../packages/diagrams/src/constants/auto-group-types.ts"() {
|
|
167
|
+
"use strict";
|
|
168
|
+
AUTO_GROUP_TYPES = {
|
|
169
|
+
network: { ends: ["vpc", "vnet", "network", "virtual network", "private network", "virtual private cloud", "vcn"] },
|
|
170
|
+
subnet: { ends: ["subnet", "subnets"] },
|
|
171
|
+
"public-subnet": { ends: ["public subnet", "public subnets"] },
|
|
172
|
+
"private-subnet": { ends: ["private subnet", "private subnets"] },
|
|
173
|
+
environment: { ends: ["environment", "env"], whole: ["production", "prod", "staging", "dev", "development", "qa", "uat"] },
|
|
174
|
+
"ci-cd": {
|
|
175
|
+
ends: ["ci", "ci cd", "cicd", "ci pipeline", "ci cd pipeline", "build pipeline", "release pipeline", "deploy pipeline", "deployment pipeline", "delivery pipeline"],
|
|
176
|
+
whole: ["pipeline", "pipelines"]
|
|
177
|
+
},
|
|
178
|
+
messaging: { ends: ["kafka", "kafka cluster", "queue", "queues", "message queue", "message queues", "event bus", "message bus", "messaging", "event streaming", "service bus", "pub sub", "pubsub"] },
|
|
179
|
+
cluster: { ends: ["kubernetes", "k8s", "kubernetes cluster", "k8s cluster", "eks cluster", "aks cluster", "gke cluster", "container cluster"], whole: ["cluster"] },
|
|
180
|
+
region: { ends: ["region"] },
|
|
181
|
+
account: { ends: ["aws account"] },
|
|
182
|
+
"data-tier": { ends: ["data", "data tier", "database tier", "data layer", "database layer", "databases", "data stores", "data store", "storage tier", "persistence", "persistence layer"] },
|
|
183
|
+
security: { ends: ["security", "iam", "security services"] },
|
|
184
|
+
observability: { ends: ["monitoring", "observability", "logging", "telemetry"] }
|
|
185
|
+
};
|
|
186
|
+
REGION_CODE = /^(?:(?:us|eu|ap|sa|ca|me|af|il|mx)-[a-z]+-\d|(?:us|europe|asia|australia|southamerica|northamerica|me|africa)-[a-z]+\d)$/;
|
|
187
|
+
AZURE_REGION_NAMES = /* @__PURE__ */ new Set([
|
|
188
|
+
"eastus",
|
|
189
|
+
"eastus2",
|
|
190
|
+
"westus",
|
|
191
|
+
"westus2",
|
|
192
|
+
"westus3",
|
|
193
|
+
"centralus",
|
|
194
|
+
"northcentralus",
|
|
195
|
+
"southcentralus",
|
|
196
|
+
"westcentralus",
|
|
197
|
+
"canadacentral",
|
|
198
|
+
"canadaeast",
|
|
199
|
+
"brazilsouth",
|
|
200
|
+
"northeurope",
|
|
201
|
+
"westeurope",
|
|
202
|
+
"uksouth",
|
|
203
|
+
"ukwest",
|
|
204
|
+
"francecentral",
|
|
205
|
+
"germanywestcentral",
|
|
206
|
+
"swedencentral",
|
|
207
|
+
"switzerlandnorth",
|
|
208
|
+
"norwayeast",
|
|
209
|
+
"polandcentral",
|
|
210
|
+
"italynorth",
|
|
211
|
+
"eastasia",
|
|
212
|
+
"southeastasia",
|
|
213
|
+
"japaneast",
|
|
214
|
+
"japanwest",
|
|
215
|
+
"koreacentral",
|
|
216
|
+
"centralindia",
|
|
217
|
+
"southindia",
|
|
218
|
+
"australiaeast",
|
|
219
|
+
"australiasoutheast",
|
|
220
|
+
"uaenorth",
|
|
221
|
+
"southafricanorth",
|
|
222
|
+
"qatarcentral",
|
|
223
|
+
"israelcentral"
|
|
224
|
+
]);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
163
228
|
// ../../packages/diagrams/src/constants/group-types.ts
|
|
164
229
|
function groupTypeIcon(type, provider, canUse = () => true) {
|
|
165
230
|
const spec = GROUP_TYPE_SPECS[type];
|
|
@@ -386,7 +451,7 @@ var init_auto_icons = __esm({
|
|
|
386
451
|
ICON_MODE_SPEC = {
|
|
387
452
|
key: "icons",
|
|
388
453
|
values: ICON_MODES.join(", "),
|
|
389
|
-
meaning: 'auto (the default): an item with no icon= gets the icon its label, else its sub= or tech=, names for certain: a brand ("Postgres"), a cloud product ("Amazon S3"), or in some kinds a role ("Email"). A name that is also an everyday word ("Vault") stays plain. icon=none keeps one item plain; off keeps all plain.',
|
|
454
|
+
meaning: 'auto (the default): an item with no icon= gets the icon its label, else its sub= or tech=, names for certain: a brand ("Postgres"), a cloud product ("Amazon S3"), or in some kinds a role ("Email"). A name that is also an everyday word ("Vault") stays plain. icon=none keeps one item plain; off keeps all plain, with flow edge labels, and stops a flow group taking its type from its name.',
|
|
390
455
|
example: 'flow "Checkout" icons=off'
|
|
391
456
|
};
|
|
392
457
|
PLAIN_WORD_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -643,7 +708,7 @@ var init_view_links = __esm({
|
|
|
643
708
|
};
|
|
644
709
|
CLI_RELEASE = {
|
|
645
710
|
packageName: "@buun_group/plotwork",
|
|
646
|
-
version: "0.1.0-beta.
|
|
711
|
+
version: "0.1.0-beta.9",
|
|
647
712
|
onNpm: true
|
|
648
713
|
};
|
|
649
714
|
}
|
|
@@ -3500,6 +3565,195 @@ var init_label_icons = __esm({
|
|
|
3500
3565
|
}
|
|
3501
3566
|
});
|
|
3502
3567
|
|
|
3568
|
+
// ../../packages/diagrams/src/constants/label-vocabulary.ts
|
|
3569
|
+
var EDGE_STYLES, LABEL_VERB_PHRASES, LABEL_VERB_MAX_WORDS, NOT_VERB_PHRASES, STYLE_STEPS;
|
|
3570
|
+
var init_label_vocabulary = __esm({
|
|
3571
|
+
"../../packages/diagrams/src/constants/label-vocabulary.ts"() {
|
|
3572
|
+
"use strict";
|
|
3573
|
+
EDGE_STYLES = {
|
|
3574
|
+
/** Reads stored data: a query, a select. */
|
|
3575
|
+
reads: { icon: "lucide:eye", role: "data" },
|
|
3576
|
+
/** Reads its settings, such as a Kubernetes ConfigMap; not stored data, so no role. */
|
|
3577
|
+
"reads-settings": { icon: "lucide:eye", role: null },
|
|
3578
|
+
/** Writes stored data: an insert, an update. */
|
|
3579
|
+
writes: { icon: "lucide:square-pen", role: "data" },
|
|
3580
|
+
/** Reads and writes a store the file names without saying which: a database, a bucket, a cache. */
|
|
3581
|
+
stores: { icon: "lucide:database", role: "data" },
|
|
3582
|
+
/** Mounts a volume or a claim. */
|
|
3583
|
+
mounts: { icon: "lucide:hard-drive", role: "data" },
|
|
3584
|
+
/** Sends, publishes, produces, or emits a message it does not wait for. */
|
|
3585
|
+
sends: { icon: "lucide:send", role: "async" },
|
|
3586
|
+
/** Receives, consumes, or subscribes to messages. */
|
|
3587
|
+
receives: { icon: "lucide:inbox", role: "async" },
|
|
3588
|
+
/** Calls or requests and waits for the answer. */
|
|
3589
|
+
calls: { icon: "lucide:arrow-right-left", role: null },
|
|
3590
|
+
/** Routes outside traffic: a host, a path, a public address, a DNS name. */
|
|
3591
|
+
routes: { icon: "lucide:globe", role: null },
|
|
3592
|
+
/** Needs another thing to be there first. */
|
|
3593
|
+
"depends-on": { icon: "lucide:link", role: null },
|
|
3594
|
+
/** Provides an API. */
|
|
3595
|
+
provides: { icon: "lucide:plug", role: null },
|
|
3596
|
+
/** Consumes an API. */
|
|
3597
|
+
consumes: { icon: "lucide:plug-zap", role: null },
|
|
3598
|
+
/** Starts another thing: a function on an event, a downstream pipeline. */
|
|
3599
|
+
triggers: { icon: "lucide:zap", role: null },
|
|
3600
|
+
/** Deploys to an environment. */
|
|
3601
|
+
deploys: { icon: "lucide:rocket", role: null },
|
|
3602
|
+
/** Grants a role, assumes one, or authenticates. */
|
|
3603
|
+
grants: { icon: "lucide:key-round", role: "identity" },
|
|
3604
|
+
/** Uses a credential: a secret, a password, a key. */
|
|
3605
|
+
secret: { icon: "lucide:key-round", role: "identity" },
|
|
3606
|
+
/** Reaches another over a private network: a private endpoint, VPC peering, VNet integration. */
|
|
3607
|
+
private: { icon: "lucide:lock", role: "private" },
|
|
3608
|
+
/** Is guarded by a firewall or a security group. */
|
|
3609
|
+
filters: { icon: "lucide:shield", role: null },
|
|
3610
|
+
/** Sends logs or telemetry. */
|
|
3611
|
+
reports: { icon: "lucide:activity", role: null },
|
|
3612
|
+
/** Pulls container images. */
|
|
3613
|
+
pulls: { icon: "lucide:download", role: null },
|
|
3614
|
+
/** Builds on a base, such as a Kustomize overlay on its base. */
|
|
3615
|
+
"builds-on": { icon: "lucide:layers", role: null },
|
|
3616
|
+
/** Includes a component. */
|
|
3617
|
+
includes: { icon: "lucide:package", role: null },
|
|
3618
|
+
/** Patches what another file holds. */
|
|
3619
|
+
patches: { icon: "lucide:replace", role: null }
|
|
3620
|
+
};
|
|
3621
|
+
LABEL_VERB_PHRASES = {
|
|
3622
|
+
reads: ["reads", "read", "reading", "reads from", "read from", "queries", "query", "querying", "looks up", "look up", "selects", "select from", "loads from", "fetches from"],
|
|
3623
|
+
writes: [
|
|
3624
|
+
"writes",
|
|
3625
|
+
"write",
|
|
3626
|
+
"writing",
|
|
3627
|
+
"writes to",
|
|
3628
|
+
"write to",
|
|
3629
|
+
"inserts",
|
|
3630
|
+
"insert",
|
|
3631
|
+
"inserts into",
|
|
3632
|
+
"updates",
|
|
3633
|
+
"update",
|
|
3634
|
+
"saves",
|
|
3635
|
+
"save",
|
|
3636
|
+
"saves to",
|
|
3637
|
+
"persists",
|
|
3638
|
+
"persist",
|
|
3639
|
+
"persists to",
|
|
3640
|
+
"deletes",
|
|
3641
|
+
"delete",
|
|
3642
|
+
"deletes from",
|
|
3643
|
+
"uploads",
|
|
3644
|
+
"upload",
|
|
3645
|
+
"uploads to",
|
|
3646
|
+
"upload to"
|
|
3647
|
+
],
|
|
3648
|
+
stores: ["stores", "store", "stores in", "store in", "caches", "caches in", "reads and writes", "reads writes", "read write", "read and write"],
|
|
3649
|
+
mounts: ["mounts", "mount"],
|
|
3650
|
+
sends: [
|
|
3651
|
+
"sends",
|
|
3652
|
+
"send",
|
|
3653
|
+
"sends to",
|
|
3654
|
+
"publishes",
|
|
3655
|
+
"publish",
|
|
3656
|
+
"publishes to",
|
|
3657
|
+
"publish to",
|
|
3658
|
+
"emits",
|
|
3659
|
+
"emit",
|
|
3660
|
+
"produces",
|
|
3661
|
+
"produce",
|
|
3662
|
+
"produces to",
|
|
3663
|
+
"enqueues",
|
|
3664
|
+
"enqueue",
|
|
3665
|
+
"pushes to",
|
|
3666
|
+
"notifies",
|
|
3667
|
+
"notify",
|
|
3668
|
+
"fires"
|
|
3669
|
+
],
|
|
3670
|
+
receives: ["receives", "receive", "consumes", "consume", "consumes from", "subscribes", "subscribes to", "subscribe to", "listens to", "listens on", "polls", "dequeues"],
|
|
3671
|
+
calls: ["calls", "call", "invokes", "invoke", "requests", "request", "fetches", "fetch", "queries api", "http", "https", "grpc", "rest", "graphql"],
|
|
3672
|
+
routes: ["routes", "routes to", "route to", "forwards", "forwards to", "forward to", "proxies", "proxies to", "redirects to", "load balances"],
|
|
3673
|
+
"depends-on": ["depends on", "depend on", "requires", "needs"],
|
|
3674
|
+
provides: ["provides", "exposes", "serves"],
|
|
3675
|
+
triggers: ["triggers", "trigger", "starts", "kicks off", "schedules", "wakes"],
|
|
3676
|
+
deploys: ["deploys", "deploy", "deploys to", "deploy to", "releases to", "ships to", "promotes to", "rolls out", "rolls out to"],
|
|
3677
|
+
grants: [
|
|
3678
|
+
"authenticates",
|
|
3679
|
+
"authenticate",
|
|
3680
|
+
"authenticates with",
|
|
3681
|
+
"authenticates against",
|
|
3682
|
+
"authorizes",
|
|
3683
|
+
"authorize",
|
|
3684
|
+
"authorises",
|
|
3685
|
+
"authorise",
|
|
3686
|
+
"signs in",
|
|
3687
|
+
"sign in",
|
|
3688
|
+
"signs in with",
|
|
3689
|
+
"logs in",
|
|
3690
|
+
"log in",
|
|
3691
|
+
"logs in with",
|
|
3692
|
+
"grants",
|
|
3693
|
+
"grant",
|
|
3694
|
+
"assumes role",
|
|
3695
|
+
"issues token",
|
|
3696
|
+
"issues tokens",
|
|
3697
|
+
"verifies token",
|
|
3698
|
+
"verify token",
|
|
3699
|
+
"validates token",
|
|
3700
|
+
"validate token",
|
|
3701
|
+
"logs out",
|
|
3702
|
+
"log out",
|
|
3703
|
+
"signs out",
|
|
3704
|
+
"sign out"
|
|
3705
|
+
],
|
|
3706
|
+
secret: ["reads secret", "reads secrets", "read secret", "read secrets", "read credentials", "fetches secret", "fetches secrets", "reads credentials", "gets secret", "gets secrets"],
|
|
3707
|
+
reports: [
|
|
3708
|
+
"reports",
|
|
3709
|
+
"reports to",
|
|
3710
|
+
"logs",
|
|
3711
|
+
"logs to",
|
|
3712
|
+
"metrics",
|
|
3713
|
+
"telemetry",
|
|
3714
|
+
"traces",
|
|
3715
|
+
"logs and metrics",
|
|
3716
|
+
"sends logs",
|
|
3717
|
+
"sends logs to",
|
|
3718
|
+
"sends metrics",
|
|
3719
|
+
"sends metrics to",
|
|
3720
|
+
"sends telemetry",
|
|
3721
|
+
"sends traces",
|
|
3722
|
+
"ships logs",
|
|
3723
|
+
"ships logs to",
|
|
3724
|
+
"exports metrics",
|
|
3725
|
+
"exports traces",
|
|
3726
|
+
"emits metrics",
|
|
3727
|
+
"emits logs"
|
|
3728
|
+
],
|
|
3729
|
+
pulls: ["pulls image", "pulls images", "pulls images from", "pulls image from"]
|
|
3730
|
+
};
|
|
3731
|
+
LABEL_VERB_MAX_WORDS = 5;
|
|
3732
|
+
NOT_VERB_PHRASES = [
|
|
3733
|
+
"read replica",
|
|
3734
|
+
"read replicas",
|
|
3735
|
+
"read model",
|
|
3736
|
+
"read only",
|
|
3737
|
+
"write model",
|
|
3738
|
+
"write ahead",
|
|
3739
|
+
"request id",
|
|
3740
|
+
"request body",
|
|
3741
|
+
"call center",
|
|
3742
|
+
"call centre",
|
|
3743
|
+
"update available",
|
|
3744
|
+
"query string",
|
|
3745
|
+
"query params"
|
|
3746
|
+
];
|
|
3747
|
+
STYLE_STEPS = [
|
|
3748
|
+
'Label each arrow with a verb, such as "reads", "writes orders", "publishes OrderPlaced", "calls", "deploys to", or "authenticates": the label then draws the icon of that relationship (verbIcons). icon= picks another icon; icon=none keeps the label plain.',
|
|
3749
|
+
"Add role= to the arrows whose line means something: role=data for reads and writes of stored data, role=async for messages nobody waits for, role=identity for sign-in and credentials, role=private for private network links. The line takes the role's colour and the legend names it; warning W500 lists the arrows to mark.",
|
|
3750
|
+
'Give every group a type= (network, subnet, environment, data-tier, messaging, cluster, ci-cd, observability, and the rest), so its frame, tone, and icon follow. A group named plainly, such as "VPC", "Production", "Kafka", or "Monitoring", gets its type by itself; type=none keeps it plain.',
|
|
3751
|
+
'Name each node after the product it is ("Postgres", "Redis", "Amazon S3") so it draws the mark, and choose the node type that says what it is.',
|
|
3752
|
+
"Keep labels to two to four words; the picture carries the rest."
|
|
3753
|
+
];
|
|
3754
|
+
}
|
|
3755
|
+
});
|
|
3756
|
+
|
|
3503
3757
|
// ../../packages/diagrams/src/constants/status-icons.ts
|
|
3504
3758
|
var STATUS_ICON_SPECS;
|
|
3505
3759
|
var init_status_icons = __esm({
|
|
@@ -3548,6 +3802,7 @@ var init_constants = __esm({
|
|
|
3548
3802
|
init_directions();
|
|
3549
3803
|
init_word_list();
|
|
3550
3804
|
init_flow_node_types();
|
|
3805
|
+
init_auto_group_types();
|
|
3551
3806
|
init_group_types();
|
|
3552
3807
|
init_overlays();
|
|
3553
3808
|
init_node_change();
|
|
@@ -3576,6 +3831,7 @@ var init_constants = __esm({
|
|
|
3576
3831
|
init_icon_concepts();
|
|
3577
3832
|
init_icon_sets();
|
|
3578
3833
|
init_label_icons();
|
|
3834
|
+
init_label_vocabulary();
|
|
3579
3835
|
init_status_icons();
|
|
3580
3836
|
init_tones();
|
|
3581
3837
|
}
|
|
@@ -3644,7 +3900,7 @@ function formatDiagnostic(diagnostic, source) {
|
|
|
3644
3900
|
if (diagnostic.hint !== null) parts.push(`hint: ${diagnostic.hint}`);
|
|
3645
3901
|
return parts.join("\n");
|
|
3646
3902
|
}
|
|
3647
|
-
var DIAGNOSTIC_CODES;
|
|
3903
|
+
var DIAGNOSTIC_CODES, STYLE_HINT_CODES;
|
|
3648
3904
|
var init_diagnostics = __esm({
|
|
3649
3905
|
"../../packages/diagrams/src/core/diagnostics.ts"() {
|
|
3650
3906
|
"use strict";
|
|
@@ -3677,6 +3933,9 @@ var init_diagnostics = __esm({
|
|
|
3677
3933
|
suggestIcon: "W204",
|
|
3678
3934
|
suggestGroupType: "W205",
|
|
3679
3935
|
overlayCovers: "W206",
|
|
3936
|
+
// Style suggestions. W5xx says how a valid diagram would look more finished; like W204 and W205 it is a suggestion, not a problem
|
|
3937
|
+
// (`isStyleHint`), so a check that fails on warnings passes it.
|
|
3938
|
+
suggestLineRole: "W500",
|
|
3680
3939
|
// Mermaid import. M1xx stops a conversion; M2xx reports something dropped or changed and never stops it.
|
|
3681
3940
|
// They point into the Mermaid source that was submitted, not into the Plotwork source.
|
|
3682
3941
|
mermaidNotDiagram: "M100",
|
|
@@ -3853,6 +4112,7 @@ var init_diagnostics = __esm({
|
|
|
3853
4112
|
overrideRefused: "S202",
|
|
3854
4113
|
overridesMissing: "S203"
|
|
3855
4114
|
};
|
|
4115
|
+
STYLE_HINT_CODES = /* @__PURE__ */ new Set([DIAGNOSTIC_CODES.suggestIcon, DIAGNOSTIC_CODES.suggestGroupType, DIAGNOSTIC_CODES.suggestLineRole]);
|
|
3856
4116
|
}
|
|
3857
4117
|
});
|
|
3858
4118
|
|
|
@@ -4023,13 +4283,13 @@ function indexOf(set2) {
|
|
|
4023
4283
|
const known3 = indexes.get(set2);
|
|
4024
4284
|
if (known3 !== void 0) return known3;
|
|
4025
4285
|
const byName = /* @__PURE__ */ new Map();
|
|
4026
|
-
const
|
|
4286
|
+
const phrases2 = /* @__PURE__ */ new Map();
|
|
4027
4287
|
for (const icon of set2.icons) {
|
|
4028
4288
|
if (byName.has(icon.name)) continue;
|
|
4029
4289
|
byName.set(icon.name, definitionOf(icon));
|
|
4030
|
-
|
|
4290
|
+
phrases2.set(icon.name, new Set([normalizePhrase(icon.name), ...icon.aliases.map(normalizePhrase)].filter(Boolean)));
|
|
4031
4291
|
}
|
|
4032
|
-
const index2 = { byName, phrases };
|
|
4292
|
+
const index2 = { byName, phrases: phrases2 };
|
|
4033
4293
|
indexes.set(set2, index2);
|
|
4034
4294
|
return index2;
|
|
4035
4295
|
}
|
|
@@ -6697,9 +6957,9 @@ function cloudPhrases(generic) {
|
|
|
6697
6957
|
const ref = `${set2}:${spec.name}`;
|
|
6698
6958
|
const bases = [normalizePhrase(spec.name), ...(spec.aliases ?? []).map(normalizePhrase)];
|
|
6699
6959
|
const title = normalizePhrase(spec.title);
|
|
6700
|
-
const
|
|
6701
|
-
for (const providerName2 of providerNames) for (const base of bases)
|
|
6702
|
-
for (const phrase2 of
|
|
6960
|
+
const phrases2 = /* @__PURE__ */ new Set([title, ...bases]);
|
|
6961
|
+
for (const providerName2 of providerNames) for (const base of bases) phrases2.add(`${providerName2} ${base}`);
|
|
6962
|
+
for (const phrase2 of phrases2) {
|
|
6703
6963
|
if (spec.vendor !== void 0 && claimed.has(phrase2)) continue;
|
|
6704
6964
|
const isScoped = spec.scopeToProvider === true && phrase2 !== title && !providerNames.some((providerName2) => phrase2.startsWith(`${providerName2} `));
|
|
6705
6965
|
out.push({ phrase: phrase2, words: phrase2.split(" ").length, ref, set: set2, isGeneric: generic.has(phrase2) || isScoped, isBrand: false });
|
|
@@ -6712,8 +6972,8 @@ function cloudPhrases(generic) {
|
|
|
6712
6972
|
function brandPhrases() {
|
|
6713
6973
|
return listSetNames("simple").flatMap((name2) => {
|
|
6714
6974
|
const ref = `simple:${name2}`;
|
|
6715
|
-
const
|
|
6716
|
-
return [...
|
|
6975
|
+
const phrases2 = /* @__PURE__ */ new Set([normalizePhrase(name2), ...(ICON_ALIASES[ref] ?? []).map(normalizePhrase), ...(findIcon(ref)?.aliases ?? []).map(normalizePhrase)]);
|
|
6976
|
+
return [...phrases2].map((phrase2) => ({ phrase: phrase2, words: phrase2.split(" ").length, ref, set: "simple", isGeneric: false, isBrand: true }));
|
|
6717
6977
|
});
|
|
6718
6978
|
}
|
|
6719
6979
|
function listProductPhrases() {
|
|
@@ -6800,7 +7060,7 @@ function indexIcon(ref) {
|
|
|
6800
7060
|
const glyph = glyphNameOf(ref);
|
|
6801
7061
|
const plainNames = [normalizePhrase(name2), ...(ICON_ALIASES[ref] ?? []).map(normalizePhrase)];
|
|
6802
7062
|
const aliases = (icon?.aliases ?? []).map(normalizePhrase);
|
|
6803
|
-
const
|
|
7063
|
+
const phrases2 = /* @__PURE__ */ new Set([...plainNames, ...aliases]);
|
|
6804
7064
|
const kindPhrases = /* @__PURE__ */ new Set();
|
|
6805
7065
|
const providerKindPhrases = /* @__PURE__ */ new Set();
|
|
6806
7066
|
const titleWords = /* @__PURE__ */ new Set();
|
|
@@ -6809,11 +7069,11 @@ function indexIcon(ref) {
|
|
|
6809
7069
|
for (const word2 of normalizePhrase(spec.title).split(" ")) titleWords.add(word2);
|
|
6810
7070
|
for (const base of [...plainNames, ...aliases, normalizePhrase(spec.title)]) stems.add(stemPhrase(base));
|
|
6811
7071
|
const provider = CLOUD_PROVIDER_SPECS[cloudSet];
|
|
6812
|
-
|
|
6813
|
-
if (spec.kind === "provider") for (const providerName2 of provider.names)
|
|
7072
|
+
phrases2.add(normalizePhrase(spec.title));
|
|
7073
|
+
if (spec.kind === "provider") for (const providerName2 of provider.names) phrases2.add(providerName2);
|
|
6814
7074
|
const kindPhraseList = CLOUD_KIND_SPECS[spec.kind].phrases.map(normalizePhrase);
|
|
6815
7075
|
for (const providerName2 of provider.names) {
|
|
6816
|
-
for (const base of [...plainNames, ...aliases])
|
|
7076
|
+
for (const base of [...plainNames, ...aliases]) phrases2.add(`${providerName2} ${base}`);
|
|
6817
7077
|
for (const kindPhrase of kindPhraseList) providerKindPhrases.add(`${providerName2} ${kindPhrase}`);
|
|
6818
7078
|
}
|
|
6819
7079
|
for (const kindPhrase of kindPhraseList) kindPhrases.add(kindPhrase);
|
|
@@ -6822,8 +7082,8 @@ function indexIcon(ref) {
|
|
|
6822
7082
|
ref,
|
|
6823
7083
|
tags: (icon?.tags ?? []).map((tag) => tag.toLowerCase()),
|
|
6824
7084
|
concept: glyph === null ? void 0 : CONCEPTS_BY_GLYPH.get(glyph),
|
|
6825
|
-
phrases,
|
|
6826
|
-
haystack: ` ${[...
|
|
7085
|
+
phrases: phrases2,
|
|
7086
|
+
haystack: ` ${[...phrases2].join(" | ")} `,
|
|
6827
7087
|
stems,
|
|
6828
7088
|
titleWords,
|
|
6829
7089
|
isVendorOnly: spec?.vendor !== void 0,
|
|
@@ -110258,9 +110518,39 @@ var init_flow_outline = __esm({
|
|
|
110258
110518
|
}
|
|
110259
110519
|
});
|
|
110260
110520
|
|
|
110521
|
+
// ../../packages/diagrams/src/parse/label-icon.ts
|
|
110522
|
+
function verbPhrases() {
|
|
110523
|
+
phrases ??= Object.entries(LABEL_VERB_PHRASES).flatMap(([verb, words2]) => (words2 ?? []).map((phrase2) => [phrase2, verb])).sort((a, b) => b[0].split(" ").length - a[0].split(" ").length || b[0].length - a[0].length);
|
|
110524
|
+
return phrases;
|
|
110525
|
+
}
|
|
110526
|
+
function startsWithWords(text3, phrase2) {
|
|
110527
|
+
return text3 === phrase2 || text3.startsWith(`${phrase2} `);
|
|
110528
|
+
}
|
|
110529
|
+
function verbNamedBy(label) {
|
|
110530
|
+
const text3 = normalizePhrase(label);
|
|
110531
|
+
if (text3 === "" || text3.split(" ").length > LABEL_VERB_MAX_WORDS) return null;
|
|
110532
|
+
if (NOT_VERB_PHRASES.some((phrase2) => startsWithWords(text3, phrase2))) return null;
|
|
110533
|
+
const found = verbPhrases().find(([phrase2]) => startsWithWords(text3, phrase2));
|
|
110534
|
+
return found === void 0 ? null : found[1];
|
|
110535
|
+
}
|
|
110536
|
+
function labelIconFor(label) {
|
|
110537
|
+
const word2 = label.trim().toLowerCase();
|
|
110538
|
+
if (Object.hasOwn(LABEL_ICON_DEFAULTS, word2)) return LABEL_ICON_DEFAULTS[word2] ?? null;
|
|
110539
|
+
const verb = verbNamedBy(label);
|
|
110540
|
+
return verb === null ? null : EDGE_STYLES[verb].icon;
|
|
110541
|
+
}
|
|
110542
|
+
var phrases;
|
|
110543
|
+
var init_label_icon = __esm({
|
|
110544
|
+
"../../packages/diagrams/src/parse/label-icon.ts"() {
|
|
110545
|
+
"use strict";
|
|
110546
|
+
init_constants();
|
|
110547
|
+
init_phrase();
|
|
110548
|
+
}
|
|
110549
|
+
});
|
|
110550
|
+
|
|
110261
110551
|
// ../../packages/diagrams/src/parse/group-options.ts
|
|
110262
110552
|
function resolveGroupType(option, state) {
|
|
110263
|
-
if (option === void 0) return null;
|
|
110553
|
+
if (option === void 0 || option.value === PLAIN_GROUP_TYPE) return null;
|
|
110264
110554
|
const type = GROUP_TYPES.find((candidate2) => candidate2 === option.value);
|
|
110265
110555
|
if (type !== void 0) return type;
|
|
110266
110556
|
state.report.push(errorAt(DIAGNOSTIC_CODES.unknownGroupType, `Unknown group type "${option.value}"`, option.valueToken, didYouMean(option.value, GROUP_TYPES)));
|
|
@@ -110273,8 +110563,29 @@ function resolveProvider(option, state) {
|
|
|
110273
110563
|
state.report.push(errorAt(DIAGNOSTIC_CODES.unknownProvider, `Unknown provider "${option.value}"`, option.valueToken, providerHint(option.value)));
|
|
110274
110564
|
return null;
|
|
110275
110565
|
}
|
|
110276
|
-
function
|
|
110277
|
-
|
|
110566
|
+
function wordsOf2(phrase2) {
|
|
110567
|
+
return phrase2.split(" ").length;
|
|
110568
|
+
}
|
|
110569
|
+
function longestOtherReading(normalized, type) {
|
|
110570
|
+
const lengths = GROUP_TYPES.filter((other) => other !== type).flatMap((other) => GROUP_TYPE_SPECS[other].phrases.filter((phrase2) => ` ${normalized} `.includes(` ${phrase2} `)).map(wordsOf2));
|
|
110571
|
+
return Math.max(0, ...lengths);
|
|
110572
|
+
}
|
|
110573
|
+
function autoGroupType(label) {
|
|
110574
|
+
const trimmed4 = label.trim().toLowerCase();
|
|
110575
|
+
if (REGION_CODE.test(trimmed4) || AZURE_REGION_NAMES.has(trimmed4)) return "region";
|
|
110576
|
+
const normalized = normalizePhrase(label);
|
|
110577
|
+
let best = null;
|
|
110578
|
+
for (const [type, phrases2] of Object.entries(AUTO_GROUP_TYPES)) {
|
|
110579
|
+
const fits = [...(phrases2?.ends ?? []).filter((phrase2) => normalized === phrase2 || normalized.endsWith(` ${phrase2}`)), ...(phrases2?.whole ?? []).filter((phrase2) => normalized === phrase2)];
|
|
110580
|
+
for (const phrase2 of fits) if (best === null || wordsOf2(phrase2) > best.words) best = { type, words: wordsOf2(phrase2) };
|
|
110581
|
+
}
|
|
110582
|
+
return best === null || longestOtherReading(normalized, best.type) > best.words ? null : best.type;
|
|
110583
|
+
}
|
|
110584
|
+
function resolveGroupLook(options3, parent, state, label = null) {
|
|
110585
|
+
const typeOption = findOption(options3, "type");
|
|
110586
|
+
const isPlain = typeOption?.value === PLAIN_GROUP_TYPE;
|
|
110587
|
+
const named = typeOption === void 0 && label !== null && !iconsAreOff(state) ? autoGroupType(label) : null;
|
|
110588
|
+
const type = named ?? resolveGroupType(typeOption, state);
|
|
110278
110589
|
const inherited = parent === null ? state.provider : state.groups.find((group2) => group2.id === parent)?.provider ?? state.provider;
|
|
110279
110590
|
const provider = resolveProvider(findOption(options3, "provider"), state) ?? inherited;
|
|
110280
110591
|
const spec = type === null ? null : GROUP_TYPE_SPECS[type];
|
|
@@ -110283,19 +110594,24 @@ function resolveGroupLook(options3, parent, state) {
|
|
|
110283
110594
|
provider,
|
|
110284
110595
|
tone: resolveTone(findOption(options3, "tone"), spec?.tone ?? GROUP_DEFAULTS.tone, state),
|
|
110285
110596
|
icon: resolveIcon(findOption(options3, "icon"), type === null ? GROUP_DEFAULTS.icon : groupIcon(type, provider), state),
|
|
110286
|
-
frame: spec?.frame ?? GROUP_DEFAULTS.frame
|
|
110597
|
+
frame: spec?.frame ?? GROUP_DEFAULTS.frame,
|
|
110598
|
+
...isPlain ? { isPlain: true } : {}
|
|
110287
110599
|
};
|
|
110288
110600
|
}
|
|
110601
|
+
var PLAIN_GROUP_TYPE;
|
|
110289
110602
|
var init_group_options = __esm({
|
|
110290
110603
|
"../../packages/diagrams/src/parse/group-options.ts"() {
|
|
110291
110604
|
"use strict";
|
|
110292
110605
|
init_constants();
|
|
110293
110606
|
init_core();
|
|
110294
110607
|
init_icons();
|
|
110608
|
+
init_phrase();
|
|
110609
|
+
init_auto_icon();
|
|
110295
110610
|
init_icon_hint();
|
|
110296
110611
|
init_options();
|
|
110297
110612
|
init_statement_helpers();
|
|
110298
110613
|
init_suggest();
|
|
110614
|
+
PLAIN_GROUP_TYPE = "none";
|
|
110299
110615
|
}
|
|
110300
110616
|
});
|
|
110301
110617
|
|
|
@@ -110538,7 +110854,7 @@ function parseGroupStatement(cursor, state, line3, parent) {
|
|
|
110538
110854
|
state.groups.push({
|
|
110539
110855
|
id: groupId,
|
|
110540
110856
|
label,
|
|
110541
|
-
...resolveGroupLook(options3, parent, state),
|
|
110857
|
+
...resolveGroupLook(options3, parent, state, label),
|
|
110542
110858
|
parent,
|
|
110543
110859
|
sub: findOption(options3, "sub")?.value ?? null,
|
|
110544
110860
|
stack: resolveStack(findOption(options3, "stack"), state, true),
|
|
@@ -110565,12 +110881,12 @@ function parseEdgeStatement(cursor, state, line3) {
|
|
|
110565
110881
|
if (iconOption2 !== void 0 && label === null) {
|
|
110566
110882
|
state.report.push(errorAt(DIAGNOSTIC_CODES.syntax, "An edge icon needs a label", iconOption2.keyToken, 'Write: a -> b : "label" icon=status:success'));
|
|
110567
110883
|
}
|
|
110568
|
-
const icon = resolveIcon(iconOption2, label === null ? null :
|
|
110884
|
+
const icon = resolveIcon(iconOption2, label === null || iconsAreOff(state) ? null : labelIconFor(label), state);
|
|
110569
110885
|
rejectTrailing(cursor, state, "Write one edge per line; chains like a -> b -> c are not supported.");
|
|
110570
110886
|
const spec = ARROW_SPECS[arrow.text];
|
|
110571
110887
|
const motion = readLineMotion(options3, state.motion, spec.heads, from, state.report);
|
|
110572
110888
|
const role = readLineRole(findOption(options3, "role"), state.report);
|
|
110573
|
-
state.edges.push({ from: from.text, to: to.text, fromToken: from, toToken: to, label, icon, line: spec.line, heads: spec.heads, ...motion, ...role === void 0 ? {} : { role } });
|
|
110889
|
+
state.edges.push({ from: from.text, to: to.text, fromToken: from, toToken: to, label, icon, ...iconOption2 === void 0 ? {} : { hasOwnIcon: true }, line: spec.line, heads: spec.heads, ...motion, ...role === void 0 ? {} : { role } });
|
|
110574
110890
|
}
|
|
110575
110891
|
function parseOverlayStatement(cursor, state, line3, parent) {
|
|
110576
110892
|
cursor.next();
|
|
@@ -110611,6 +110927,7 @@ var init_flow_statements = __esm({
|
|
|
110611
110927
|
init_constants();
|
|
110612
110928
|
init_core();
|
|
110613
110929
|
init_auto_icon();
|
|
110930
|
+
init_label_icon();
|
|
110614
110931
|
init_group_options();
|
|
110615
110932
|
init_line_motion();
|
|
110616
110933
|
init_line_role();
|
|
@@ -110757,6 +111074,7 @@ function resolveEdges(state) {
|
|
|
110757
111074
|
to: toNodeId(edge.to),
|
|
110758
111075
|
label: edge.label,
|
|
110759
111076
|
icon: edge.icon,
|
|
111077
|
+
...edge.hasOwnIcon === void 0 ? {} : { hasOwnIcon: edge.hasOwnIcon },
|
|
110760
111078
|
line: edge.line,
|
|
110761
111079
|
heads: edge.heads,
|
|
110762
111080
|
...edge.isAnimated === void 0 ? {} : { isAnimated: edge.isAnimated },
|
|
@@ -111159,7 +111477,7 @@ function typesNamedBy(label) {
|
|
|
111159
111477
|
function suggestGroupTypes(diagram) {
|
|
111160
111478
|
const warnings = [];
|
|
111161
111479
|
for (const group2 of diagram.groups) {
|
|
111162
|
-
if (group2.type !== null) continue;
|
|
111480
|
+
if (group2.type !== null || group2.isPlain === true) continue;
|
|
111163
111481
|
const types = typesNamedBy(group2.label);
|
|
111164
111482
|
const [type] = types;
|
|
111165
111483
|
if (types.length !== 1 || type === void 0) continue;
|
|
@@ -111177,7 +111495,6 @@ function suggestGroupTypes(diagram) {
|
|
|
111177
111495
|
}
|
|
111178
111496
|
return warnings;
|
|
111179
111497
|
}
|
|
111180
|
-
var REGION_CODE;
|
|
111181
111498
|
var init_suggest_group_types = __esm({
|
|
111182
111499
|
"../../packages/diagrams/src/lint/suggest-group-types.ts"() {
|
|
111183
111500
|
"use strict";
|
|
@@ -111185,7 +111502,53 @@ var init_suggest_group_types = __esm({
|
|
|
111185
111502
|
init_core();
|
|
111186
111503
|
init_icons();
|
|
111187
111504
|
init_suggest_icons();
|
|
111188
|
-
|
|
111505
|
+
}
|
|
111506
|
+
});
|
|
111507
|
+
|
|
111508
|
+
// ../../packages/diagrams/src/lint/suggest-line-roles.ts
|
|
111509
|
+
function nameOf(edge) {
|
|
111510
|
+
return `${edge.from} -> ${edge.to}`;
|
|
111511
|
+
}
|
|
111512
|
+
function suggestLineRoles(diagram) {
|
|
111513
|
+
const byRole = /* @__PURE__ */ new Map();
|
|
111514
|
+
for (const edge of diagram.edges) {
|
|
111515
|
+
if (edge.role !== void 0 || edge.hasOwnIcon === true || edge.label === null) continue;
|
|
111516
|
+
const verb = verbNamedBy(edge.label);
|
|
111517
|
+
const role = verb === null ? null : EDGE_STYLES[verb].role;
|
|
111518
|
+
if (role !== null) byRole.set(role, [...byRole.get(role) ?? [], edge]);
|
|
111519
|
+
}
|
|
111520
|
+
return LINE_ROLES.flatMap((role) => {
|
|
111521
|
+
const edges = byRole.get(role) ?? [];
|
|
111522
|
+
if (edges.length === 0) return [];
|
|
111523
|
+
const named = edges.slice(0, NAMED_ARROWS).map(nameOf).join(", ");
|
|
111524
|
+
const rest = edges.length > NAMED_ARROWS ? ` and ${edges.length - NAMED_ARROWS} more` : "";
|
|
111525
|
+
const doing = edges.length === 1 ? `1 arrow ${ROLE_DOING[role].one}` : `${edges.length} arrows ${ROLE_DOING[role].many}`;
|
|
111526
|
+
const spec = LINE_ROLE_SPECS[role];
|
|
111527
|
+
return [
|
|
111528
|
+
warningAt(
|
|
111529
|
+
DIAGNOSTIC_CODES.suggestLineRole,
|
|
111530
|
+
`${doing} (${named}${rest}) with no role=`,
|
|
111531
|
+
HEADER,
|
|
111532
|
+
edges.length === 1 ? `Add role=${role} to it, which draws the line ${spec.tone} and names it ${spec.legend} in the legend.` : `Add role=${role} to each, which draws the lines ${spec.tone} and names them ${spec.legend} in the legend.`
|
|
111533
|
+
)
|
|
111534
|
+
];
|
|
111535
|
+
});
|
|
111536
|
+
}
|
|
111537
|
+
var ROLE_DOING, NAMED_ARROWS;
|
|
111538
|
+
var init_suggest_line_roles = __esm({
|
|
111539
|
+
"../../packages/diagrams/src/lint/suggest-line-roles.ts"() {
|
|
111540
|
+
"use strict";
|
|
111541
|
+
init_constants();
|
|
111542
|
+
init_core();
|
|
111543
|
+
init_label_icon();
|
|
111544
|
+
init_general_warnings();
|
|
111545
|
+
ROLE_DOING = {
|
|
111546
|
+
data: { one: "reads or writes stored data", many: "read or write stored data" },
|
|
111547
|
+
async: { one: "sends or receives a message that is not waited for", many: "send or receive messages that are not waited for" },
|
|
111548
|
+
identity: { one: "signs in or carries a credential", many: "sign in or carry credentials" },
|
|
111549
|
+
private: { one: "crosses a private network", many: "cross a private network" }
|
|
111550
|
+
};
|
|
111551
|
+
NAMED_ARROWS = 4;
|
|
111189
111552
|
}
|
|
111190
111553
|
});
|
|
111191
111554
|
|
|
@@ -111226,7 +111589,7 @@ function lintFlow(diagram, measure) {
|
|
|
111226
111589
|
shortenedWarning(shortenedIds3(diagram)),
|
|
111227
111590
|
widthWarning(measure.size, "Use direction=down, shorten labels, or split the diagram.")
|
|
111228
111591
|
]);
|
|
111229
|
-
return [...general, ...overlayWarnings(diagram, measure.overlayCovers), ...suggestGroupTypes(diagram), ...suggestIcons(diagram)];
|
|
111592
|
+
return [...general, ...overlayWarnings(diagram, measure.overlayCovers), ...suggestGroupTypes(diagram), ...suggestIcons(diagram), ...suggestLineRoles(diagram)];
|
|
111230
111593
|
}
|
|
111231
111594
|
var init_lint3 = __esm({
|
|
111232
111595
|
"../../packages/diagrams/src/kinds/flow/lint.ts"() {
|
|
@@ -111240,6 +111603,7 @@ var init_lint3 = __esm({
|
|
|
111240
111603
|
init_overlay_warnings();
|
|
111241
111604
|
init_suggest_group_types();
|
|
111242
111605
|
init_suggest_icons();
|
|
111606
|
+
init_suggest_line_roles();
|
|
111243
111607
|
}
|
|
111244
111608
|
});
|
|
111245
111609
|
|
|
@@ -112835,7 +113199,7 @@ function matches(rule, words2) {
|
|
|
112835
113199
|
return rule.whole.includes(whole2) || rule.last.includes(last) || words2.some((word2) => rule.product.includes(word2));
|
|
112836
113200
|
}
|
|
112837
113201
|
function keywordType(label) {
|
|
112838
|
-
const words2 =
|
|
113202
|
+
const words2 = wordsOf3(label);
|
|
112839
113203
|
if (words2.length === 0 || words2.length > KEYWORD_MAX_WORDS) return null;
|
|
112840
113204
|
const found = new Set(KEYWORD_RULES.filter((rule) => matches(rule, words2)).map((rule) => rule.type));
|
|
112841
113205
|
const [only] = [...found];
|
|
@@ -112847,7 +113211,7 @@ function statusCodeTone(label) {
|
|
|
112847
113211
|
return family === "4" || family === "5" ? "red" : null;
|
|
112848
113212
|
}
|
|
112849
113213
|
function productType(text3) {
|
|
112850
|
-
const words2 =
|
|
113214
|
+
const words2 = wordsOf3(text3);
|
|
112851
113215
|
if (words2.length === 0 || words2.length > KEYWORD_MAX_WORDS) return null;
|
|
112852
113216
|
const found = new Set(KEYWORD_RULES.filter((rule) => words2.some((word2) => rule.product.includes(word2))).map((rule) => rule.type));
|
|
112853
113217
|
const [only] = [...found];
|
|
@@ -112884,7 +113248,7 @@ function inferNodeIcon(node3, type) {
|
|
|
112884
113248
|
if (NOT_PRODUCT_TYPES2.has(type) || FLOW_NODE_TYPE_DEFAULTS[type].shape === "pill") return null;
|
|
112885
113249
|
return brandMarkNamedBy(node3.label) ?? (node3.sub === null ? null : brandMarkNamedBy(node3.sub));
|
|
112886
113250
|
}
|
|
112887
|
-
var
|
|
113251
|
+
var wordsOf3, STATUS_CODE, NOT_PRODUCT_TYPES2;
|
|
112888
113252
|
var init_infer = __esm({
|
|
112889
113253
|
"../../packages/diagrams/src/import/infer.ts"() {
|
|
112890
113254
|
"use strict";
|
|
@@ -112892,7 +113256,7 @@ var init_infer = __esm({
|
|
|
112892
113256
|
init_icons();
|
|
112893
113257
|
init_suggest_icons();
|
|
112894
113258
|
init_mapping();
|
|
112895
|
-
|
|
113259
|
+
wordsOf3 = (label) => label.toLowerCase().split(/[^a-z0-9]+/).filter((word2) => word2 !== "");
|
|
112896
113260
|
STATUS_CODE = /^(?:(?:return|returns|respond|respond with|response|http)\s+)?(?:http\s+)?([2-5])\d\d(?:\s|$)/i;
|
|
112897
113261
|
NOT_PRODUCT_TYPES2 = /* @__PURE__ */ new Set(["decision", "terminal", "step"]);
|
|
112898
113262
|
}
|
|
@@ -116344,7 +116708,7 @@ function summarizeGit(diagram) {
|
|
|
116344
116708
|
const counts = `${countOf(diagram.commits.length, "commit")} on ${countOf(diagram.branches.length, "branch", "branches")}${optionalCount(merges, "merge")}${optionalCount(picks2, "cherry-pick")}${optionalCount(tags, "tag")}`;
|
|
116345
116709
|
return `${title}: ${counts}.${description}`;
|
|
116346
116710
|
}
|
|
116347
|
-
function
|
|
116711
|
+
function nameOf2(commit) {
|
|
116348
116712
|
return commit.message === null ? `commit ${commit.index + 1}` : `"${commit.message}"`;
|
|
116349
116713
|
}
|
|
116350
116714
|
function describeCommit(commit, diagram) {
|
|
@@ -116358,7 +116722,7 @@ function describeCommit(commit, diagram) {
|
|
|
116358
116722
|
return `merge of ${commit.mergedBranch ?? "a branch"} into ${commit.branch}${message2}${nothing2}${kind}${id}${tags}`;
|
|
116359
116723
|
}
|
|
116360
116724
|
if (commit.origin === "cherry-pick") {
|
|
116361
|
-
const of = source === void 0 ? "a commit" : `${source.id ??
|
|
116725
|
+
const of = source === void 0 ? "a commit" : `${source.id ?? nameOf2(source)}${source.message === null ? "" : ` ("${source.message}")`}`;
|
|
116362
116726
|
const own2 = commit.message !== null && commit.message !== source?.message ? `, message "${commit.message}"` : "";
|
|
116363
116727
|
return `cherry-pick of ${of}${own2}${kind}${id}${tags}`;
|
|
116364
116728
|
}
|
|
@@ -116367,7 +116731,7 @@ function describeCommit(commit, diagram) {
|
|
|
116367
116731
|
function describeBranch(branch, diagram) {
|
|
116368
116732
|
const parent = branch.forkedFrom === null ? void 0 : diagram.commits[branch.forkedFrom];
|
|
116369
116733
|
if (parent === void 0 || branch.parentBranch === null) return `${branch.name} is the default branch`;
|
|
116370
|
-
return `${branch.name} was made from ${branch.parentBranch} at ${
|
|
116734
|
+
return `${branch.name} was made from ${branch.parentBranch} at ${nameOf2(parent)}`;
|
|
116371
116735
|
}
|
|
116372
116736
|
function outlineGit(diagram) {
|
|
116373
116737
|
const lines = [summarizeGit(diagram), "Branches, in lane order:"];
|
|
@@ -117196,7 +117560,7 @@ var init_check2 = __esm({
|
|
|
117196
117560
|
});
|
|
117197
117561
|
|
|
117198
117562
|
// ../../packages/diagrams/src/kinds/journey/layout-columns.ts
|
|
117199
|
-
function
|
|
117563
|
+
function wordsOf4(text3, role) {
|
|
117200
117564
|
const widths = (text3 ?? "").split(/\s+/).filter(Boolean).map((word2) => measureRole(word2, role));
|
|
117201
117565
|
return { widths, space: measureRole(" ", role), longest: widths.reduce((most, width) => Math.max(most, width), 0) };
|
|
117202
117566
|
}
|
|
@@ -117236,7 +117600,7 @@ function candidates(needed) {
|
|
|
117236
117600
|
}
|
|
117237
117601
|
function chooseColumn(sections, hasTabs) {
|
|
117238
117602
|
const tasks = sections.flatMap((section) => section.tasks);
|
|
117239
|
-
const words2 = tasks.map((task) => ({ label:
|
|
117603
|
+
const words2 = tasks.map((task) => ({ label: wordsOf4(task.label, "label"), sub: wordsOf4(task.sub, "sub") }));
|
|
117240
117604
|
const longest = words2.reduce((most, item) => Math.max(most, item.label.longest, item.sub.longest), 0);
|
|
117241
117605
|
const widths = candidates(longest + card.paddingX * 2);
|
|
117242
117606
|
const isClean = (column) => {
|
|
@@ -117545,11 +117909,11 @@ function assignTones(chosen) {
|
|
|
117545
117909
|
return given2;
|
|
117546
117910
|
});
|
|
117547
117911
|
}
|
|
117548
|
-
function
|
|
117912
|
+
function wordsOf5(name2) {
|
|
117549
117913
|
return (name2.match(WORD) ?? []).map((word2) => [...word2]);
|
|
117550
117914
|
}
|
|
117551
117915
|
function initialsCandidates(name2) {
|
|
117552
|
-
const words2 =
|
|
117916
|
+
const words2 = wordsOf5(name2);
|
|
117553
117917
|
const first = words2[0] ?? [];
|
|
117554
117918
|
if (first.length === 0) return [[...name2.trim()][0]?.toUpperCase() ?? "?"];
|
|
117555
117919
|
const upper = (chars) => chars.join("").toUpperCase();
|
|
@@ -119183,7 +119547,7 @@ function outlineLayers(diagram) {
|
|
|
119183
119547
|
...diagram.links.map((link2) => `- ${describeLink(link2, labels2)}`)
|
|
119184
119548
|
];
|
|
119185
119549
|
}
|
|
119186
|
-
var STYLE_WORDS,
|
|
119550
|
+
var STYLE_WORDS, nameOf3, listOf;
|
|
119187
119551
|
var init_outline6 = __esm({
|
|
119188
119552
|
"../../packages/diagrams/src/kinds/layers/outline.ts"() {
|
|
119189
119553
|
"use strict";
|
|
@@ -119191,8 +119555,8 @@ var init_outline6 = __esm({
|
|
|
119191
119555
|
init_check3();
|
|
119192
119556
|
init_text3();
|
|
119193
119557
|
STYLE_WORDS = { solid: "", dashed: ", optional or indirect", dotted: ", asynchronous" };
|
|
119194
|
-
|
|
119195
|
-
listOf = (blocks2) => blocks2.length === 0 ? "no blocks." : `${blocks2.map(
|
|
119558
|
+
nameOf3 = (block) => block.sub === null ? oneLine2(block.label) : `${oneLine2(block.label)} (${oneLine2(block.sub)})`;
|
|
119559
|
+
listOf = (blocks2) => blocks2.length === 0 ? "no blocks." : `${blocks2.map(nameOf3).join(", ")}.`;
|
|
119196
119560
|
}
|
|
119197
119561
|
});
|
|
119198
119562
|
|
|
@@ -125664,21 +126028,21 @@ var init_marks2 = __esm({
|
|
|
125664
126028
|
});
|
|
125665
126029
|
|
|
125666
126030
|
// ../../packages/diagrams/src/kinds/sankey/node-content.ts
|
|
125667
|
-
function
|
|
126031
|
+
function nameOf4(node3) {
|
|
125668
126032
|
const name2 = oneLine6(node3.label);
|
|
125669
126033
|
const chars = [...name2];
|
|
125670
126034
|
return chars.length > MAX_NAME_CHARS ? { text: chars.slice(0, MAX_NAME_CHARS).join(""), isClipped: true } : { text: name2, isClipped: false };
|
|
125671
126035
|
}
|
|
125672
126036
|
function wantedWidth(node3, valueText) {
|
|
125673
|
-
const text3 = Math.max(measureRole(
|
|
126037
|
+
const text3 = Math.max(measureRole(nameOf4(node3).text, "label"), valueText === null ? 0 : measureRole(valueText, "sub"));
|
|
125674
126038
|
return Math.ceil(2 * SANKEY_METRICS.padX + (node3.icon === null ? 0 : SANKEY_METRICS.chipSize + SANKEY_METRICS.chipGap) + text3);
|
|
125675
126039
|
}
|
|
125676
126040
|
function floorWidth(node3, valueText) {
|
|
125677
|
-
const longest =
|
|
126041
|
+
const longest = nameOf4(node3).text.split(" ").reduce((most, word2) => Math.max(most, measureRole(word2, "label")), 0);
|
|
125678
126042
|
return Math.ceil(2 * SANKEY_METRICS.padX + (node3.icon === null ? 0 : SANKEY_METRICS.chipSize + SANKEY_METRICS.chipGap) + Math.max(longest, valueText === null ? 0 : measureRole(valueText, "sub")));
|
|
125679
126043
|
}
|
|
125680
126044
|
function fitNode(node3, valueText, width) {
|
|
125681
|
-
const name2 =
|
|
126045
|
+
const name2 = nameOf4(node3);
|
|
125682
126046
|
const hasChip = node3.icon !== null;
|
|
125683
126047
|
const textWidth3 = width - 2 * SANKEY_METRICS.padX - (hasChip ? SANKEY_METRICS.chipSize + SANKEY_METRICS.chipGap : 0);
|
|
125684
126048
|
const fitted = fitText(name2.text, "label", textWidth3, textWidth3, SANKEY_METRICS.maxLabelLines);
|
|
@@ -130824,7 +131188,7 @@ function planState(ir, ctx) {
|
|
|
130824
131188
|
origin: node3.span.line
|
|
130825
131189
|
}));
|
|
130826
131190
|
const kindOf3 = new Map(real.map((node3) => [node3.key, node3.kind]));
|
|
130827
|
-
const
|
|
131191
|
+
const nameOf11 = (key) => {
|
|
130828
131192
|
const marker = ir.nodes.find((node3) => node3.key === key);
|
|
130829
131193
|
return marker !== void 0 && (marker.kind === "start" || marker.kind === "end") ? `the ${marker.kind} marker` : `"${key}"`;
|
|
130830
131194
|
};
|
|
@@ -130847,7 +131211,7 @@ function planState(ir, ctx) {
|
|
|
130847
131211
|
}
|
|
130848
131212
|
const isNested = transition.from !== transition.to && (lineageOf2(transition.to, parentKeys).includes(transition.from) || lineageOf2(transition.from, parentKeys).includes(transition.to));
|
|
130849
131213
|
if (isNested) {
|
|
130850
|
-
reporter.add(DIAGNOSTIC_CODES.mermaidDroppedMeaning, span, `Dropped a transition between ${
|
|
131214
|
+
reporter.add(DIAGNOSTIC_CODES.mermaidDroppedMeaning, span, `Dropped a transition between ${nameOf11(transition.from)} and ${nameOf11(transition.to)}, because one is inside the other. A transition cannot join a state to one inside it.`, "Start the transition from a state inside the composite state, or from its own start marker.", "nested-transition");
|
|
130851
131215
|
continue;
|
|
130852
131216
|
}
|
|
130853
131217
|
const { composite, region } = transition.scope;
|
|
@@ -130912,7 +131276,7 @@ function summarizeState(diagram) {
|
|
|
130912
131276
|
const description = diagram.meta.description === null ? "" : ` ${diagram.meta.description}`;
|
|
130913
131277
|
return `${title}: ${counts}.${description}`;
|
|
130914
131278
|
}
|
|
130915
|
-
function
|
|
131279
|
+
function nameOf5(diagram, node3) {
|
|
130916
131280
|
const holder = node3.parent === null ? void 0 : diagram.states.find((candidate2) => candidate2.id === node3.parent);
|
|
130917
131281
|
const scope = holder === void 0 ? "" : ` of ${holder.label}${node3.region === null ? "" : regionSuffix(diagram, holder.id, node3.region)}`;
|
|
130918
131282
|
if (node3.kind === "start" || node3.kind === "end") return `${KIND_NAMES[node3.kind]}${scope}`;
|
|
@@ -130927,7 +131291,7 @@ function regionSuffix(diagram, parent, index2) {
|
|
|
130927
131291
|
}
|
|
130928
131292
|
function nodeLine2(diagram, node3) {
|
|
130929
131293
|
const detail = node3.description.length === 0 ? "" : ` (${node3.description.join("; ")})`;
|
|
130930
|
-
const name2 =
|
|
131294
|
+
const name2 = nameOf5(diagram, node3);
|
|
130931
131295
|
if (node3.kind === "state") return `${name2}${detail}, state`;
|
|
130932
131296
|
if (node3.kind === "composite") return `${name2}${detail}, composite state`;
|
|
130933
131297
|
if (node3.kind === "choice") return `${name2}, choice`;
|
|
@@ -130938,7 +131302,7 @@ function nodeLine2(diagram, node3) {
|
|
|
130938
131302
|
function transitionLine(diagram, transition) {
|
|
130939
131303
|
const name2 = (id) => {
|
|
130940
131304
|
const node3 = diagram.states.find((candidate2) => candidate2.id === id);
|
|
130941
|
-
return node3 === void 0 ? id :
|
|
131305
|
+
return node3 === void 0 ? id : nameOf5(diagram, node3);
|
|
130942
131306
|
};
|
|
130943
131307
|
const on = transition.event === null ? "" : ` on ${transition.event}`;
|
|
130944
131308
|
const guard = transition.guard === null ? "" : `, if ${transition.guard}`;
|
|
@@ -130970,7 +131334,7 @@ function outlineState(diagram) {
|
|
|
130970
131334
|
lines.push("Notes:");
|
|
130971
131335
|
for (const note of diagram.notes) {
|
|
130972
131336
|
const target = diagram.states.find((node3) => node3.id === note.target);
|
|
130973
|
-
lines.push(`- On ${target === void 0 ? note.target :
|
|
131337
|
+
lines.push(`- On ${target === void 0 ? note.target : nameOf5(diagram, target)}: ${note.text}`);
|
|
130974
131338
|
}
|
|
130975
131339
|
}
|
|
130976
131340
|
return lines;
|
|
@@ -138997,7 +139361,7 @@ api --> email : "Sends email using" tech="SMTP"
|
|
|
138997
139361
|
email --> customer : "Sends emails to"
|
|
138998
139362
|
` },
|
|
138999
139363
|
{ kind: "class", title: "Notification service", source: 'class "Notification service" desc="A notifier queues messages and delivers each one through a channel. Channels are interchangeable, so a new one needs no change to the notifier."\n\nclass Notifier stereotype="service" {\n "-queue: Queue<Message>"\n "+send(m: Message): void"\n "+retry(): int"\n}\n\nclass Message {\n "+id: uuid"\n "+body: String"\n "+priority: Priority"\n}\n\nclass Priority type=enum {\n "LOW"\n "NORMAL"\n "URGENT"\n}\n\nclass Template "Template<T>" type=abstract {\n "+render(data: T): String" abstract\n "+named(n: String): Template" static\n}\n\npackage channels "Channels" {\n class Channel type=interface {\n "+deliver(m: Message): Ack"\n }\n class Email "EmailChannel" {\n "-host: String"\n "+deliver(m: Message): Ack"\n }\n class Sms "SmsChannel" {\n "-gateway: String"\n "+deliver(m: Message): Ack"\n }\n}\n\nNotifier "1" owns "*" Message : "queues"\nNotifier "1" has "1..*" Channel : "delivers through"\nNotifier --> Template : "renders with"\nMessage --> Priority\nEmail implements Channel\nSms implements Channel\n\nnote on Message : "Kept until every channel has confirmed delivery."\n' },
|
|
139000
|
-
{ kind: "flow", title: "Login request", source: 'flow "Login request" desc="A user signs in through an API that checks credentials in a database."\n\nnode user person "User"\nnode api service "Auth API" sub="Validates credentials"\n\ngroup data "Data"
|
|
139364
|
+
{ kind: "flow", title: "Login request", source: 'flow "Login request" desc="A user signs in through an API that checks credentials in a database and keeps the session in a cache."\n\nnode user person "User"\nnode api service "Auth API" sub="Validates credentials"\n\ngroup data "Data" {\n node db database "PostgreSQL" sub="Password hashes"\n node cache cache "Redis" sub="Sessions"\n}\n\nuser -> api : "signs in" role=identity\napi -> db : "looks up user" role=data\ndb --> api : "row"\napi -> cache : "stores session" role=data\n' },
|
|
139001
139365
|
{ kind: "gantt", title: "Product launch plan", source: 'gantt "Product launch plan" start=2026-01-05 unit=week today=2026-02-11 weekends=skip holidays=2026-04-03 desc="A fourteen week plan from research to launch, with design and build running side by side."\n\nsection "Discover" {\n task research "User research" start=2026-01-05 duration=2w status=done\n task brief "Product brief" after=research duration=1w status=done\n}\n\nsection "Design" tone=violet {\n task ux "UX flows" after=brief duration=2w status=done\n task ui "Visual design" after=ux duration=3w status=active\n task ds "Design system" after=brief duration=4w status=active\n}\n\nsection "Build" tone=aqua {\n task api "API and data model" after=brief duration=5w status=active\n task web "Web app" after=ui,api duration=4w status=critical\n task mobile "Mobile app" after=ui,api duration=4w\n milestone beta "Beta ready" after=web\n}\n\nsection "Launch" tone=orange {\n task docs "Help center" after=ui duration=3w\n task qa "Testing and fixes" after=web,mobile duration=2w status=critical\n milestone ga "Public launch" after=qa status=critical\n}\n' },
|
|
139002
139366
|
{ kind: "git", title: "Release and hotfix", source: 'git "Release and hotfix" desc="A feature is merged into develop, develop is released as v1.0, and a hotfix is tagged and picked back."\n\ncommit "Initial commit"\nbranch develop order=2\ncommit "Set up CI"\nbranch "feature/search" from=develop\ncommit "Add search box"\ncommit "Index the docs"\ncheckout develop\nmerge "feature/search" "Add search"\ncheckout main\nmerge develop "Release 1.0" tag="v1.0" type=highlight\nbranch hotfix order=1\ncommit "Fix null check" id=fix\ncheckout main\nmerge hotfix tag="v1.0.1"\ncheckout develop\ncherry-pick fix\ncommit "Revert flaky test" type=reverse\n' },
|
|
139003
139367
|
{ kind: "journey", title: "Checkout experience", source: 'journey "Checkout experience" desc="How a shopper feels from finding a product to holding the parcel, and who is involved at each step."\n\nactor "Customer" tone=blue\nactor "Support agent" tone=violet\nactor "Bank"\nactor "Courier"\n\nsection "Browse" {\n task "Find a product" score=5 actors="Customer"\n task "Compare prices" score=3 actors="Customer, Support agent" sub="Asks about delivery"\n}\n\nsection "Pay" {\n task "Enter card details" score=2 actors="Customer"\n task "Confirm with the bank" score=1 actors="Customer, Bank"\n task "Get a receipt" score=4 actors="Customer"\n}\n\nsection "Deliver" {\n task "Track the parcel" score=4 actors="Customer, Courier"\n task "Receive it" score=5 actors="Customer, Courier"\n}\n' },
|
|
@@ -139055,7 +139419,7 @@ ship -> delivered : "arrived"
|
|
|
139055
139419
|
{ kind: "treemap", title: "Monthly cloud spend", source: 'treemap "Monthly cloud spend" unit="$" better=down desc="Where the monthly cloud bill goes, by service, with the change since last month. A rise in cost is drawn red."\n\ngroup "Compute" icon=lucide:cpu {\n item "EC2" 18400 icon=aws:ec2 delta="8%"\n item "Fargate" 6800 icon=aws:fargate delta="21%"\n item "Lambda" 4200 icon=aws:lambda delta="-12%"\n item "EKS" 3100 icon=aws:eks\n}\n\ngroup "Data" icon=lucide:database {\n item "RDS" 9600 icon=aws:rds delta="4%"\n item "S3" 5200 icon=aws:s3 delta="-3%"\n item "DynamoDB" 3900 icon=aws:dynamodb\n item "OpenSearch" 3400 icon=aws:opensearch\n item "ElastiCache" 2800\n}\n\ngroup "Network" icon=lucide:globe {\n item "Data transfer" 4800 delta="15%"\n item "NAT gateway" 3300 icon=aws:nat-gateway\n item "CloudFront" 2200 icon=aws:cloudfront delta="-6%"\n item "Load balancers" 1900 icon=aws:elb\n}\n\ngroup "Operations" icon=lucide:activity {\n item "CloudWatch" 4600 icon=aws:cloudwatch\n item "Support plan" 3200\n group "Security" icon=lucide:shield {\n item "GuardDuty" 2400 icon=aws:guardduty\n item "WAF" 1900 icon=aws:waf\n }\n}\n' },
|
|
139056
139420
|
{ kind: "xychart", title: "API latency against the SLO", source: 'xychart "API latency against the SLO" desc="Weekly p50 and p95 latency of the checkout API against its 400 ms objective: p95 crossed the line after release 2.3 and came back under it after the cache fix."\n\nx "Week" ["W1" "W2" "W3" "W4" "W5" "W6" "W7" "W8"]\ny "Latency" unit="ms" min=0 max=500\n\nbar "p95" [310 330 345 420 455 440 350 335]\nline "p50" [120 125 128 160 170 165 135 130]\n\nthreshold "SLO 400 ms" 400 tone=red\n\nnote "Release 2.3" at="W4"\nnote "Cache fix" at="W7"\n' }
|
|
139057
139421
|
];
|
|
139058
|
-
ARCHITECTURE_EXAMPLE = { kind: "flow", title: "Web application on a cloud", source: 'flow "Web application on a cloud" provider=azure direction=down desc="Visitors load a single-page app from storage through a content delivery network and sign in through an identity service. The app calls an API on an application plan, which stores uploads, reads a database, and hands slow work to a queue that a background worker drains. A pipeline builds and deploys the API, and a monitoring service collects telemetry."\n\nnode visitors client "Visitors" sub="Browsers"\n\ngroup edge "Edge" type=edge {\n node cdn gateway "Content delivery" icon=azure:cdn\n}\n\ngroup sign-in "Sign-in" type=identity-boundary {\n node idp identity "Identity service" icon=azure:entra-id\n}\n\ngroup files "Storage" type=storage-account {\n node site storage "Web app files" icon=azure:blob-storage stack=simple:react,simple:typescript\n node uploads storage "Uploads" icon=azure:blob-storage\n}\n\ngroup plan "Application plan" type=service-plan {\n node api service "Orders API" icon=azure:app-service stack=simple:nodedotjs\n}\n\ngroup messaging "Messaging" type=messaging {\n node jobs queue "Job queue" icon=azure:service-bus\n}\n\nnode worker function "Background worker" icon=azure:functions stack=simple:nodedotjs\nnode db database "Database" icon=azure:sql-database\n\ngroup delivery "Delivery pipeline" type=ci-cd {\n node repo step "Source code" icon=lucide:git-branch\n node build step "Build pipeline" icon=azure:devops\n}\n\ngroup monitoring "Monitoring" type=observability {\n node telemetry service "Metrics and logs" icon=azure:monitor\n}\n\nvisitors -> cdn : "HTTPS"\nvisitors -> idp : "sign in"\ncdn -> site\ncdn -> api : "API calls"\napi -> uploads : "store files"\napi -> jobs : "enqueue"\njobs ..> worker : "event"\nworker -> db : "writes"\napi -> db : "reads"\nrepo -> build\nbuild ..> api : "deploys image"\napi ..> telemetry : "telemetry"\n' };
|
|
139422
|
+
ARCHITECTURE_EXAMPLE = { kind: "flow", title: "Web application on a cloud", source: 'flow "Web application on a cloud" provider=azure direction=down desc="Visitors load a single-page app from storage through a content delivery network and sign in through an identity service. The app calls an API on an application plan, which stores uploads, reads a database, and hands slow work to a queue that a background worker drains. A pipeline builds and deploys the API, and a monitoring service collects telemetry."\n\nnode visitors client "Visitors" sub="Browsers"\n\ngroup edge "Edge" type=edge {\n node cdn gateway "Content delivery" icon=azure:cdn\n}\n\ngroup sign-in "Sign-in" type=identity-boundary {\n node idp identity "Identity service" icon=azure:entra-id\n}\n\ngroup files "Storage" type=storage-account {\n node site storage "Web app files" icon=azure:blob-storage stack=simple:react,simple:typescript\n node uploads storage "Uploads" icon=azure:blob-storage\n}\n\ngroup plan "Application plan" type=service-plan {\n node api service "Orders API" icon=azure:app-service stack=simple:nodedotjs\n}\n\ngroup messaging "Messaging" type=messaging {\n node jobs queue "Job queue" icon=azure:service-bus\n}\n\nnode worker function "Background worker" icon=azure:functions stack=simple:nodedotjs\nnode db database "Database" icon=azure:sql-database\n\ngroup delivery "Delivery pipeline" type=ci-cd {\n node repo step "Source code" icon=lucide:git-branch\n node build step "Build pipeline" icon=azure:devops\n}\n\ngroup monitoring "Monitoring" type=observability {\n node telemetry service "Metrics and logs" icon=azure:monitor\n}\n\nvisitors -> cdn : "HTTPS"\nvisitors -> idp : "sign in" role=identity\ncdn -> site\ncdn -> api : "API calls"\napi -> uploads : "store files" role=data\napi -> jobs : "enqueue" role=async\njobs ..> worker : "event"\nworker -> db : "writes" role=data\napi -> db : "reads" role=data\nrepo -> build\nbuild ..> api : "deploys image"\napi ..> telemetry : "telemetry"\n' };
|
|
139059
139423
|
}
|
|
139060
139424
|
});
|
|
139061
139425
|
|
|
@@ -139107,6 +139471,8 @@ function buildVocabulary() {
|
|
|
139107
139471
|
},
|
|
139108
139472
|
lineOptions: LINE_OPTION_SPECS.map((spec) => ({ ...spec })),
|
|
139109
139473
|
labelIcons: Object.entries(LABEL_ICON_DEFAULTS).map(([label, icon]) => ({ label, icon })),
|
|
139474
|
+
verbIcons: Object.entries(LABEL_VERB_PHRASES).map(([verb, words2]) => ({ icon: EDGE_STYLES[verb].icon, words: [...words2 ?? []] })),
|
|
139475
|
+
style: [...STYLE_STEPS],
|
|
139110
139476
|
autoIcons: { ...ICON_MODE_SPEC },
|
|
139111
139477
|
roleIcons: roleIconTable(),
|
|
139112
139478
|
statusIcons: Object.entries(STATUS_ICON_SPECS).map(([name2, spec]) => ({ ref: `status:${name2}`, tone: spec.tone, meaning: spec.meaning })),
|
|
@@ -139215,6 +139581,8 @@ var init_build_vocabulary = __esm({
|
|
|
139215
139581
|
arrows: ["overview", "flow", "sequence"],
|
|
139216
139582
|
lineOptions: ["overview", "flow", "sequence"],
|
|
139217
139583
|
labelIcons: ["overview", "flow"],
|
|
139584
|
+
verbIcons: ["flow"],
|
|
139585
|
+
style: ["overview", "flow"],
|
|
139218
139586
|
autoIcons: AUTO_ICON_KINDS,
|
|
139219
139587
|
roleIcons: ["flow", "c4", "layers", "mindmap", "swimlane"],
|
|
139220
139588
|
blockTypes: ["overview", "sequence"],
|
|
@@ -139835,7 +140203,7 @@ function descendantsOf(scan, index2) {
|
|
|
139835
140203
|
});
|
|
139836
140204
|
return inside;
|
|
139837
140205
|
}
|
|
139838
|
-
function
|
|
140206
|
+
function nameOf6(element) {
|
|
139839
140207
|
if (element.role === "edge") return `${element.from ?? ""} ${element.arrow ?? ""} ${element.to ?? ""}`;
|
|
139840
140208
|
return element.id ?? (element.label === null ? element.rest : `"${element.label}"`);
|
|
139841
140209
|
}
|
|
@@ -139859,7 +140227,7 @@ function subjectOf(element) {
|
|
|
139859
140227
|
function renamedName(element, rename2) {
|
|
139860
140228
|
if (element.role === "edge") return `${rename2(element.from ?? "")} -> ${rename2(element.to ?? "")}`;
|
|
139861
140229
|
if (element.role === "header") return "header";
|
|
139862
|
-
return element.id === null ?
|
|
140230
|
+
return element.id === null ? nameOf6(element) : rename2(element.id);
|
|
139863
140231
|
}
|
|
139864
140232
|
function entriesOf3(source, rename2) {
|
|
139865
140233
|
const { elements } = scanSource(source);
|
|
@@ -178587,6 +178955,8 @@ var init_vocabulary18 = __esm({
|
|
|
178587
178955
|
group: GroupSchema.describe("How a flow group looks and what it accepts; its corner tab shows its icon and name."),
|
|
178588
178956
|
lineOptions: external_exports.array(LineOptionSchema).describe("Options that animate a line (animate=on makes dashes travel toward the arrowhead) or number the steps of a flow or sequence (numbered=on, start=, and step= on a line). All are off by default."),
|
|
178589
178957
|
labelIcons: external_exports.array(LabelIconSchema).describe("Edge labels that get a tick or cross automatically; icon=none on the edge removes it."),
|
|
178958
|
+
verbIcons: external_exports.array(external_exports.object({ icon: external_exports.string().describe("The icon drawn in the label."), words: external_exports.array(external_exports.string()).describe('Phrases that draw it: the whole label, or its first words followed by what is acted on ("reads orders").') })).describe("The icons a flow edge label draws when it names a relationship with a verb. icon= on the edge wins, icon=none removes it, and icons=off on the header turns them all off."),
|
|
178959
|
+
style: external_exports.array(external_exports.string()).describe("How to make a flow diagram look finished: verbs on arrows, role= on lines that mean something, typed groups, product names."),
|
|
178590
178960
|
autoIcons: AutoIconsSchema.describe("Items with no icon= get the icon their label names for certain (a brand, a cloud product, a common role). icon=none keeps one item plain; icons=off on the header keeps them all plain."),
|
|
178591
178961
|
roleIcons: external_exports.array(external_exports.object({ icon: external_exports.string().describe("The icon drawn."), words: external_exports.array(external_exports.string()).describe("Whole words of a label of three words or fewer that draw it.") })).describe("The plain icons for common roles, drawn on flow and sequence service and external items, C4 elements, layers blocks, mind map topics, and swimlane lanes. The last role word of the label wins."),
|
|
178592
178962
|
statusIcons: external_exports.array(StatusIconSchema).describe("Colored status and outcome icons: a green check, a red X, and so on."),
|
|
@@ -179206,7 +179576,7 @@ function finding(level2, code, message2, at3, hint2) {
|
|
|
179206
179576
|
function appliesTo(rule, kind) {
|
|
179207
179577
|
return rule.kinds === void 0 || rule.kinds.includes(kind);
|
|
179208
179578
|
}
|
|
179209
|
-
function
|
|
179579
|
+
function nameOf7(subject) {
|
|
179210
179580
|
return subject.id === null || subject.id === subject.label ? `"${subject.label}"` : `${subject.id} ("${subject.label}")`;
|
|
179211
179581
|
}
|
|
179212
179582
|
function iconAccepted(icon, choices) {
|
|
@@ -179233,7 +179603,7 @@ function iconFindings(rule, subjects, level2, places) {
|
|
|
179233
179603
|
const drawn = subject.icon === null ? "draws no icon" : `draws ${subject.icon}`;
|
|
179234
179604
|
const [first] = rule.use;
|
|
179235
179605
|
const choices = rule.use.length === 1 ? `icon=${first ?? ""}` : `icon= with one of ${rule.use.join(", ")}`;
|
|
179236
|
-
return [finding(rule.level ?? level2, DIAGNOSTIC_CODES.ruleIcon, `${
|
|
179606
|
+
return [finding(rule.level ?? level2, DIAGNOSTIC_CODES.ruleIcon, `${nameOf7(subject)} matches /${rule.label}/ and ${drawn}`, places.of(subject), rule.hint ?? `Give it ${choices}.`)];
|
|
179237
179607
|
});
|
|
179238
179608
|
}
|
|
179239
179609
|
function toneFindings(rule, subjects, level2, places) {
|
|
@@ -179243,7 +179613,7 @@ function toneFindings(rule, subjects, level2, places) {
|
|
|
179243
179613
|
if (!broken) return [];
|
|
179244
179614
|
const of = rule.types === void 0 ? "a node" : `a ${subject.type}`;
|
|
179245
179615
|
const fix = rule.allow !== void 0 ? `Use tone=${rule.allow.join(" or tone=")}.` : `Use a tone other than ${(rule.forbid ?? []).join(", ")}.`;
|
|
179246
|
-
return [finding(rule.level ?? level2, DIAGNOSTIC_CODES.ruleTone, `${
|
|
179616
|
+
return [finding(rule.level ?? level2, DIAGNOSTIC_CODES.ruleTone, `${nameOf7(subject)} is ${subject.tone}, a tone the team does not use for ${of}`, places.of(subject), rule.hint ?? fix)];
|
|
179247
179617
|
});
|
|
179248
179618
|
}
|
|
179249
179619
|
function diagramFindings(diagram, rules, count3, level2, places) {
|
|
@@ -179536,9 +179906,9 @@ users -> ingress : "HTTPS"
|
|
|
179536
179906
|
ingress -> web
|
|
179537
179907
|
ingress -> api
|
|
179538
179908
|
ingress -> admin
|
|
179539
|
-
api -> config : "reads"
|
|
179909
|
+
api -> config : "reads" icon=lucide:eye
|
|
179540
179910
|
web ..> monitor : "metrics"
|
|
179541
|
-
api -> secrets : "reads"`;
|
|
179911
|
+
api -> secrets : "reads secrets" role=identity`;
|
|
179542
179912
|
NEUTRAL2 = `flow "{{title}}" direction=down desc="{{description}}"
|
|
179543
179913
|
|
|
179544
179914
|
group delivery "{{pipeline}}" type=ci-cd {
|
|
@@ -179844,8 +180214,8 @@ bus ..> processor : "all events"
|
|
|
179844
180214
|
bus ..> notifier : "alerts"
|
|
179845
180215
|
bus ..> dlq : "after retries"
|
|
179846
180216
|
archiver -> archive : "archive"
|
|
179847
|
-
processor -> db : "write"
|
|
179848
|
-
notifier ..> mail : "send"`;
|
|
180217
|
+
processor -> db : "write" role=data
|
|
180218
|
+
notifier ..> mail : "send" role=async`;
|
|
179849
180219
|
NEUTRAL5 = `flow "{{title}}" direction=down desc="{{description}}"
|
|
179850
180220
|
|
|
179851
180221
|
group producers "{{producers}}" type=app-tier {
|
|
@@ -180073,7 +180443,7 @@ var init_microservices_gateway = __esm({
|
|
|
180073
180443
|
{ id: "billing-database", default: "Billing database", meaning: "The database that only the billing service reads and writes." }
|
|
180074
180444
|
];
|
|
180075
180445
|
EDGES6 = `clients -> gateway : "HTTPS"
|
|
180076
|
-
gateway -> idp : "verify token"
|
|
180446
|
+
gateway -> idp : "verify token" role=identity
|
|
180077
180447
|
gateway -> catalog : "{{catalog-path}}"
|
|
180078
180448
|
gateway -> booking : "{{booking-path}}"
|
|
180079
180449
|
catalog -> catalog-db
|
|
@@ -180223,12 +180593,12 @@ var init_queue_worker = __esm({
|
|
|
180223
180593
|
{ id: "alarm", default: "Queue depth alarm", meaning: "The alarm that fires when too many jobs wait in the queue." }
|
|
180224
180594
|
];
|
|
180225
180595
|
EDGES7 = `client -> api : "{{submit}}"
|
|
180226
|
-
api ..> queue : "enqueue job"
|
|
180596
|
+
api ..> queue : "enqueue job" role=async
|
|
180227
180597
|
queue ..> w1
|
|
180228
180598
|
queue ..> w2
|
|
180229
180599
|
queue ..> w3
|
|
180230
180600
|
queue ..> alarm
|
|
180231
|
-
w2 -> db : "write result"
|
|
180601
|
+
w2 -> db : "write result" role=data
|
|
180232
180602
|
w3 ..> dlq : "after {{retries}} tries"`;
|
|
180233
180603
|
OVERLAY = 'overlay pool "{{pool}}" type=scale-group members=w1,w2,w3';
|
|
180234
180604
|
NEUTRAL9 = `flow "{{title}}" direction=down desc="{{description}}"
|
|
@@ -180325,9 +180695,9 @@ var init_serverless_api = __esm({
|
|
|
180325
180695
|
gateway -> create : "POST {{path}}"
|
|
180326
180696
|
gateway -> list : "GET {{path}}"
|
|
180327
180697
|
gateway -> get : "GET {{path}}/id"
|
|
180328
|
-
gateway -> auth : "verify token"
|
|
180329
|
-
create -> bucket : "upload"
|
|
180330
|
-
create -> db : "write"
|
|
180698
|
+
gateway -> auth : "verify token" role=identity
|
|
180699
|
+
create -> bucket : "upload" role=data
|
|
180700
|
+
create -> db : "write" role=data
|
|
180331
180701
|
list -> db
|
|
180332
180702
|
get -> db
|
|
180333
180703
|
get ..> monitor : "logs and metrics"`;
|
|
@@ -180521,7 +180891,7 @@ dns -> cdn
|
|
|
180521
180891
|
cert -> cdn
|
|
180522
180892
|
publish ..> cdn
|
|
180523
180893
|
cdn -> bucket : "fetch files"
|
|
180524
|
-
publish -> bucket : "upload"`;
|
|
180894
|
+
publish -> bucket : "upload" role=data`;
|
|
180525
180895
|
NEUTRAL12 = `flow "{{title}}" direction=down desc="{{description}}"
|
|
180526
180896
|
|
|
180527
180897
|
group pipeline "{{pipeline}}" type=ci-cd {
|
|
@@ -180905,14 +181275,14 @@ var init_web_app_on_cloud = __esm({
|
|
|
180905
181275
|
{ id: "telemetry", default: "Metrics and logs", meaning: "The service that collects what the API reports." }
|
|
180906
181276
|
];
|
|
180907
181277
|
EDGES11 = `visitors -> cdn : "HTTPS"
|
|
180908
|
-
visitors -> idp : "sign in"
|
|
181278
|
+
visitors -> idp : "sign in" role=identity
|
|
180909
181279
|
cdn -> site
|
|
180910
181280
|
cdn -> api : "API calls"
|
|
180911
|
-
api -> uploads : "store files"
|
|
180912
|
-
api -> jobs : "enqueue"
|
|
181281
|
+
api -> uploads : "store files" role=data
|
|
181282
|
+
api -> jobs : "enqueue" role=async
|
|
180913
181283
|
jobs ..> worker : "event"
|
|
180914
|
-
worker -> db : "writes"
|
|
180915
|
-
api -> db : "reads"
|
|
181284
|
+
worker -> db : "writes" role=data
|
|
181285
|
+
api -> db : "reads" role=data
|
|
180916
181286
|
repo -> build
|
|
180917
181287
|
build ..> api : "deploys image"
|
|
180918
181288
|
api ..> telemetry : "telemetry"`;
|
|
@@ -181196,6 +181566,14 @@ var init_direction = __esm({
|
|
|
181196
181566
|
}
|
|
181197
181567
|
});
|
|
181198
181568
|
|
|
181569
|
+
// ../../packages/diagrams/src/importers/shared/edge-style.ts
|
|
181570
|
+
var init_edge_style = __esm({
|
|
181571
|
+
"../../packages/diagrams/src/importers/shared/edge-style.ts"() {
|
|
181572
|
+
"use strict";
|
|
181573
|
+
init_constants();
|
|
181574
|
+
}
|
|
181575
|
+
});
|
|
181576
|
+
|
|
181199
181577
|
// ../../packages/diagrams/src/importers/shared/icons.ts
|
|
181200
181578
|
function known2(ref) {
|
|
181201
181579
|
return ref !== null && isKnownIcon(ref) ? ref : null;
|
|
@@ -181688,7 +182066,7 @@ function writeOneFlow(draft, report3) {
|
|
|
181688
182066
|
const children = (parent) => groups.filter((group2) => parentOf4(group2) === parent);
|
|
181689
182067
|
const writeGroup = (group2, depth) => {
|
|
181690
182068
|
lines.gap();
|
|
181691
|
-
lines.add(`group ${ids.idFor(`group:${group2.key}`)} ${quote(group2.label)}${options2({ type: group2.type ?? namedType(group2.label), icon: known2(group2.icon ?? null), sub: group2.sub ?? null, tone: group2.tone ?? null })} {`, depth);
|
|
182069
|
+
lines.add(`group ${ids.idFor(`group:${group2.key}`)} ${quote(group2.label)}${options2({ type: group2.type ?? namedType(group2.label) ?? group2.otherwise ?? null, icon: known2(group2.icon ?? null), sub: group2.sub ?? null, tone: group2.tone ?? null })} {`, depth);
|
|
181692
182070
|
for (const node3 of kept2) if ((node3.group ?? null) === group2.key) nodeLine4(node3, depth + 1);
|
|
181693
182071
|
for (const child of children(group2.key)) writeGroup(child, depth + 1);
|
|
181694
182072
|
lines.add("}", depth);
|
|
@@ -181698,16 +182076,24 @@ function writeOneFlow(draft, report3) {
|
|
|
181698
182076
|
for (const node3 of kept2) if (node3.group === void 0 || node3.group === null || !groupKeys.has(node3.group)) nodeLine4(node3, 0);
|
|
181699
182077
|
for (const group2 of children(null)) writeGroup(group2, 0);
|
|
181700
182078
|
const written3 = /* @__PURE__ */ new Set();
|
|
181701
|
-
|
|
181702
|
-
lines.gap();
|
|
182079
|
+
const drawn = [];
|
|
181703
182080
|
for (const edge of draft.edges) {
|
|
181704
182081
|
const pair2 = `${edge.from}\0${edge.to}`;
|
|
181705
182082
|
if (edge.from === edge.to || !keptKeys.has(edge.from) || !keptKeys.has(edge.to) || written3.has(pair2)) continue;
|
|
181706
182083
|
written3.add(pair2);
|
|
181707
|
-
|
|
181708
|
-
|
|
181709
|
-
|
|
182084
|
+
drawn.push(edge);
|
|
182085
|
+
}
|
|
182086
|
+
const roleOf3 = (edge) => edge.verb === void 0 || edge.verb === null ? null : EDGE_STYLES[edge.verb].role;
|
|
182087
|
+
const roles = new Set(drawn.map(roleOf3));
|
|
182088
|
+
const colour = roles.size > 1;
|
|
182089
|
+
lines.gap();
|
|
182090
|
+
for (const edge of drawn) {
|
|
182091
|
+
const hasLabel = edge.label !== void 0 && edge.label !== null && edge.label !== "";
|
|
182092
|
+
const label = hasLabel ? ` : ${quote(edge.label ?? "")}` : "";
|
|
182093
|
+
const style = edge.verb === void 0 || edge.verb === null ? null : EDGE_STYLES[edge.verb];
|
|
182094
|
+
lines.add(`${ids.idFor(`node:${edge.from}`)} ${edge.arrow ?? "->"} ${ids.idFor(`node:${edge.to}`)}${label}${options2({ icon: hasLabel ? known2(style?.icon ?? null) : null, role: colour ? style?.role ?? null : null })}`);
|
|
181710
182095
|
}
|
|
182096
|
+
const links = drawn.length;
|
|
181711
182097
|
const coverage = draft.coverage ?? { noun: draft.noun, total: draft.nodes.length, drawn: kept2.length, summarised: 0 };
|
|
181712
182098
|
const named = { ...ids.mapped("group:"), ...ids.mapped("node:") };
|
|
181713
182099
|
return { kind: "flow", source: lines.toString(), stats: { items: kept2.length, links, groups: groups.length, dropped: left.length }, advice: draft.advice ?? null, coverage, ids: named };
|
|
@@ -181719,6 +182105,7 @@ var init_flow2 = __esm({
|
|
|
181719
182105
|
init_core();
|
|
181720
182106
|
init_lint21();
|
|
181721
182107
|
init_suggest_icons();
|
|
182108
|
+
init_edge_style();
|
|
181722
182109
|
init_icons3();
|
|
181723
182110
|
init_reporter2();
|
|
181724
182111
|
init_split_flow();
|
|
@@ -182090,6 +182477,7 @@ var init_shared2 = __esm({
|
|
|
182090
182477
|
"../../packages/diagrams/src/importers/shared/index.ts"() {
|
|
182091
182478
|
"use strict";
|
|
182092
182479
|
init_direction();
|
|
182480
|
+
init_edge_style();
|
|
182093
182481
|
init_flow2();
|
|
182094
182482
|
init_split_flow();
|
|
182095
182483
|
init_icons3();
|
|
@@ -182677,7 +183065,7 @@ function drawCharts(files, context, index2) {
|
|
|
182677
183065
|
const edges = [];
|
|
182678
183066
|
const repositories = new Set(charts.flatMap((chart) => chart.dependencies.map((dependency) => dependency.repository)).filter((repository) => repository !== null && repository !== "" && !repository.startsWith("file://")));
|
|
182679
183067
|
const framed = repositories.size > 1;
|
|
182680
|
-
const groups = framed ? [...repositories].sort().map((repository) => ({ key: `repository:${repository}`, label: repositoryLabel(repository), sub: "Chart repository", icon: "simple:helm", idHint: repositoryLabel(repository).split("/").pop() ?? "repository" })) : [];
|
|
183068
|
+
const groups = framed ? [...repositories].sort().map((repository) => ({ key: `repository:${repository}`, label: repositoryLabel(repository), sub: "Chart repository", type: "external-systems", icon: "simple:helm", idHint: repositoryLabel(repository).split("/").pop() ?? "repository" })) : [];
|
|
182681
183069
|
for (const chart of charts) {
|
|
182682
183070
|
const look = imageLook(chart.name);
|
|
182683
183071
|
nodes.push({ key: chartKey(chart), type: look?.type ?? "service", label: chart.name, sub: cleanText([[chart.library ? "Library chart" : "Chart", chart.version].filter((part) => part !== null).join(" "), chart.appVersion === null ? null : `app ${chart.appVersion}`].filter((part) => part !== null).join(", ")), icon: look?.icon ?? "simple:helm", idHint: chart.name });
|
|
@@ -182695,7 +183083,7 @@ function drawCharts(files, context, index2) {
|
|
|
182695
183083
|
nodes.push({ key, type: look?.type ?? "service", label: shown, sub: cleanText([shown === dependency.name ? "Chart" : `Chart ${dependency.name}`, off ? "off in values" : dependency.condition !== null && setting !== "true" ? "optional" : null].filter((part) => part !== null).join(", ")), icon: look?.icon ?? iconForName(dependency.name, look?.type ?? "service") ?? "simple:helm", group: repository, idHint: shown });
|
|
182696
183084
|
}
|
|
182697
183085
|
const version2 = chart.locked.get(dependency.name) ?? dependency.version;
|
|
182698
|
-
edges.push({ from: chartKey(chart), to: key, label: version2, ...off ? { arrow: "-->" } : {} });
|
|
183086
|
+
edges.push({ from: chartKey(chart), to: key, label: version2, verb: "depends-on", ...off ? { arrow: "-->" } : {} });
|
|
182699
183087
|
}
|
|
182700
183088
|
}
|
|
182701
183089
|
const root = charts[0];
|
|
@@ -182911,7 +183299,7 @@ function edgesOf(drawn, folded, context) {
|
|
|
182911
183299
|
const from = keyOf(manifest.kind, manifest.namespace, manifest.name);
|
|
182912
183300
|
for (const route of manifest.routes) {
|
|
182913
183301
|
const service = keyOf("Service", manifest.namespace, route.service);
|
|
182914
|
-
if (has("Service", manifest.namespace, route.service)) edges.push({ from, to: folded.get(service) ?? service, label: route.label });
|
|
183302
|
+
if (has("Service", manifest.namespace, route.service)) edges.push({ from, to: folded.get(service) ?? service, label: route.label, verb: "routes" });
|
|
182915
183303
|
else unresolved(manifest, `Service ${route.service}`);
|
|
182916
183304
|
}
|
|
182917
183305
|
if (manifest.kind === "Service" && !folded.has(from)) {
|
|
@@ -182929,7 +183317,7 @@ function edgesOf(drawn, folded, context) {
|
|
|
182929
183317
|
}
|
|
182930
183318
|
}
|
|
182931
183319
|
for (const use of manifest.uses) {
|
|
182932
|
-
if (has(use.kind, manifest.namespace, use.name)) edges.push({ from, to: keyOf(use.kind, manifest.namespace, use.name), arrow: use.kind === "PersistentVolumeClaim" ? "->" : "-->", label: use.kind === "PersistentVolumeClaim" ? "mounts" : "reads" });
|
|
183320
|
+
if (has(use.kind, manifest.namespace, use.name)) edges.push({ from, to: keyOf(use.kind, manifest.namespace, use.name), arrow: use.kind === "PersistentVolumeClaim" ? "->" : "-->", label: use.kind === "PersistentVolumeClaim" ? "mounts" : "reads", verb: use.kind === "PersistentVolumeClaim" ? "mounts" : use.kind === "Secret" ? "secret" : "reads-settings" });
|
|
182933
183321
|
else unresolved(manifest, `${use.kind} ${use.name}`);
|
|
182934
183322
|
}
|
|
182935
183323
|
}
|
|
@@ -182971,13 +183359,13 @@ function drawManifests(documents, context, framing) {
|
|
|
182971
183359
|
const ordered = [...drawn].sort((a, b) => (LOOKS[a.kind]?.rank ?? 2) - (LOOKS[b.kind]?.rank ?? 2));
|
|
182972
183360
|
const namespaces = [...new Set(ordered.map((manifest) => manifest.namespace))];
|
|
182973
183361
|
const grouped = namespaces.length > 1;
|
|
182974
|
-
const groups = grouped ? namespaces.map((namespace) => ({ key: `ns:${namespace}`, label: namespace, type: namespaceType(namespace), sub: "Namespace", idHint: `ns_${namespace}` })) : [];
|
|
183362
|
+
const groups = grouped ? namespaces.map((namespace) => ({ key: `ns:${namespace}`, label: namespace, type: namespaceType(namespace), otherwise: "resource-group", tone: namespaceType(namespace) === null ? "violet" : null, sub: "Namespace", idHint: `ns_${namespace}` })) : [];
|
|
182975
183363
|
const framed = /* @__PURE__ */ new Map();
|
|
182976
183364
|
for (const manifest of framing === null ? [] : ordered) {
|
|
182977
183365
|
let parent = grouped ? `ns:${manifest.namespace}` : null;
|
|
182978
183366
|
for (const frame of framing?.framesOf(manifest) ?? []) {
|
|
182979
183367
|
const key = grouped ? `${manifest.namespace}/${frame.key}` : frame.key;
|
|
182980
|
-
if (!groups.some((group2) => group2.key === key)) groups.push({ key, label: frame.label, sub: frame.sub, icon: frame.icon, parent, idHint: frame.idHint });
|
|
183368
|
+
if (!groups.some((group2) => group2.key === key)) groups.push({ key, label: frame.label, sub: frame.sub, icon: frame.icon, otherwise: frame.type, tone: frame.tone ?? null, parent, idHint: frame.idHint });
|
|
182981
183369
|
parent = key;
|
|
182982
183370
|
}
|
|
182983
183371
|
if (parent !== null) framed.set(manifest, parent);
|
|
@@ -183135,18 +183523,18 @@ function drawFolder(files, context, index2) {
|
|
|
183135
183523
|
for (const entry2 of ordered) {
|
|
183136
183524
|
const role = roleOf3(entry2);
|
|
183137
183525
|
const frame = `frame:${entry2.folder}`;
|
|
183138
|
-
groups.push({ key: frame, label: entry2.folder.slice(common.length) || baseName2(entry2.folder) || "kustomization", sub: role, icon: "lucide:layers", idHint: entry2.folder.slice(common.length) || baseName2(entry2.folder) || "root" });
|
|
183526
|
+
groups.push({ key: frame, label: entry2.folder.slice(common.length) || baseName2(entry2.folder) || "kustomization", sub: role, ...role === "Overlay" ? { type: "environment" } : { otherwise: "resource-group" }, icon: "lucide:layers", idHint: entry2.folder.slice(common.length) || baseName2(entry2.folder) || "root" });
|
|
183139
183527
|
nodes.push({ key: own2(entry2), type: "service", label: baseName2(entry2.folder) || "kustomization", sub: cleanText(entry2.details.length === 0 ? "kustomization.yaml" : entry2.details.slice(0, 4).join(", ")), icon: "lucide:layers", group: frame, idHint: `${baseName2(entry2.folder) || "kustomization"}_kustomization` });
|
|
183140
183528
|
for (const resource of entry2.resources) {
|
|
183141
183529
|
if (isRemote(resource)) {
|
|
183142
183530
|
nodes.push({ key: `remote:${resource}`, type: "service", label: cleanText(resource.replace(/^https?:\/\//, "").replace(/\?.*$/, "").split("/").slice(-2).join("/")), sub: "Remote resource", icon: "lucide:globe", group: frame, idHint: "remote" });
|
|
183143
|
-
edges.push({ from: own2(entry2), to: `remote:${resource}`, label: "builds on" });
|
|
183531
|
+
edges.push({ from: own2(entry2), to: `remote:${resource}`, label: "builds on", verb: "builds-on" });
|
|
183144
183532
|
continue;
|
|
183145
183533
|
}
|
|
183146
183534
|
const path = resolvePath(entry2.folder, resource);
|
|
183147
183535
|
const inner = path === null ? void 0 : byFolder.get(path);
|
|
183148
183536
|
if (inner !== void 0) {
|
|
183149
|
-
edges.push({ from: own2(entry2), to: own2(inner), label: "builds on" });
|
|
183537
|
+
edges.push({ from: own2(entry2), to: own2(inner), label: "builds on", verb: "builds-on" });
|
|
183150
183538
|
continue;
|
|
183151
183539
|
}
|
|
183152
183540
|
const found = path === null ? void 0 : objects.get(path);
|
|
@@ -183160,7 +183548,7 @@ function drawFolder(files, context, index2) {
|
|
|
183160
183548
|
}
|
|
183161
183549
|
for (const component of entry2.components) {
|
|
183162
183550
|
const inner = byFolder.get(resolvePath(entry2.folder, component) ?? "\0");
|
|
183163
|
-
if (inner !== void 0) edges.push({ from: own2(entry2), to: own2(inner), label: "includes" });
|
|
183551
|
+
if (inner !== void 0) edges.push({ from: own2(entry2), to: own2(inner), label: "includes", verb: "includes" });
|
|
183164
183552
|
else missing.push(`${entry2.folder === "" ? "" : `${entry2.folder}/`}${component}`);
|
|
183165
183553
|
}
|
|
183166
183554
|
for (const generator of entry2.generators) {
|
|
@@ -183175,16 +183563,16 @@ function drawFolder(files, context, index2) {
|
|
|
183175
183563
|
const key = `patch:${entry2.folder}/${patch.path ?? `${kind ?? "any"}/${name2 ?? "any"}`}`;
|
|
183176
183564
|
nodes.push({ key, type: "service", label: patch.path === null ? `${kind ?? "object"} ${name2 ?? ""}`.trim() : baseName2(patch.path), sub: cleanText(`Patch${kind === null ? "" : ` of ${kind}${name2 === null ? "" : ` ${name2}`}`}`), icon: "lucide:file-code", group: frame, idHint: `${baseName2(patch.path ?? "patch").replace(/\.ya?ml$/, "")}_patch` });
|
|
183177
183565
|
const target = kind === null && name2 === null ? null : fileOf2(entry2, kind, name2) ?? [...objects].find(([, inside]) => inside.some((object2) => (kind === null || object2.kind === kind) && (name2 === null || object2.name === name2)))?.[0] ?? null;
|
|
183178
|
-
if (target !== null) edges.push({ from: key, to: `file:${target}`, label: "patches" });
|
|
183566
|
+
if (target !== null) edges.push({ from: key, to: `file:${target}`, label: "patches", verb: "patches" });
|
|
183179
183567
|
}
|
|
183180
183568
|
}
|
|
183181
183569
|
const drawnFiles = [...objects].filter(([path]) => nodes.some((node3) => node3.key === `file:${path}`));
|
|
183182
183570
|
for (const [path, manifests] of drawnFiles) {
|
|
183183
183571
|
for (const manifest of manifests) {
|
|
183184
183572
|
for (const use of manifest.uses) {
|
|
183185
|
-
for (const node3 of nodes) if (node3.key.startsWith("generator:") && node3.key.endsWith(`/${use.kind}/${use.name}`)) edges.push({ from: `file:${path}`, to: node3.key, arrow: "-->", label: "reads" });
|
|
183573
|
+
for (const node3 of nodes) if (node3.key.startsWith("generator:") && node3.key.endsWith(`/${use.kind}/${use.name}`)) edges.push({ from: `file:${path}`, to: node3.key, arrow: "-->", label: "reads", verb: use.kind === "Secret" ? "secret" : "reads-settings" });
|
|
183186
183574
|
const holder = drawnFiles.find(([, others]) => others.some((other) => other.kind === use.kind && other.name === use.name));
|
|
183187
|
-
if (holder !== void 0 && holder[0] !== path) edges.push({ from: `file:${path}`, to: `file:${holder[0]}`, arrow: "-->", label: use.kind === "PersistentVolumeClaim" ? "mounts" : "reads" });
|
|
183575
|
+
if (holder !== void 0 && holder[0] !== path) edges.push({ from: `file:${path}`, to: `file:${holder[0]}`, arrow: "-->", label: use.kind === "PersistentVolumeClaim" ? "mounts" : "reads", verb: use.kind === "PersistentVolumeClaim" ? "mounts" : use.kind === "Secret" ? "secret" : "reads-settings" });
|
|
183188
183576
|
}
|
|
183189
183577
|
for (const [other, inside] of drawnFiles) {
|
|
183190
183578
|
if (other === path) continue;
|
|
@@ -184334,7 +184722,7 @@ function bundleArrows(nodes, groups, edges, ownBox, joinPairs = true) {
|
|
|
184334
184722
|
if (sources.length < BUNDLE_AT) continue;
|
|
184335
184723
|
if (sources.length < FEW && (!joinPairs || !HOSTS2.has(typeOf.get(frame) ?? "") || (pairs.get(frame) ?? 0) < 2 || sources.some((edge) => !edges.some((other) => !joinable.has(other) && (other.from === edge.from || other.to === edge.from))))) continue;
|
|
184336
184724
|
for (const edge of sources) joined2.add(edge);
|
|
184337
|
-
replacements.set(first, { from: own2.key, to: first.to, label: `${first.label ?? ""} (${sources.length})
|
|
184725
|
+
replacements.set(first, { from: own2.key, to: first.to, label: `${first.label ?? ""} (${sources.length})`, verb: first.verb ?? null });
|
|
184338
184726
|
}
|
|
184339
184727
|
const out = [];
|
|
184340
184728
|
const written3 = /* @__PURE__ */ new Set();
|
|
@@ -184346,7 +184734,7 @@ function bundleArrows(nodes, groups, edges, ownBox, joinPairs = true) {
|
|
|
184346
184734
|
if (written3.has(pair2)) {
|
|
184347
184735
|
const index2 = out.findIndex((candidate2) => `${candidate2.from}\0${candidate2.to}` === pair2);
|
|
184348
184736
|
const before = out[index2];
|
|
184349
|
-
out[index2] = { ...before, label: [before.label, next.label].filter((label) => label !== null && label !== void 0 && label !== "").join(", ") };
|
|
184737
|
+
out[index2] = { ...before, label: [before.label, next.label].filter((label) => label !== null && label !== void 0 && label !== "").join(", "), verb: before.verb === next.verb ? before.verb ?? null : null };
|
|
184350
184738
|
continue;
|
|
184351
184739
|
}
|
|
184352
184740
|
written3.add(pair2);
|
|
@@ -184869,6 +185257,10 @@ function stackArrows(plan) {
|
|
|
184869
185257
|
}
|
|
184870
185258
|
return { arrows, unjoined };
|
|
184871
185259
|
}
|
|
185260
|
+
function verbOf(arrow) {
|
|
185261
|
+
if (arrow.grant || arrow.order !== true && POLICY_KEY.test(arrow.via)) return "grants";
|
|
185262
|
+
return LABEL_VERBS[arrow.label ?? ""] ?? null;
|
|
185263
|
+
}
|
|
184872
185264
|
function joinArrows(arrows) {
|
|
184873
185265
|
const joined2 = new Set(arrows.filter((arrow) => arrow.order !== true).flatMap((arrow) => [`${arrow.from}\0${arrow.to}`, `${arrow.to}\0${arrow.from}`]));
|
|
184874
185266
|
const byPair = /* @__PURE__ */ new Map();
|
|
@@ -184880,10 +185272,12 @@ function joinArrows(arrows) {
|
|
|
184880
185272
|
const grantWords = grants.length === 0 ? [] : grants.length === 1 ? [grants[0]?.label ?? "role"] : [`${grants.length} roles`];
|
|
184881
185273
|
const words2 = [...grantWords, ...others];
|
|
184882
185274
|
const label = words2.length === 0 ? null : words2.length <= MAX_LABELS2 ? words2.join(", ") : `${group2.length} links`;
|
|
184883
|
-
|
|
185275
|
+
const verbs = new Set(group2.map(verbOf));
|
|
185276
|
+
const verb = verbs.size === 1 ? [...verbs][0] ?? null : null;
|
|
185277
|
+
return { from: first.from, to: first.to, label, verb, ...group2.every((arrow) => arrow.order === true) ? { arrow: "-->" } : {} };
|
|
184884
185278
|
});
|
|
184885
185279
|
}
|
|
184886
|
-
var ORDER_LABEL, INBOUND, QUIET, ATTRIBUTE_LABELS, TYPE_LABELS, VAGUE_ATTRIBUTES, MAX_LABELS2;
|
|
185280
|
+
var ORDER_LABEL, INBOUND, QUIET, ATTRIBUTE_LABELS, TYPE_LABELS, VAGUE_ATTRIBUTES, LABEL_VERBS, POLICY_KEY, MAX_LABELS2;
|
|
184887
185281
|
var init_edges2 = __esm({
|
|
184888
185282
|
"../../packages/diagrams/src/importers/terraform/edges.ts"() {
|
|
184889
185283
|
"use strict";
|
|
@@ -184944,6 +185338,34 @@ var init_edges2 = __esm({
|
|
|
184944
185338
|
service: "calls"
|
|
184945
185339
|
};
|
|
184946
185340
|
VAGUE_ATTRIBUTES = /* @__PURE__ */ new Set(["value", "values", "config", "configuration", "settings", "properties", "body", "content", "input", "inputs", "parameters", "source", "data"]);
|
|
185341
|
+
LABEL_VERBS = {
|
|
185342
|
+
identity: "grants",
|
|
185343
|
+
role: "grants",
|
|
185344
|
+
policy: "grants",
|
|
185345
|
+
grants: "grants",
|
|
185346
|
+
"grants on": "grants",
|
|
185347
|
+
principal: "grants",
|
|
185348
|
+
data: "stores",
|
|
185349
|
+
storage: "stores",
|
|
185350
|
+
cache: "stores",
|
|
185351
|
+
secret: "secret",
|
|
185352
|
+
secrets: "secret",
|
|
185353
|
+
password: "secret",
|
|
185354
|
+
messages: "sends",
|
|
185355
|
+
"dead letters": "sends",
|
|
185356
|
+
triggers: "triggers",
|
|
185357
|
+
logs: "reports",
|
|
185358
|
+
"logs to": "reports",
|
|
185359
|
+
telemetry: "reports",
|
|
185360
|
+
images: "pulls",
|
|
185361
|
+
"private link": "private",
|
|
185362
|
+
"VNet integration": "private",
|
|
185363
|
+
"public IP": "routes",
|
|
185364
|
+
firewall: "filters",
|
|
185365
|
+
calls: "calls",
|
|
185366
|
+
[ORDER_LABEL]: "depends-on"
|
|
185367
|
+
};
|
|
185368
|
+
POLICY_KEY = /(?:^|\.)[a-z0-9_]*polic(?:y|ies)[a-z0-9_]*\./;
|
|
184947
185369
|
MAX_LABELS2 = 2;
|
|
184948
185370
|
}
|
|
184949
185371
|
});
|
|
@@ -185207,7 +185629,7 @@ function picture(plan, context, groupType) {
|
|
|
185207
185629
|
if (shape === "container") {
|
|
185208
185630
|
const frame = containerFrame(resource.key);
|
|
185209
185631
|
const parent = byFile ? parentOf4(frame, resource) : plan.parents.get(frame) ?? null;
|
|
185210
|
-
groups.push({ key: frame, label: box.label, type:
|
|
185632
|
+
groups.push({ key: frame, label: box.label, type: HOLDER_TYPES[box.type] ?? "resource-group", icon: box.icon ?? null, sub: null, parent, idHint: `${resource.name}_group` });
|
|
185211
185633
|
const product = role.role === "node" ? productOf2(resource, plan) : box.label;
|
|
185212
185634
|
nodes.push({ ...box, label: box.label === product ? box.label : product, sub: box.label === product ? box.sub ?? null : withParts(literalDetails(resource), multiplicity(resource), resource.kind === "data" && !plan.compatible ? "existing" : null), group: frame });
|
|
185213
185635
|
} else {
|
|
@@ -185227,7 +185649,7 @@ function picture(plan, context, groupType) {
|
|
|
185227
185649
|
for (const [key, module] of plan.modules) {
|
|
185228
185650
|
const source = module.source.replace(/^(?:\.\.?\/)+/, "");
|
|
185229
185651
|
const label = `${humanize(module.name)}${module.instance === null ? "" : ` ${module.instance}`}`;
|
|
185230
|
-
groups.push({ key, label, type: null, icon: moduleIcon(module.name, module.source, stackProvider(plan)) ?? "lucide:package", sub: cleanText(`${module.noun ?? "Module"} ${source}`), parent: plan.parents.get(key) ?? null, idHint: `${module.name}${module.instance === null ? "" : `_${module.instance}`}` });
|
|
185652
|
+
groups.push({ key, label, type: null, otherwise: "resource-group", icon: moduleIcon(module.name, module.source, stackProvider(plan)) ?? "lucide:package", sub: cleanText(`${module.noun ?? "Module"} ${source}`), parent: plan.parents.get(key) ?? null, idHint: `${module.name}${module.instance === null ? "" : `_${module.instance}`}` });
|
|
185231
185653
|
}
|
|
185232
185654
|
const holding = /* @__PURE__ */ new Set();
|
|
185233
185655
|
for (const node3 of nodes) for (const key of [node3.group ?? "", ...plan.ancestors(node3.group ?? "")]) holding.add(key);
|
|
@@ -185269,7 +185691,7 @@ function withoutIdleBoxes(nodes, groups, edges) {
|
|
|
185269
185691
|
const framed = groups.map((group2) => {
|
|
185270
185692
|
const box = idle.get(group2.key);
|
|
185271
185693
|
if (box === void 0) return group2;
|
|
185272
|
-
const said = group2.label.includes(box.label) || group2.type !== null && group2.type !== void 0 ? null : box.label;
|
|
185694
|
+
const said = group2.label.includes(box.label) || group2.type !== null && group2.type !== void 0 && group2.key !== containerFrame(box.key) ? null : box.label;
|
|
185273
185695
|
return { ...group2, sub: withParts(group2.sub ?? null, said, box.sub ?? null) };
|
|
185274
185696
|
});
|
|
185275
185697
|
return { nodes: kept2, groups: framed };
|
|
@@ -185293,7 +185715,7 @@ function literalDetails(resource) {
|
|
|
185293
185715
|
const values = names8.map((name2) => literal2(resource, name2)).filter((value) => value !== null && value !== "");
|
|
185294
185716
|
return values.length === 0 ? null : values.join(" ");
|
|
185295
185717
|
}
|
|
185296
|
-
var ACCOUNT_NAMES;
|
|
185718
|
+
var ACCOUNT_NAMES, HOLDER_TYPES;
|
|
185297
185719
|
var init_picture = __esm({
|
|
185298
185720
|
"../../packages/diagrams/src/importers/terraform/picture.ts"() {
|
|
185299
185721
|
"use strict";
|
|
@@ -185306,6 +185728,17 @@ var init_picture = __esm({
|
|
|
185306
185728
|
init_plan9();
|
|
185307
185729
|
init_resources();
|
|
185308
185730
|
ACCOUNT_NAMES = { aws: "AWS account", azure: "Azure subscription", gcp: "Google Cloud project" };
|
|
185731
|
+
HOLDER_TYPES = {
|
|
185732
|
+
database: "data-tier",
|
|
185733
|
+
cache: "data-tier",
|
|
185734
|
+
storage: "storage-account",
|
|
185735
|
+
queue: "messaging",
|
|
185736
|
+
secret: "security",
|
|
185737
|
+
identity: "identity-boundary",
|
|
185738
|
+
service: "app-tier",
|
|
185739
|
+
function: "app-tier",
|
|
185740
|
+
gateway: "edge"
|
|
185741
|
+
};
|
|
185309
185742
|
}
|
|
185310
185743
|
});
|
|
185311
185744
|
|
|
@@ -187362,7 +187795,7 @@ function chainOf(expr) {
|
|
|
187362
187795
|
}
|
|
187363
187796
|
return { base: current, steps };
|
|
187364
187797
|
}
|
|
187365
|
-
function
|
|
187798
|
+
function nameOf8(slot, evaluator) {
|
|
187366
187799
|
const named = bodyObject(slot.declaration.value)?.entries.find((entry2) => entry2.key === "name")?.value;
|
|
187367
187800
|
return named === void 0 ? null : textOf5(evaluator.evaluate(named, slot.env));
|
|
187368
187801
|
}
|
|
@@ -187377,15 +187810,15 @@ var init_slots2 = __esm({
|
|
|
187377
187810
|
|
|
187378
187811
|
// ../../packages/diagrams/src/importers/bicep/items.ts
|
|
187379
187812
|
function withoutReadCopies(items2) {
|
|
187380
|
-
const
|
|
187813
|
+
const nameOf11 = (item) => item.attributes.find((attribute2) => attribute2.name === "name")?.value ?? null;
|
|
187381
187814
|
const made = /* @__PURE__ */ new Map();
|
|
187382
187815
|
for (const item of items2) {
|
|
187383
|
-
const name2 =
|
|
187816
|
+
const name2 = nameOf11(item);
|
|
187384
187817
|
if (!item.existing && name2 !== null) made.set(`${item.type}\0${name2}`, item.name);
|
|
187385
187818
|
}
|
|
187386
187819
|
const alias = /* @__PURE__ */ new Map();
|
|
187387
187820
|
for (const item of items2) {
|
|
187388
|
-
const name2 =
|
|
187821
|
+
const name2 = nameOf11(item);
|
|
187389
187822
|
const real = name2 === null ? void 0 : made.get(`${item.type}\0${name2}`);
|
|
187390
187823
|
if (item.existing && real !== void 0) alias.set(item.name, real);
|
|
187391
187824
|
}
|
|
@@ -187478,18 +187911,18 @@ var init_items3 = __esm({
|
|
|
187478
187911
|
}
|
|
187479
187912
|
/** The resource a child names as its parent by the start of its name (`vnet-shop` of `vnet-shop/app`), when the stack declares it. */
|
|
187480
187913
|
parentByName(slot) {
|
|
187481
|
-
const name2 =
|
|
187914
|
+
const name2 = nameOf8(slot, this.evaluator);
|
|
187482
187915
|
const segments = slot.armType.split("/");
|
|
187483
187916
|
if (name2 === null || !name2.includes("/") || segments.length < 3) return null;
|
|
187484
187917
|
const parentType = segments.slice(0, -1).join("/").toLowerCase();
|
|
187485
187918
|
const parentName = name2.slice(0, name2.lastIndexOf("/"));
|
|
187486
|
-
for (const list of this.slots.values()) for (const candidate2 of list) if (candidate2.armType.toLowerCase() === parentType &&
|
|
187919
|
+
for (const list of this.slots.values()) for (const candidate2 of list) if (candidate2.armType.toLowerCase() === parentType && nameOf8(candidate2, this.evaluator) === parentName) return candidate2.transparent ? candidate2.holder?.name ?? null : candidate2.name;
|
|
187487
187920
|
if (/\/(?:blob|queue|table|file)services$/.test(parentType) && segments.length >= 4) return this.declared(segments.slice(0, -2).join("/"), parentName.slice(0, parentName.lastIndexOf("/")));
|
|
187488
187921
|
return null;
|
|
187489
187922
|
}
|
|
187490
187923
|
/** The item of a type and a name the deployment declares, or null. */
|
|
187491
187924
|
declared(type, name2) {
|
|
187492
|
-
for (const list of this.slots.values()) for (const candidate2 of list) if (candidate2.armType.toLowerCase() === type.toLowerCase() &&
|
|
187925
|
+
for (const list of this.slots.values()) for (const candidate2 of list) if (candidate2.armType.toLowerCase() === type.toLowerCase() && nameOf8(candidate2, this.evaluator) === name2) return candidate2.name;
|
|
187493
187926
|
return null;
|
|
187494
187927
|
}
|
|
187495
187928
|
/** The item that stands for a name: a storage service's account, since the service itself is not drawn. */
|
|
@@ -187730,9 +188163,9 @@ var init_references = __esm({
|
|
|
187730
188163
|
if (type !== null && last !== null && last !== void 0) {
|
|
187731
188164
|
for (const list of this.slots.values()) {
|
|
187732
188165
|
for (const slot of list) {
|
|
187733
|
-
const own2 =
|
|
188166
|
+
const own2 = nameOf8(slot, this.evaluator);
|
|
187734
188167
|
if (slot.armType.toLowerCase() === type && (own2 === last || own2 === names8.join("/"))) return [slot.name];
|
|
187735
|
-
if (type === `${slot.armType.toLowerCase()}/subnets` &&
|
|
188168
|
+
if (type === `${slot.armType.toLowerCase()}/subnets` && nameOf8(slot, this.evaluator) === names8[names8.length - 2]) {
|
|
187736
188169
|
const subnet = slot.subnets.find((entry2) => entry2.display === last || entry2.label === last);
|
|
187737
188170
|
if (subnet !== void 0) return [subnet.name];
|
|
187738
188171
|
}
|
|
@@ -188885,6 +189318,74 @@ var init_document2 = __esm({
|
|
|
188885
189318
|
}
|
|
188886
189319
|
});
|
|
188887
189320
|
|
|
189321
|
+
// ../../packages/diagrams/src/importers/asyncapi/layers.ts
|
|
189322
|
+
function adjacency(keys, arrows, reverse) {
|
|
189323
|
+
const next = new Map(keys.map((key) => [key, []]));
|
|
189324
|
+
for (const arrow of arrows) next.get(reverse ? arrow.to : arrow.from)?.push(reverse ? arrow.from : arrow.to);
|
|
189325
|
+
return next;
|
|
189326
|
+
}
|
|
189327
|
+
function finishOrder(start2, next, seen, finished2) {
|
|
189328
|
+
const stack = [{ key: start2, index: 0 }];
|
|
189329
|
+
seen.add(start2);
|
|
189330
|
+
while (stack.length > 0) {
|
|
189331
|
+
const top = stack[stack.length - 1];
|
|
189332
|
+
const following = next.get(top.key) ?? [];
|
|
189333
|
+
if (top.index < following.length) {
|
|
189334
|
+
const key = following[top.index];
|
|
189335
|
+
top.index += 1;
|
|
189336
|
+
if (!seen.has(key)) {
|
|
189337
|
+
seen.add(key);
|
|
189338
|
+
stack.push({ key, index: 0 });
|
|
189339
|
+
}
|
|
189340
|
+
} else {
|
|
189341
|
+
finished2.push(top.key);
|
|
189342
|
+
stack.pop();
|
|
189343
|
+
}
|
|
189344
|
+
}
|
|
189345
|
+
}
|
|
189346
|
+
function layersOf(keys, arrows) {
|
|
189347
|
+
const forward = adjacency(keys, arrows, false);
|
|
189348
|
+
const backward = adjacency(keys, arrows, true);
|
|
189349
|
+
const finished2 = [];
|
|
189350
|
+
const seen = /* @__PURE__ */ new Set();
|
|
189351
|
+
for (const key of keys) if (!seen.has(key)) finishOrder(key, forward, seen, finished2);
|
|
189352
|
+
const component = /* @__PURE__ */ new Map();
|
|
189353
|
+
const members2 = [];
|
|
189354
|
+
const assigned = /* @__PURE__ */ new Set();
|
|
189355
|
+
for (const key of [...finished2].reverse()) {
|
|
189356
|
+
if (assigned.has(key)) continue;
|
|
189357
|
+
const found = [];
|
|
189358
|
+
finishOrder(key, backward, assigned, found);
|
|
189359
|
+
for (const member of found) component.set(member, members2.length);
|
|
189360
|
+
members2.push(found);
|
|
189361
|
+
}
|
|
189362
|
+
const looped = new Set(members2.filter((group2) => group2.length > 1).flat());
|
|
189363
|
+
for (const arrow of arrows) if (arrow.from === arrow.to) looped.add(arrow.from);
|
|
189364
|
+
const step = new Array(members2.length).fill(0);
|
|
189365
|
+
const fed = /* @__PURE__ */ new Set();
|
|
189366
|
+
for (let index2 = 0; index2 < members2.length; index2 += 1) {
|
|
189367
|
+
for (const key of members2[index2] ?? []) {
|
|
189368
|
+
for (const to of forward.get(key) ?? []) {
|
|
189369
|
+
const target = component.get(to);
|
|
189370
|
+
if (target === index2) continue;
|
|
189371
|
+
step[target] = Math.max(step[target], step[index2] + 1);
|
|
189372
|
+
fed.add(target);
|
|
189373
|
+
}
|
|
189374
|
+
}
|
|
189375
|
+
}
|
|
189376
|
+
for (let index2 = members2.length - 1; index2 >= 0; index2 -= 1) {
|
|
189377
|
+
if (fed.has(index2)) continue;
|
|
189378
|
+
const targets = (members2[index2] ?? []).flatMap((key) => forward.get(key) ?? []).map((to) => component.get(to)).filter((target) => target !== index2);
|
|
189379
|
+
if (targets.length > 0) step[index2] = Math.min(...targets.map((target) => step[target])) - 1;
|
|
189380
|
+
}
|
|
189381
|
+
return { layer: new Map(keys.map((key) => [key, step[component.get(key)]])), looped };
|
|
189382
|
+
}
|
|
189383
|
+
var init_layers2 = __esm({
|
|
189384
|
+
"../../packages/diagrams/src/importers/asyncapi/layers.ts"() {
|
|
189385
|
+
"use strict";
|
|
189386
|
+
}
|
|
189387
|
+
});
|
|
189388
|
+
|
|
188888
189389
|
// ../../packages/diagrams/src/importers/asyncapi/spec.ts
|
|
188889
189390
|
function messageName(root, node3, fallback) {
|
|
188890
189391
|
const ref = refOf(node3);
|
|
@@ -189019,6 +189520,7 @@ function readAsyncApi(text3, context) {
|
|
|
189019
189520
|
const edges = [];
|
|
189020
189521
|
const arrows = /* @__PURE__ */ new Map();
|
|
189021
189522
|
const channelBox = /* @__PURE__ */ new Map();
|
|
189523
|
+
const channelFamily = /* @__PURE__ */ new Map();
|
|
189022
189524
|
const brokerHosts = /* @__PURE__ */ new Map();
|
|
189023
189525
|
const brokerServers = /* @__PURE__ */ new Map();
|
|
189024
189526
|
let operations = 0;
|
|
@@ -189038,8 +189540,9 @@ function readAsyncApi(text3, context) {
|
|
|
189038
189540
|
const key = `channel:${channel.address}`;
|
|
189039
189541
|
const existing = channelBox.get(key);
|
|
189040
189542
|
if (existing === void 0) {
|
|
189041
|
-
const box = { key, type: "queue", label: cleanText(channel.address), sub: channel.description === null ? null : cleanText(channel.description), group:
|
|
189543
|
+
const box = { key, type: "queue", label: cleanText(channel.address), sub: channel.description === null ? null : cleanText(channel.description), group: null, idHint: channel.address };
|
|
189042
189544
|
channelBox.set(key, box);
|
|
189545
|
+
if (family !== void 0) channelFamily.set(key, family);
|
|
189043
189546
|
nodes.push(box);
|
|
189044
189547
|
}
|
|
189045
189548
|
}
|
|
@@ -189053,19 +189556,37 @@ function readAsyncApi(text3, context) {
|
|
|
189053
189556
|
arrows.set(pair2, { from, to, messages: [...arrows.get(pair2)?.messages ?? [], ...operation.messages] });
|
|
189054
189557
|
}
|
|
189055
189558
|
}
|
|
189056
|
-
for (const arrow of arrows.values()) edges.push({ from: arrow.from, to: arrow.to, label: messagesLabel(arrow.messages) });
|
|
189057
|
-
const
|
|
189559
|
+
for (const arrow of arrows.values()) edges.push({ from: arrow.from, to: arrow.to, label: messagesLabel(arrow.messages), verb: arrow.from.startsWith("channel:") ? "receives" : "sends" });
|
|
189560
|
+
const { layer: layer2, looped } = layersOf(
|
|
189561
|
+
nodes.map((node3) => node3.key),
|
|
189562
|
+
edges
|
|
189563
|
+
);
|
|
189564
|
+
const brokerIcon = (family) => BROKERS[family]?.icon ?? (brokerServers.get(family) ?? []).map((server) => iconForName(`${server.name} ${server.host ?? ""}`, "queue")).find((icon) => icon?.startsWith("simple:") === true) ?? null;
|
|
189565
|
+
const frameSteps = /* @__PURE__ */ new Map();
|
|
189566
|
+
const frameKey = (family, step) => {
|
|
189567
|
+
const index3 = (frameSteps.get(family) ?? []).indexOf(step);
|
|
189568
|
+
return index3 === 0 ? `broker:${family}` : `broker:${family}:${index3 + 1}`;
|
|
189569
|
+
};
|
|
189570
|
+
const placed = nodes.map((node3) => {
|
|
189571
|
+
const family = channelFamily.get(node3.key);
|
|
189572
|
+
if (family === void 0) return node3;
|
|
189573
|
+
if (looped.has(node3.key)) return { ...node3, icon: brokerIcon(family) };
|
|
189574
|
+
const step = layer2.get(node3.key) ?? 0;
|
|
189575
|
+
const steps = frameSteps.get(family) ?? [];
|
|
189576
|
+
if (!steps.includes(step)) frameSteps.set(family, [...steps, step]);
|
|
189577
|
+
return { ...node3, group: frameKey(family, step) };
|
|
189578
|
+
});
|
|
189579
|
+
const usedFamilies = new Set(channelFamily.values());
|
|
189058
189580
|
for (const family of [...brokerServers.keys()]) {
|
|
189059
|
-
const key = `broker:${family}`;
|
|
189060
|
-
if (!usedFamilies.has(key)) continue;
|
|
189061
189581
|
const broker = BROKERS[family];
|
|
189062
189582
|
const hosts = [...brokerHosts.get(family) ?? []];
|
|
189063
|
-
const servers = brokerServers.get(family) ?? [];
|
|
189064
|
-
const named = servers.map((server) => iconForName(`${server.name} ${server.host ?? ""}`, "queue")).find((icon) => icon?.startsWith("simple:") === true) ?? null;
|
|
189065
189583
|
const where = hosts.length === 0 ? null : hosts.length === 1 ? hosts[0] ?? null : `${hosts.length} hosts`;
|
|
189066
|
-
|
|
189584
|
+
const steps = [...frameSteps.get(family) ?? []].sort((a, b) => a - b);
|
|
189585
|
+
for (const step of steps) {
|
|
189586
|
+
groups.push({ key: frameKey(family, step), label: broker?.label ?? `${family.toUpperCase()} broker`, type: "messaging", icon: brokerIcon(family), sub: where === null || step !== steps[0] ? null : cleanText(where), idHint: family });
|
|
189587
|
+
}
|
|
189067
189588
|
}
|
|
189068
|
-
const unused = [...brokerServers.entries()].filter(([family]) => !usedFamilies.has(
|
|
189589
|
+
const unused = [...brokerServers.entries()].filter(([family]) => !usedFamilies.has(family)).flatMap(([, servers]) => servers);
|
|
189069
189590
|
if (unused.length > 0) {
|
|
189070
189591
|
const first = unused[0];
|
|
189071
189592
|
const file2 = applications.find(({ app }) => app.servers.includes(first))?.file ?? files[0];
|
|
@@ -189074,14 +189595,14 @@ function readAsyncApi(text3, context) {
|
|
|
189074
189595
|
const sends = (key) => edges.some((edge) => edge.from === key);
|
|
189075
189596
|
const receives = (key) => edges.some((edge) => edge.to === key);
|
|
189076
189597
|
const rank = (node3) => node3.type === "queue" ? 1 : sends(node3.key) && !receives(node3.key) ? 0 : !sends(node3.key) && receives(node3.key) ? 2 : 1;
|
|
189077
|
-
const ordered = [...
|
|
189598
|
+
const ordered = [...placed].sort((a, b) => rank(a) - rank(b));
|
|
189078
189599
|
const one = applications.length === 1 ? applications[0]?.app : void 0;
|
|
189079
189600
|
const channels = channelBox.size;
|
|
189080
189601
|
return writeFlow(
|
|
189081
189602
|
{
|
|
189082
189603
|
title: context.title ?? (one === void 0 ? "Event flows" : cleanText(one.title)),
|
|
189083
189604
|
desc: one === void 0 ? `${countOf2(applications.length, "application")} and the ${countOf2(channels, "channel")} where they meet: an arrow into a channel sends to it, an arrow out of one receives from it, labelled with the messages. Imported from AsyncAPI.` : `What ${cleanText(one.title)} sends and receives on ${countOf2(channels, "channel")}: an arrow into a channel sends to it, an arrow out of one receives from it, labelled with the messages. Imported from AsyncAPI ${cleanText(one.version)}.`,
|
|
189084
|
-
direction: "
|
|
189605
|
+
direction: "down",
|
|
189085
189606
|
nodes: ordered,
|
|
189086
189607
|
groups,
|
|
189087
189608
|
edges,
|
|
@@ -189099,6 +189620,7 @@ var init_asyncapi = __esm({
|
|
|
189099
189620
|
init_core();
|
|
189100
189621
|
init_shared2();
|
|
189101
189622
|
init_document2();
|
|
189623
|
+
init_layers2();
|
|
189102
189624
|
init_spec();
|
|
189103
189625
|
BROKERS = {
|
|
189104
189626
|
kafka: { label: "Kafka", icon: "simple:apachekafka" },
|
|
@@ -189460,12 +189982,12 @@ function readBackstage(textIn, context) {
|
|
|
189460
189982
|
for (const group2 of entities.filter((entity) => entity.kind === "Group")) {
|
|
189461
189983
|
const members2 = entities.filter((entity) => entity.kind === "User" && entity.memberOf.includes(group2.ref)).map((user) => user.title ?? user.name);
|
|
189462
189984
|
const said = members2.length === 0 ? null : members2.length <= 2 ? members2.join(", ") : countOf2(members2.length, "member");
|
|
189463
|
-
groups.push({ key: group2.ref, label: group2.title ?? group2.name, sub: cleanText(["Group", group2.type, said].filter((part) => part !== null).join(", ")), icon: "lucide:users", parent: group2.parent !== null && byRef.has(group2.parent) ? group2.parent : null, idHint: group2.name });
|
|
189985
|
+
groups.push({ key: group2.ref, label: group2.title ?? group2.name, sub: cleanText(["Group", group2.type, said].filter((part) => part !== null).join(", ")), type: "identity-boundary", icon: "lucide:users", parent: group2.parent !== null && byRef.has(group2.parent) ? group2.parent : null, idHint: group2.name });
|
|
189464
189986
|
}
|
|
189465
189987
|
for (const entity of boxes2) if (entity.owner !== null && byRef.get(entity.owner)?.kind === "Group") frameOf3.set(entity.ref, entity.owner);
|
|
189466
189988
|
} else {
|
|
189467
|
-
for (const domain2 of entities.filter((entity) => entity.kind === "Domain")) groups.push({ key: domain2.ref, label: domain2.title ?? domain2.name, sub: cleanText(`Domain${domain2.owner === null ? "" : `, owned by ${nameOfRef2(domain2.owner)}`}`), icon: "lucide:map", idHint: domain2.name });
|
|
189468
|
-
for (const system of entities.filter((entity) => entity.kind === "System")) groups.push({ key: system.ref, label: system.title ?? system.name, sub: cleanText(`System${system.owner === null ? "" : `, owned by ${nameOfRef2(system.owner)}`}`), icon: "lucide:boxes", parent: system.domain !== null && byRef.has(system.domain) ? system.domain : null, idHint: system.name });
|
|
189989
|
+
for (const domain2 of entities.filter((entity) => entity.kind === "Domain")) groups.push({ key: domain2.ref, label: domain2.title ?? domain2.name, sub: cleanText(`Domain${domain2.owner === null ? "" : `, owned by ${nameOfRef2(domain2.owner)}`}`), type: "resource-group", tone: "blue", icon: "lucide:map", idHint: domain2.name });
|
|
189990
|
+
for (const system of entities.filter((entity) => entity.kind === "System")) groups.push({ key: system.ref, label: system.title ?? system.name, sub: cleanText(`System${system.owner === null ? "" : `, owned by ${nameOfRef2(system.owner)}`}`), type: "app-tier", icon: "lucide:boxes", parent: system.domain !== null && byRef.has(system.domain) ? system.domain : null, idHint: system.name });
|
|
189469
189991
|
for (const entity of boxes2) if (entity.system !== null && byRef.get(entity.system)?.kind === "System") frameOf3.set(entity.ref, entity.system);
|
|
189470
189992
|
}
|
|
189471
189993
|
const order = { Component: 0, API: 1, Resource: 2 };
|
|
@@ -189478,19 +190000,19 @@ function readBackstage(textIn, context) {
|
|
|
189478
190000
|
const drawn = new Set(nodes.map((node3) => node3.key));
|
|
189479
190001
|
const edges = [];
|
|
189480
190002
|
const unknown2 = /* @__PURE__ */ new Set();
|
|
189481
|
-
const link2 = (from, to, label, arrow) => {
|
|
190003
|
+
const link2 = (from, to, label, verb, arrow) => {
|
|
189482
190004
|
if (!drawn.has(to)) {
|
|
189483
190005
|
if (!byRef.has(to)) unknown2.add(to);
|
|
189484
190006
|
return;
|
|
189485
190007
|
}
|
|
189486
|
-
edges.push({ from, to, label, ...arrow === void 0 ? {} : { arrow } });
|
|
190008
|
+
edges.push({ from, to, label, verb, ...arrow === void 0 ? {} : { arrow } });
|
|
189487
190009
|
};
|
|
189488
190010
|
for (const entity of ordered) {
|
|
189489
|
-
for (const api of entity.providesApis) link2(entity.ref, api, "provides");
|
|
189490
|
-
for (const api of entity.consumesApis) link2(entity.ref, api, "consumes");
|
|
189491
|
-
for (const target of entity.dependsOn) link2(entity.ref, target, "depends on");
|
|
189492
|
-
for (const source of entity.dependencyOf) if (drawn.has(source)) link2(source, entity.ref, "depends on");
|
|
189493
|
-
if (entity.kind === "Component" && entity.parent !== null) link2(entity.ref, entity.parent, "part of", "-->");
|
|
190011
|
+
for (const api of entity.providesApis) link2(entity.ref, api, "provides", "provides");
|
|
190012
|
+
for (const api of entity.consumesApis) link2(entity.ref, api, "consumes", "consumes");
|
|
190013
|
+
for (const target of entity.dependsOn) link2(entity.ref, target, "depends on", "depends-on");
|
|
190014
|
+
for (const source of entity.dependencyOf) if (drawn.has(source)) link2(source, entity.ref, "depends on", "depends-on");
|
|
190015
|
+
if (entity.kind === "Component" && entity.parent !== null) link2(entity.ref, entity.parent, "part of", null, "-->");
|
|
189494
190016
|
}
|
|
189495
190017
|
if (unknown2.size > 0) {
|
|
189496
190018
|
context.report.add(DIAGNOSTIC_CODES.importUnresolved, START, `${countOf2(unknown2.size, "relation")} name${unknown2.size === 1 ? "s an entity" : " entities"} the files do not describe, so no arrow is drawn: ${[...unknown2].slice(0, 3).join(", ")}.`, "Send the catalog-info.yaml files that describe them, or check that each reference names its kind, such as resource:orders-db.");
|
|
@@ -190700,7 +191222,7 @@ function edgesOf2(services, volumes) {
|
|
|
190700
191222
|
for (const other of services) {
|
|
190701
191223
|
if (other.name !== service.name && service.environment.some((value) => namesHost2(value, other.name))) edges.push({ from: `service:${service.name}`, to: `service:${other.name}` });
|
|
190702
191224
|
}
|
|
190703
|
-
for (const volume of service.volumes) if (volumes.has(volume)) edges.push({ from: `service:${service.name}`, to: `volume:${volume}`, label: "mounts" });
|
|
191225
|
+
for (const volume of service.volumes) if (volumes.has(volume)) edges.push({ from: `service:${service.name}`, to: `volume:${volume}`, label: "mounts", verb: "mounts" });
|
|
190704
191226
|
}
|
|
190705
191227
|
return edges;
|
|
190706
191228
|
}
|
|
@@ -192416,12 +192938,12 @@ function helmFrames(manifests) {
|
|
|
192416
192938
|
const release = releaseOf(manifest);
|
|
192417
192939
|
const chart = chartLabel(manifest);
|
|
192418
192940
|
const partOf2 = manifest.meta.get("app.kubernetes.io/part-of");
|
|
192419
|
-
if (partOf2 !== void 0 && partOf2 !== "" && partOf2 !== release) frames.push({ key: `part-of:${partOf2}`, label: partOf2, sub: "Application", icon: "lucide:boxes", idHint: partOf2 });
|
|
192941
|
+
if (partOf2 !== void 0 && partOf2 !== "" && partOf2 !== release) frames.push({ key: `part-of:${partOf2}`, label: partOf2, sub: "Application", icon: "lucide:boxes", type: "app-tier", idHint: partOf2 });
|
|
192420
192942
|
if (release === null) return frames;
|
|
192421
192943
|
const several = (charts.get(release)?.size ?? 0) > 1;
|
|
192422
192944
|
const only = several || chart === null ? null : chart;
|
|
192423
|
-
frames.push({ key: `release:${release}`, label: release, sub: cleanText(only === null ? "Release" : `Release of ${only.name}${only.version === null ? "" : ` ${only.version}`}`), icon: "simple:helm", idHint: release });
|
|
192424
|
-
if (several && chart !== null) frames.push({ key: `chart:${release}/${chart.name}`, label: chart.name, sub: cleanText(`Chart${chart.version === null ? "" : ` ${chart.version}`}`), icon: "lucide:package", idHint: chart.name });
|
|
192945
|
+
frames.push({ key: `release:${release}`, label: release, sub: cleanText(only === null ? "Release" : `Release of ${only.name}${only.version === null ? "" : ` ${only.version}`}`), icon: "simple:helm", type: "resource-group", tone: "blue", idHint: release });
|
|
192946
|
+
if (several && chart !== null) frames.push({ key: `chart:${release}/${chart.name}`, label: chart.name, sub: cleanText(`Chart${chart.version === null ? "" : ` ${chart.version}`}`), icon: "lucide:package", type: "resource-group", idHint: chart.name });
|
|
192425
192947
|
return frames;
|
|
192426
192948
|
};
|
|
192427
192949
|
}
|
|
@@ -192635,7 +193157,7 @@ function stepBoxes(jobs) {
|
|
|
192635
193157
|
last.set(job.id, keys[keys.length - 1]);
|
|
192636
193158
|
}
|
|
192637
193159
|
for (const job of jobs) for (const need of job.needs) edges.push({ from: last.get(need) ?? "", to: first.get(job.id) ?? "" });
|
|
192638
|
-
const groups = jobs.map((job) => ({ key: `job:${job.id}`, label: job.label, sub: job.detail, idHint: `job_${job.id}` }));
|
|
193160
|
+
const groups = jobs.map((job) => ({ key: `job:${job.id}`, label: job.label, sub: job.detail, otherwise: "ci-cd", idHint: `job_${job.id}` }));
|
|
192639
193161
|
return { nodes, edges, groups };
|
|
192640
193162
|
}
|
|
192641
193163
|
function readWorkflow(source, context) {
|
|
@@ -192846,7 +193368,7 @@ function readGitlabCi(source, context) {
|
|
|
192846
193368
|
nodes.push({ key: `job:${job.name}`, type: "step", label: cleanText(job.name), sub: subOf3(job), icon: job.image === null ? null : imageLook(job.image)?.icon ?? null, group: `stage:${stage}`, idHint: job.name });
|
|
192847
193369
|
if (job.trigger !== null) {
|
|
192848
193370
|
nodes.push({ key: `trigger:${job.name}`, type: "external", label: cleanText(job.trigger.label), sub: job.trigger.child ? "Child pipeline" : "Downstream pipeline", icon: "simple:gitlab", idHint: `${job.name}_pipeline` });
|
|
192849
|
-
edges.push({ from: `job:${job.name}`, to: `trigger:${job.name}`, label: "triggers" });
|
|
193371
|
+
edges.push({ from: `job:${job.name}`, to: `trigger:${job.name}`, label: "triggers", verb: "triggers" });
|
|
192850
193372
|
}
|
|
192851
193373
|
}
|
|
192852
193374
|
}
|
|
@@ -194308,7 +194830,7 @@ function stateResources(state, offsetOf) {
|
|
|
194308
194830
|
const byUrn = new Map(all.map((resource) => [resource.urn, resource]));
|
|
194309
194831
|
const counts = /* @__PURE__ */ new Map();
|
|
194310
194832
|
for (const resource of all) counts.set(logicalName(resource.urn), (counts.get(logicalName(resource.urn)) ?? 0) + 1);
|
|
194311
|
-
const
|
|
194833
|
+
const nameOf11 = (urn) => (counts.get(logicalName(urn)) ?? 0) > 1 ? urn : logicalName(urn);
|
|
194312
194834
|
const safe3 = (name2) => name2.replace(/[^A-Za-z0-9_-]+/g, "_");
|
|
194313
194835
|
const scopeOf2 = (resource) => {
|
|
194314
194836
|
const chain2 = [];
|
|
@@ -194333,21 +194855,21 @@ function stateResources(state, offsetOf) {
|
|
|
194333
194855
|
const outputs = target?.outputs;
|
|
194334
194856
|
const name2 = typeof outputs === "object" && outputs !== null && !Array.isArray(outputs) ? outputs["name"] : null;
|
|
194335
194857
|
const path = pathTo(inputs[property] ?? null, [target?.id ?? "", typeof name2 === "string" && property.endsWith("Name") ? name2 : ""], [property]);
|
|
194336
|
-
return { path: path ?? [property], refs: [
|
|
194858
|
+
return { path: path ?? [property], refs: [nameOf11(urn)] };
|
|
194337
194859
|
})
|
|
194338
194860
|
);
|
|
194339
194861
|
const parent = resource.parent === null ? void 0 : byUrn.get(resource.parent);
|
|
194340
194862
|
for (const urns of Object.values(resource.propertyDependencies)) for (const urn of urns) named.add(urn);
|
|
194341
|
-
const dependsOn = resource.dependencies.filter((urn) => !named.has(urn) && byUrn.get(urn)?.custom === true && urn !== resource.urn && urn !== resource.parent).map(
|
|
194863
|
+
const dependsOn = resource.dependencies.filter((urn) => !named.has(urn) && byUrn.get(urn)?.custom === true && urn !== resource.urn && urn !== resource.parent).map(nameOf11);
|
|
194342
194864
|
const properties = mergeValues2(resource.outputs, resource.inputs);
|
|
194343
194865
|
return {
|
|
194344
|
-
name:
|
|
194866
|
+
name: nameOf11(resource.urn),
|
|
194345
194867
|
logical: logicalName(resource.urn),
|
|
194346
194868
|
token: resource.type,
|
|
194347
194869
|
properties,
|
|
194348
194870
|
refs: refs.filter((entry2) => entry2.refs.length > 0),
|
|
194349
194871
|
dependsOn,
|
|
194350
|
-
parent: parent?.custom === true ?
|
|
194872
|
+
parent: parent?.custom === true ? nameOf11(parent.urn) : null,
|
|
194351
194873
|
existing: false,
|
|
194352
194874
|
start: offsetOf(resource.urn),
|
|
194353
194875
|
scope: scopeOf2(resource)
|
|
@@ -195591,7 +196113,7 @@ function writeC4(workspace, view, shown, title, desc) {
|
|
|
195591
196113
|
};
|
|
195592
196114
|
const writeBoundary = (boundary, depth) => {
|
|
195593
196115
|
lines.gap();
|
|
195594
|
-
lines.add(`boundary ${ids.idFor(`b:${boundary.key}`)} ${quote(cleanText(boundary.name))}${options2({ kind: boundary.kind, tech: boundary.tech === null ? null : cleanText(boundary.tech) }, ["tech"])} {`, depth);
|
|
196116
|
+
lines.add(`boundary ${ids.idFor(`b:${boundary.key}`)} ${quote(cleanText(boundary.name))}${options2({ kind: boundary.kind, tech: boundary.tech === null ? null : cleanText(boundary.tech), icon: BOUNDARY_LOOKS2[boundary.kind].icon, tone: BOUNDARY_LOOKS2[boundary.kind].tone }, ["tech"])} {`, depth);
|
|
195595
196117
|
for (const entry2 of shown.elements) if (entry2.boundary === boundary.key) elementLine2(entry2, depth + 1);
|
|
195596
196118
|
for (const child of shown.boundaries) if (child.parent === boundary.key) writeBoundary(child, depth + 1);
|
|
195597
196119
|
lines.add("}", depth);
|
|
@@ -195682,7 +196204,7 @@ function readStructurizr(text3, context) {
|
|
|
195682
196204
|
ids: written3.ids
|
|
195683
196205
|
};
|
|
195684
196206
|
}
|
|
195685
|
-
var DATABASE_WORDS, LEVELS, LEVEL_WORDS, structurizrImporter;
|
|
196207
|
+
var BOUNDARY_LOOKS2, DATABASE_WORDS, LEVELS, LEVEL_WORDS, structurizrImporter;
|
|
195686
196208
|
var init_structurizr = __esm({
|
|
195687
196209
|
"../../packages/diagrams/src/importers/structurizr/index.ts"() {
|
|
195688
196210
|
"use strict";
|
|
@@ -195692,6 +196214,12 @@ var init_structurizr = __esm({
|
|
|
195692
196214
|
init_dsl();
|
|
195693
196215
|
init_json2();
|
|
195694
196216
|
init_view();
|
|
196217
|
+
BOUNDARY_LOOKS2 = {
|
|
196218
|
+
system: { icon: "lucide:blocks", tone: "blue" },
|
|
196219
|
+
container: { icon: "lucide:box", tone: "blue" },
|
|
196220
|
+
group: { icon: "lucide:boxes", tone: "violet" },
|
|
196221
|
+
enterprise: { icon: "lucide:building", tone: "neutral" }
|
|
196222
|
+
};
|
|
195695
196223
|
DATABASE_WORDS = /\b(?:database|postgres(?:ql)?|mysql|mariadb|oracle|sql server|sqlite|mongodb|dynamodb|cassandra|cosmos ?db|couchdb|neo4j|elasticsearch|opensearch|clickhouse|snowflake|bigquery|redshift)\b/i;
|
|
195696
196224
|
LEVELS = ["context", "container", "component"];
|
|
195697
196225
|
LEVEL_WORDS = {
|
|
@@ -196328,7 +196856,7 @@ function childOf(parent, name2, line3) {
|
|
|
196328
196856
|
parent.push(entry2);
|
|
196329
196857
|
return entry2;
|
|
196330
196858
|
}
|
|
196331
|
-
function
|
|
196859
|
+
function nameOf9(raw) {
|
|
196332
196860
|
const text3 = cleanText(raw, "");
|
|
196333
196861
|
const isDir = text3.endsWith("/") && text3.length > 1;
|
|
196334
196862
|
return { name: isDir ? text3.slice(0, -1) : text3, isDir };
|
|
@@ -196355,7 +196883,7 @@ function readCommand(lines) {
|
|
|
196355
196883
|
depth += 1;
|
|
196356
196884
|
at3 += 4;
|
|
196357
196885
|
}
|
|
196358
|
-
const { name: name2, isDir } =
|
|
196886
|
+
const { name: name2, isDir } = nameOf9(line3.slice(at3));
|
|
196359
196887
|
if (name2 === "") continue;
|
|
196360
196888
|
if (!branched && root === null && top.length === 0) {
|
|
196361
196889
|
root = name2;
|
|
@@ -196405,7 +196933,7 @@ function readOutline(lines) {
|
|
|
196405
196933
|
for (const [index2, raw] of lines.entries()) {
|
|
196406
196934
|
if (raw.trim() === "") continue;
|
|
196407
196935
|
const { width, text: text3 } = indentOf6(raw);
|
|
196408
|
-
const { name: name2, isDir } =
|
|
196936
|
+
const { name: name2, isDir } = nameOf9(text3);
|
|
196409
196937
|
if (name2 === "") continue;
|
|
196410
196938
|
while (stack.length > 0 && (stack[stack.length - 1]?.width ?? 0) >= width) stack.pop();
|
|
196411
196939
|
const parent = stack[stack.length - 1]?.entry;
|
|
@@ -198165,14 +198693,14 @@ function isProduct(ref) {
|
|
|
198165
198693
|
return cloudSetOf2(ref) !== void 0 || setOf(ref) === "simple";
|
|
198166
198694
|
}
|
|
198167
198695
|
function isTheIcon(query, ref) {
|
|
198168
|
-
if (normalizePhrase(
|
|
198696
|
+
if (normalizePhrase(nameOf10(ref)) === query) return true;
|
|
198169
198697
|
if (customIconPhrases(ref)?.has(query) === true) return true;
|
|
198170
198698
|
const set2 = cloudSetOf2(ref);
|
|
198171
|
-
if (set2 !== void 0 &&
|
|
198699
|
+
if (set2 !== void 0 && nameOf10(ref) === "cloud" && CLOUD_PROVIDER_SPECS[set2].names.includes(query)) return true;
|
|
198172
198700
|
return (phrasesByText().get(query) ?? []).some((phrase2) => phrase2.ref === ref && !phrase2.isGeneric);
|
|
198173
198701
|
}
|
|
198174
198702
|
function nameHasWords(query, ref) {
|
|
198175
|
-
const words2 =
|
|
198703
|
+
const words2 = nameOf10(ref).split("-");
|
|
198176
198704
|
return query.split(" ").every((word2) => words2.includes(word2));
|
|
198177
198705
|
}
|
|
198178
198706
|
function isContested(query, top, others, needsSameMatch) {
|
|
@@ -198188,7 +198716,7 @@ function classifyIcon(name2, results) {
|
|
|
198188
198716
|
if (nameHasWords(query, top) && !isContested(query, top, others, false)) return "strong";
|
|
198189
198717
|
return "ambiguous";
|
|
198190
198718
|
}
|
|
198191
|
-
var phraseIndex, setOf,
|
|
198719
|
+
var phraseIndex, setOf, nameOf10, cloudSetOf2;
|
|
198192
198720
|
var init_icon_confidence = __esm({
|
|
198193
198721
|
"../../packages/diagrams/src/tools/workflows/icon-confidence.ts"() {
|
|
198194
198722
|
"use strict";
|
|
@@ -198196,7 +198724,7 @@ var init_icon_confidence = __esm({
|
|
|
198196
198724
|
init_icons();
|
|
198197
198725
|
phraseIndex = null;
|
|
198198
198726
|
setOf = (ref) => ref.slice(0, ref.indexOf(":"));
|
|
198199
|
-
|
|
198727
|
+
nameOf10 = (ref) => ref.slice(ref.indexOf(":") + 1);
|
|
198200
198728
|
cloudSetOf2 = (ref) => CLOUD_SETS.find((set2) => set2 === setOf(ref));
|
|
198201
198729
|
}
|
|
198202
198730
|
});
|
|
@@ -198547,7 +199075,7 @@ function isMarkCell(cell2) {
|
|
|
198547
199075
|
const word2 = cell2.trim().toLowerCase();
|
|
198548
199076
|
return YES_WORDS.includes(word2) || NO_WORDS.includes(word2) || TICKS.includes(word2) || CROSSES2.includes(word2) || word2 === "partial";
|
|
198549
199077
|
}
|
|
198550
|
-
function
|
|
199078
|
+
function wordsOf6(text3) {
|
|
198551
199079
|
return text3.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim().split(" ").filter((word2) => word2 !== "");
|
|
198552
199080
|
}
|
|
198553
199081
|
function cleanLabel2(text3) {
|
|
@@ -198581,7 +199109,7 @@ function idMaker(fallback) {
|
|
|
198581
199109
|
let count3 = 0;
|
|
198582
199110
|
return (label) => {
|
|
198583
199111
|
count3 += 1;
|
|
198584
|
-
const words2 =
|
|
199112
|
+
const words2 = wordsOf6(label).slice(0, 3);
|
|
198585
199113
|
let id = words2.join("_");
|
|
198586
199114
|
if (!/^[a-z]/.test(id) || RESERVED_IDS.has(id)) id = `${fallback}${count3}`;
|
|
198587
199115
|
id = id.slice(0, 24);
|
|
@@ -199319,7 +199847,7 @@ function singular2(word2) {
|
|
|
199319
199847
|
function iconFor(name2) {
|
|
199320
199848
|
const product = iconNamedBy(name2, null);
|
|
199321
199849
|
if (product !== null) return product;
|
|
199322
|
-
for (const word2 of
|
|
199850
|
+
for (const word2 of wordsOf6(name2)) {
|
|
199323
199851
|
const ref = ROLE_ICONS2[word2] ?? ROLE_ICONS2[singular2(word2)];
|
|
199324
199852
|
if (ref !== void 0 && isKnownIcon(ref)) return ref;
|
|
199325
199853
|
}
|
|
@@ -199411,7 +199939,7 @@ var init_icons4 = __esm({
|
|
|
199411
199939
|
function chain(ids, arrow = "->", label = "") {
|
|
199412
199940
|
return ids.slice(1).map((id, index2) => `${ids[index2] ?? id} ${arrow} ${id}${label}`);
|
|
199413
199941
|
}
|
|
199414
|
-
function
|
|
199942
|
+
function layersOf2(material) {
|
|
199415
199943
|
const lists = listsOf(material);
|
|
199416
199944
|
if (lists.length >= 2) return lists.slice(0, 6).map((list) => ({ name: list.label, blocks: list.values.slice(0, 6) }));
|
|
199417
199945
|
if (material.items.some((item) => item.depth > 0)) {
|
|
@@ -199433,6 +199961,11 @@ function partType(name2) {
|
|
|
199433
199961
|
if (/\b(web app|browser|mobile|app|client|frontend)\b/i.test(name2)) return "client";
|
|
199434
199962
|
return "service";
|
|
199435
199963
|
}
|
|
199964
|
+
function roleOption(verb) {
|
|
199965
|
+
const named = verbNamedBy(verb);
|
|
199966
|
+
const role = named === null ? null : EDGE_STYLES[named].role;
|
|
199967
|
+
return role === null ? "" : ` role=${role}`;
|
|
199968
|
+
}
|
|
199436
199969
|
function linkedFlow(material, title) {
|
|
199437
199970
|
const ids = idMaker("part");
|
|
199438
199971
|
const nodes = /* @__PURE__ */ new Map();
|
|
@@ -199446,7 +199979,7 @@ function linkedFlow(material, title) {
|
|
|
199446
199979
|
return node3.id;
|
|
199447
199980
|
};
|
|
199448
199981
|
const links = material.relations.slice(0, MOST * 2).map((relation2) => ({ from: nodeOf5(relation2.from), to: nodeOf5(relation2.to), verb: relation2.verb }));
|
|
199449
|
-
const edges = links.map((link2) => `${link2.from} -> ${link2.to} : ${quoted4(link2.verb)}`);
|
|
199982
|
+
const edges = links.map((link2) => `${link2.from} -> ${link2.to} : ${quoted4(link2.verb)}${roleOption(link2.verb)}`);
|
|
199450
199983
|
return sourceOf(`flow ${quoted4(title)} direction=${directionFor(longestChain2(links))}`, [
|
|
199451
199984
|
...[...nodes.values()].map((node3) => `node ${node3.id} ${partType(node3.label)} ${quoted4(node3.label)}${iconOption(node3.label)}`),
|
|
199452
199985
|
"",
|
|
@@ -199482,6 +200015,8 @@ var WIDEST_CHAIN, SYSTEM_BUILDERS;
|
|
|
199482
200015
|
var init_systems = __esm({
|
|
199483
200016
|
"../../packages/diagrams/src/guidance/starters/systems.ts"() {
|
|
199484
200017
|
"use strict";
|
|
200018
|
+
init_constants();
|
|
200019
|
+
init_label_icon();
|
|
199485
200020
|
init_icons4();
|
|
199486
200021
|
init_text6();
|
|
199487
200022
|
init_shared4();
|
|
@@ -199568,7 +200103,7 @@ var init_systems = __esm({
|
|
|
199568
200103
|
},
|
|
199569
200104
|
layers: (material, title) => {
|
|
199570
200105
|
const ids = idMaker("block");
|
|
199571
|
-
const body6 =
|
|
200106
|
+
const body6 = layersOf2(material).flatMap((layer2) => {
|
|
199572
200107
|
const blocks2 = distinctLabels(layer2.blocks);
|
|
199573
200108
|
return [`layer ${quoted4(layer2.name)} {`, ...(blocks2.length > 0 ? blocks2 : [layer2.name]).map((block) => ` block ${ids(block)} ${quoted4(block)}`), "}", ""];
|
|
199574
200109
|
});
|
|
@@ -199622,13 +200157,13 @@ function stem(word2) {
|
|
|
199622
200157
|
return word2;
|
|
199623
200158
|
}
|
|
199624
200159
|
function keyOf4(text3) {
|
|
199625
|
-
return
|
|
200160
|
+
return wordsOf6(text3).map(stem).join(" ");
|
|
199626
200161
|
}
|
|
199627
200162
|
function wordPoints(texts) {
|
|
199628
200163
|
const strong = /* @__PURE__ */ new Map();
|
|
199629
200164
|
const weak = /* @__PURE__ */ new Map();
|
|
199630
200165
|
for (const { text: text3, weight } of texts) {
|
|
199631
|
-
const words2 =
|
|
200166
|
+
const words2 = wordsOf6(text3).map(stem);
|
|
199632
200167
|
const seen = /* @__PURE__ */ new Set();
|
|
199633
200168
|
for (let start2 = 0; start2 < words2.length; start2 += 1) {
|
|
199634
200169
|
let key = "";
|
|
@@ -199751,8 +200286,8 @@ var init_rank = __esm({
|
|
|
199751
200286
|
MEDIUM = 4;
|
|
199752
200287
|
INDEX = /* @__PURE__ */ new Map();
|
|
199753
200288
|
for (const intent of INTENTS) {
|
|
199754
|
-
for (const [
|
|
199755
|
-
for (const phrase2 of
|
|
200289
|
+
for (const [phrases2, isStrong] of [[intent.strong, true], [intent.weak, false]]) {
|
|
200290
|
+
for (const phrase2 of phrases2) INDEX.set(keyOf4(phrase2), [...INDEX.get(keyOf4(phrase2)) ?? [], { id: intent.id, isStrong }]);
|
|
199756
200291
|
}
|
|
199757
200292
|
}
|
|
199758
200293
|
LONGEST_PHRASE = Math.max(...[...INDEX.keys()].map((key) => key.split(" ").length));
|
|
@@ -200854,6 +201389,7 @@ var init_server_info = __esm({
|
|
|
200854
201389
|
"Set embedSource true on draw_diagram whenever you save an SVG into a repository, so the file carries its source and read_diagram can give it back next time; the source is then readable by anyone who has the file.",
|
|
200855
201390
|
...SAVING_INSTRUCTIONS,
|
|
200856
201391
|
'An item with no icon= gets the icon its label names when the match is certain, such as the Postgres mark on a node labelled "Postgres", so label items with the product they are; icon=none keeps one item plain and icons=off on the header keeps them all plain.',
|
|
201392
|
+
'For a finished look, label flow arrows with verbs ("reads", "publishes", "deploys to") so they draw icons, add role= (data, async, identity, private) to the lines that carry those, and give groups a type=; style in get_diagram_syntax says more.',
|
|
200857
201393
|
"Use map_icons to choose icons for many names at once; it never guesses, so choose from the candidates for an ambiguous name, and never invent an icon.",
|
|
200858
201394
|
"To move Mermaid to Plotwork, call convert_mermaid with one diagram, read every diagnostic and its hint, then choose node types and icons; for a whole Markdown file call sync_markdown with the document, its path, and convertMermaid true, write the returned markdown and files, then review the diff.",
|
|
200859
201395
|
"When the repository has a plotwork.config.json (or .plotwork/config.json) at its root, read it and pass it as settings to every tool that takes settings: its defaults fill the header options the source leaves out, and broken style rules come back as warnings to fix.",
|