@cardenelabs/cdl 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/validate.ts CHANGED
@@ -5,6 +5,20 @@ import { nodeTemplateTexts } from "./render/template-fields";
5
5
  import { derivedRefIds } from "./render/derived-values";
6
6
 
7
7
  const TONES = new Set<string>(TONE_NAMES);
8
+
9
+ /**
10
+ * phase の `draw` が効く kind (cdl#512 / cdl#516)。
11
+ *
12
+ * **一覧を 1 箇所で持つ**。 知らせの文面もここから組み立てる = 対応種別が増えた時に
13
+ * 片方だけ古くなる形を作らない。
14
+ *
15
+ * | kind | 起点 | 動き |
16
+ * |---|---|---|
17
+ * | `chart-line` | 左端 | 線が右へ伸びる |
18
+ * | `chart-bar` | 横軸 | 棒が上へ伸びる |
19
+ * | `chart-pie` | 12 時 | 扇が時計回りに開く |
20
+ */
21
+ export const DRAW_KINDS: ReadonlySet<string> = new Set(["chart-line", "chart-bar", "chart-pie"]);
8
22
  const KINDS = new Set<string>(NODE_KINDS);
9
23
  const ENG_BANNED = /\b(FUNCTION|STORAGE|EVENT LOG|BALANCES MAPPING|READ|WRITE|EMIT|CALL)\b/;
10
24
 
@@ -108,7 +122,7 @@ export function validate(diag: CdlDiagram): void {
108
122
  ]);
109
123
 
110
124
  // 「もしかして」 サジェスト (typo 検出): edit distance 1 で最も近い候補 1 件
111
- const suggest = (target: string, candidates: Set<string>): string => {
125
+ const suggest = (target: string, candidates: Set<string>, candidateKind: "lane" | "node" = "lane"): string => {
112
126
  const list = [...candidates];
113
127
  if (list.length === 0) return "";
114
128
  let best = "";
@@ -120,7 +134,7 @@ export function validate(diag: CdlDiagram): void {
120
134
  best = c;
121
135
  }
122
136
  }
123
- return bestD <= 2 ? ` (もしかして "${best}"?)` : ` (定義済 lane: ${list.slice(0, 5).join(", ")}${list.length > 5 ? "..." : ""})`;
137
+ return bestD <= 2 ? ` (もしかして "${best}"?)` : ` (定義済 ${candidateKind}: ${list.slice(0, 5).join(", ")}${list.length > 5 ? "..." : ""})`;
124
138
  };
125
139
  for (const n of diag.nodes) {
126
140
  if (!laneIds.has(n.lane)) {
@@ -132,12 +146,12 @@ export function validate(diag: CdlDiagram): void {
132
146
  for (const e of diag.edges) {
133
147
  if (!nodeIds.has(e.from)) {
134
148
  errors.push(
135
- `[cdl] unknown-ref: edge "${e.id}" の from "${e.from}" が node に存在しません${suggest(e.from, nodeIds)}\n → 修正例: .node("${e.from}", { lane: "...", stack: 0, kind: "actor", title: "..." }) を edge 宣言前に追加`,
149
+ `[cdl] unknown-ref: edge "${e.id}" の from "${e.from}" が node に存在しません${suggest(e.from, nodeIds, "node")}\n → 修正例: .node("${e.from}", { lane: "...", stack: 0, kind: "actor", title: "..." }) を edge 宣言前に追加`,
136
150
  );
137
151
  }
138
152
  if (!nodeIds.has(e.to)) {
139
153
  errors.push(
140
- `[cdl] unknown-ref: edge "${e.id}" の to "${e.to}" が node に存在しません${suggest(e.to, nodeIds)}\n → 修正例: .node("${e.to}", { lane: "...", stack: 0, kind: "...", title: "..." }) を edge 宣言前に追加`,
154
+ `[cdl] unknown-ref: edge "${e.id}" の to "${e.to}" が node に存在しません${suggest(e.to, nodeIds, "node")}\n → 修正例: .node("${e.to}", { lane: "...", stack: 0, kind: "...", title: "..." }) を edge 宣言前に追加`,
141
155
  );
142
156
  }
143
157
  if (e.from === e.to) {
@@ -156,6 +170,22 @@ export function validate(diag: CdlDiagram): void {
156
170
  errors.push(`[cdl] unknown-ref: phase "${p.id}" の activate "${id}" は node でも edge でもない (typo の可能性)`);
157
171
  }
158
172
  }
173
+ // 描き始める対象は node に限る (cdl#512)。 edge は `activate` された phase で自分から
174
+ // 伸びるため (`render/edges.tsx` の `SolidEdgePath`)、 `draw` で指す相手にならない
175
+ for (const id of p.draw ?? []) {
176
+ if (!nodeIds.has(id)) {
177
+ errors.push(`[cdl] unknown-ref: phase "${p.id}" の draw "${id}" は node ではない (typo の可能性)${suggest(id, nodeIds, "node")}`);
178
+ continue;
179
+ }
180
+ // 描き方を持たない種別を指しても図は出るが、 書いた指定は何もしない。
181
+ // 黙って捨てると「書いたのに伸びない」 が手掛かりなしで起きる
182
+ const kind = diag.nodes.find((n) => n.id === id)?.kind;
183
+ if (!DRAW_KINDS.has(String(kind))) {
184
+ warnings.push(
185
+ `phase "${p.id}" の draw "${id}" は kind "${kind}" で、 起点から描く動きを持たない (対象は ${[...DRAW_KINDS].join(" / ")})`,
186
+ );
187
+ }
188
+ }
159
189
  for (const t of p.tweens) {
160
190
  if (!stateIds.has(t.stateId)) {
161
191
  errors.push(`[cdl] unknown-ref: phase "${p.id}" tween 対象 state "${t.stateId}" 未定義`);