@beechcms/cli 0.6.0-preview.1 → 0.6.0-preview.3

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.
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">57.89% </span>
26
+ <span class="strong">100% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>77/133</span>
28
+ <span class='fraction'>43/43</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">82.35% </span>
33
+ <span class="strong">77.77% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>28/34</span>
35
+ <span class='fraction'>14/18</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">50% </span>
40
+ <span class="strong">100% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>1/2</span>
42
+ <span class='fraction'>9/9</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">57.89% </span>
47
+ <span class="strong">100% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>77/133</span>
49
+ <span class='fraction'>35/35</span>
50
50
  </div>
51
51
 
52
52
 
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </template>
63
63
  </div>
64
- <div class='status-line medium'></div>
64
+ <div class='status-line high'></div>
65
65
  <pre><table class="coverage">
66
66
  <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
67
  <a name='L2'></a><a href='#L2'>2</a>
@@ -143,113 +143,10 @@
143
143
  <a name='L78'></a><a href='#L78'>78</a>
144
144
  <a name='L79'></a><a href='#L79'>79</a>
145
145
  <a name='L80'></a><a href='#L80'>80</a>
146
- <a name='L81'></a><a href='#L81'>81</a>
147
- <a name='L82'></a><a href='#L82'>82</a>
148
- <a name='L83'></a><a href='#L83'>83</a>
149
- <a name='L84'></a><a href='#L84'>84</a>
150
- <a name='L85'></a><a href='#L85'>85</a>
151
- <a name='L86'></a><a href='#L86'>86</a>
152
- <a name='L87'></a><a href='#L87'>87</a>
153
- <a name='L88'></a><a href='#L88'>88</a>
154
- <a name='L89'></a><a href='#L89'>89</a>
155
- <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a>
157
- <a name='L92'></a><a href='#L92'>92</a>
158
- <a name='L93'></a><a href='#L93'>93</a>
159
- <a name='L94'></a><a href='#L94'>94</a>
160
- <a name='L95'></a><a href='#L95'>95</a>
161
- <a name='L96'></a><a href='#L96'>96</a>
162
- <a name='L97'></a><a href='#L97'>97</a>
163
- <a name='L98'></a><a href='#L98'>98</a>
164
- <a name='L99'></a><a href='#L99'>99</a>
165
- <a name='L100'></a><a href='#L100'>100</a>
166
- <a name='L101'></a><a href='#L101'>101</a>
167
- <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a>
169
- <a name='L104'></a><a href='#L104'>104</a>
170
- <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a>
172
- <a name='L107'></a><a href='#L107'>107</a>
173
- <a name='L108'></a><a href='#L108'>108</a>
174
- <a name='L109'></a><a href='#L109'>109</a>
175
- <a name='L110'></a><a href='#L110'>110</a>
176
- <a name='L111'></a><a href='#L111'>111</a>
177
- <a name='L112'></a><a href='#L112'>112</a>
178
- <a name='L113'></a><a href='#L113'>113</a>
179
- <a name='L114'></a><a href='#L114'>114</a>
180
- <a name='L115'></a><a href='#L115'>115</a>
181
- <a name='L116'></a><a href='#L116'>116</a>
182
- <a name='L117'></a><a href='#L117'>117</a>
183
- <a name='L118'></a><a href='#L118'>118</a>
184
- <a name='L119'></a><a href='#L119'>119</a>
185
- <a name='L120'></a><a href='#L120'>120</a>
186
- <a name='L121'></a><a href='#L121'>121</a>
187
- <a name='L122'></a><a href='#L122'>122</a>
188
- <a name='L123'></a><a href='#L123'>123</a>
189
- <a name='L124'></a><a href='#L124'>124</a>
190
- <a name='L125'></a><a href='#L125'>125</a>
191
- <a name='L126'></a><a href='#L126'>126</a>
192
- <a name='L127'></a><a href='#L127'>127</a>
193
- <a name='L128'></a><a href='#L128'>128</a>
194
- <a name='L129'></a><a href='#L129'>129</a>
195
- <a name='L130'></a><a href='#L130'>130</a>
196
- <a name='L131'></a><a href='#L131'>131</a>
197
- <a name='L132'></a><a href='#L132'>132</a>
198
- <a name='L133'></a><a href='#L133'>133</a>
199
- <a name='L134'></a><a href='#L134'>134</a>
200
- <a name='L135'></a><a href='#L135'>135</a>
201
- <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a>
216
- <a name='L151'></a><a href='#L151'>151</a>
217
- <a name='L152'></a><a href='#L152'>152</a>
218
- <a name='L153'></a><a href='#L153'>153</a>
219
- <a name='L154'></a><a href='#L154'>154</a>
220
- <a name='L155'></a><a href='#L155'>155</a>
221
- <a name='L156'></a><a href='#L156'>156</a>
222
- <a name='L157'></a><a href='#L157'>157</a>
223
- <a name='L158'></a><a href='#L158'>158</a>
224
- <a name='L159'></a><a href='#L159'>159</a>
225
- <a name='L160'></a><a href='#L160'>160</a>
226
- <a name='L161'></a><a href='#L161'>161</a>
227
- <a name='L162'></a><a href='#L162'>162</a>
228
- <a name='L163'></a><a href='#L163'>163</a>
229
- <a name='L164'></a><a href='#L164'>164</a>
230
- <a name='L165'></a><a href='#L165'>165</a>
231
- <a name='L166'></a><a href='#L166'>166</a>
232
- <a name='L167'></a><a href='#L167'>167</a>
233
- <a name='L168'></a><a href='#L168'>168</a>
234
- <a name='L169'></a><a href='#L169'>169</a>
235
- <a name='L170'></a><a href='#L170'>170</a>
236
- <a name='L171'></a><a href='#L171'>171</a>
237
- <a name='L172'></a><a href='#L172'>172</a>
238
- <a name='L173'></a><a href='#L173'>173</a>
239
- <a name='L174'></a><a href='#L174'>174</a>
240
- <a name='L175'></a><a href='#L175'>175</a>
241
- <a name='L176'></a><a href='#L176'>176</a>
242
- <a name='L177'></a><a href='#L177'>177</a>
243
- <a name='L178'></a><a href='#L178'>178</a>
244
- <a name='L179'></a><a href='#L179'>179</a>
245
- <a name='L180'></a><a href='#L180'>180</a>
246
- <a name='L181'></a><a href='#L181'>181</a>
247
- <a name='L182'></a><a href='#L182'>182</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
146
+ <a name='L81'></a><a href='#L81'>81</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
248
147
  <span class="cline-any cline-neutral">&nbsp;</span>
249
148
  <span class="cline-any cline-neutral">&nbsp;</span>
250
- <span class="cline-any cline-yes">1x</span>
251
149
  <span class="cline-any cline-neutral">&nbsp;</span>
252
- <span class="cline-any cline-yes">1x</span>
253
150
  <span class="cline-any cline-neutral">&nbsp;</span>
254
151
  <span class="cline-any cline-neutral">&nbsp;</span>
255
152
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -262,175 +159,76 @@
262
159
  <span class="cline-any cline-neutral">&nbsp;</span>
263
160
  <span class="cline-any cline-neutral">&nbsp;</span>
264
161
  <span class="cline-any cline-neutral">&nbsp;</span>
265
- <span class="cline-any cline-yes">1x</span>
266
- <span class="cline-any cline-yes">8x</span>
267
162
  <span class="cline-any cline-neutral">&nbsp;</span>
268
163
  <span class="cline-any cline-neutral">&nbsp;</span>
269
- <span class="cline-any cline-yes">8x</span>
270
- <span class="cline-any cline-yes">15x</span>
271
- <span class="cline-any cline-yes">15x</span>
272
- <span class="cline-any cline-yes">24x</span>
273
- <span class="cline-any cline-yes">9x</span>
274
- <span class="cline-any cline-yes">1x</span>
275
- <span class="cline-any cline-yes">1x</span>
276
- <span class="cline-any cline-yes">1x</span>
277
- <span class="cline-any cline-yes">1x</span>
278
- <span class="cline-any cline-yes">9x</span>
279
- <span class="cline-any cline-yes">24x</span>
280
- <span class="cline-any cline-yes">15x</span>
281
- <span class="cline-any cline-yes">1x</span>
282
- <span class="cline-any cline-yes">1x</span>
283
- <span class="cline-any cline-yes">15x</span>
284
164
  <span class="cline-any cline-neutral">&nbsp;</span>
165
+ <span class="cline-any cline-yes">11x</span>
285
166
  <span class="cline-any cline-neutral">&nbsp;</span>
286
- <span class="cline-any cline-yes">8x</span>
287
- <span class="cline-any cline-yes">15x</span>
288
- <span class="cline-any cline-yes">15x</span>
289
- <span class="cline-any cline-yes">24x</span>
290
- <span class="cline-any cline-yes">5x</span>
167
+ <span class="cline-any cline-neutral">&nbsp;</span>
168
+ <span class="cline-any cline-neutral">&nbsp;</span>
169
+ <span class="cline-any cline-yes">4x</span>
170
+ <span class="cline-any cline-neutral">&nbsp;</span>
171
+ <span class="cline-any cline-yes">4x</span>
291
172
  <span class="cline-any cline-yes">1x</span>
292
173
  <span class="cline-any cline-yes">1x</span>
293
174
  <span class="cline-any cline-neutral">&nbsp;</span>
175
+ <span class="cline-any cline-neutral">&nbsp;</span>
176
+ <span class="cline-any cline-yes">3x</span>
177
+ <span class="cline-any cline-neutral">&nbsp;</span>
178
+ <span class="cline-any cline-yes">3x</span>
179
+ <span class="cline-any cline-yes">3x</span>
180
+ <span class="cline-any cline-yes">3x</span>
181
+ <span class="cline-any cline-neutral">&nbsp;</span>
182
+ <span class="cline-any cline-neutral">&nbsp;</span>
183
+ <span class="cline-any cline-yes">3x</span>
294
184
  <span class="cline-any cline-yes">1x</span>
295
185
  <span class="cline-any cline-yes">1x</span>
296
- <span class="cline-any cline-yes">5x</span>
297
- <span class="cline-any cline-yes">24x</span>
298
- <span class="cline-any cline-yes">15x</span>
299
- <span class="cline-any cline-yes">1x</span>
300
186
  <span class="cline-any cline-yes">1x</span>
301
- <span class="cline-any cline-yes">15x</span>
302
- <span class="cline-any cline-neutral">&nbsp;</span>
303
- <span class="cline-any cline-neutral">&nbsp;</span>
304
- <span class="cline-any cline-yes">8x</span>
305
- <span class="cline-any cline-yes">8x</span>
306
- <span class="cline-any cline-yes">8x</span>
307
- <span class="cline-any cline-yes">15x</span>
308
- <span class="cline-any cline-yes">15x</span>
309
- <span class="cline-any cline-yes">24x</span>
310
- <span class="cline-any cline-yes">5x</span>
311
- <span class="cline-any cline-yes">24x</span>
312
- <span class="cline-any cline-no">&nbsp;</span>
313
- <span class="cline-any cline-no">&nbsp;</span>
314
- <span class="cline-any cline-yes">24x</span>
315
- <span class="cline-any cline-no">&nbsp;</span>
316
- <span class="cline-any cline-no">&nbsp;</span>
317
- <span class="cline-any cline-yes">5x</span>
318
- <span class="cline-any cline-yes">5x</span>
319
- <span class="cline-any cline-yes">15x</span>
320
- <span class="cline-any cline-no">&nbsp;</span>
321
- <span class="cline-any cline-no">&nbsp;</span>
322
- <span class="cline-any cline-yes">15x</span>
323
- <span class="cline-any cline-yes">8x</span>
324
- <span class="cline-any cline-neutral">&nbsp;</span>
325
- <span class="cline-any cline-neutral">&nbsp;</span>
326
- <span class="cline-any cline-neutral">&nbsp;</span>
327
- <span class="cline-any cline-neutral">&nbsp;</span>
328
- <span class="cline-any cline-yes">8x</span>
329
- <span class="cline-any cline-yes">8x</span>
330
- <span class="cline-any cline-yes">6x</span>
331
- <span class="cline-any cline-yes">6x</span>
332
- <span class="cline-any cline-yes">6x</span>
187
+ <span class="cline-any cline-neutral">&nbsp;</span>
188
+ <span class="cline-any cline-neutral">&nbsp;</span>
189
+ <span class="cline-any cline-neutral">&nbsp;</span>
190
+ <span class="cline-any cline-neutral">&nbsp;</span>
191
+ <span class="cline-any cline-yes">3x</span>
192
+ <span class="cline-any cline-yes">3x</span>
193
+ <span class="cline-any cline-neutral">&nbsp;</span>
194
+ <span class="cline-any cline-yes">3x</span>
195
+ <span class="cline-any cline-yes">3x</span>
196
+ <span class="cline-any cline-yes">3x</span>
197
+ <span class="cline-any cline-yes">2x</span>
198
+ <span class="cline-any cline-neutral">&nbsp;</span>
199
+ <span class="cline-any cline-yes">2x</span>
200
+ <span class="cline-any cline-yes">2x</span>
201
+ <span class="cline-any cline-neutral">&nbsp;</span>
202
+ <span class="cline-any cline-neutral">&nbsp;</span>
333
203
  <span class="cline-any cline-yes">1x</span>
334
204
  <span class="cline-any cline-yes">1x</span>
335
205
  <span class="cline-any cline-yes">1x</span>
336
- <span class="cline-any cline-yes">6x</span>
337
206
  <span class="cline-any cline-neutral">&nbsp;</span>
338
207
  <span class="cline-any cline-neutral">&nbsp;</span>
339
- <span class="cline-any cline-yes">8x</span>
340
208
  <span class="cline-any cline-neutral">&nbsp;</span>
341
- <span class="cline-any cline-yes">8x</span>
342
- <span class="cline-any cline-yes">15x</span>
343
209
  <span class="cline-any cline-neutral">&nbsp;</span>
344
- <span class="cline-any cline-yes">15x</span>
345
- <span class="cline-any cline-no">&nbsp;</span>
346
- <span class="cline-any cline-no">&nbsp;</span>
347
- <span class="cline-any cline-yes">15x</span>
210
+ <span class="cline-any cline-yes">3x</span>
348
211
  <span class="cline-any cline-neutral">&nbsp;</span>
349
- <span class="cline-any cline-yes">15x</span>
350
- <span class="cline-any cline-yes">15x</span>
351
- <span class="cline-any cline-yes">24x</span>
352
- <span class="cline-any cline-no">&nbsp;</span>
353
- <span class="cline-any cline-no">&nbsp;</span>
354
- <span class="cline-any cline-yes">24x</span>
355
- <span class="cline-any cline-yes">24x</span>
212
+ <span class="cline-any cline-yes">3x</span>
213
+ <span class="cline-any cline-yes">3x</span>
356
214
  <span class="cline-any cline-neutral">&nbsp;</span>
357
- <span class="cline-any cline-yes">15x</span>
358
- <span class="cline-any cline-yes">15x</span>
215
+ <span class="cline-any cline-yes">3x</span>
359
216
  <span class="cline-any cline-yes">1x</span>
360
217
  <span class="cline-any cline-yes">1x</span>
361
- <span class="cline-any cline-neutral">&nbsp;</span>
362
- <span class="cline-any cline-yes">15x</span>
218
+ <span class="cline-any cline-yes">1x</span>
219
+ <span class="cline-any cline-yes">2x</span>
363
220
  <span class="cline-any cline-yes">1x</span>
364
221
  <span class="cline-any cline-yes">1x</span>
365
- <span class="cline-any cline-yes">15x</span>
366
- <span class="cline-any cline-neutral">&nbsp;</span>
367
- <span class="cline-any cline-yes">8x</span>
368
- <span class="cline-any cline-yes">8x</span>
369
- <span class="cline-any cline-neutral">&nbsp;</span>
370
- <span class="cline-any cline-no">&nbsp;</span>
371
- <span class="cline-any cline-no">&nbsp;</span>
372
- <span class="cline-any cline-neutral">&nbsp;</span>
373
- <span class="cline-any cline-no">&nbsp;</span>
374
- <span class="cline-any cline-no">&nbsp;</span>
375
- <span class="cline-any cline-no">&nbsp;</span>
376
- <span class="cline-any cline-no">&nbsp;</span>
377
- <span class="cline-any cline-neutral">&nbsp;</span>
378
- <span class="cline-any cline-no">&nbsp;</span>
379
- <span class="cline-any cline-neutral">&nbsp;</span>
380
- <span class="cline-any cline-no">&nbsp;</span>
381
- <span class="cline-any cline-no">&nbsp;</span>
382
- <span class="cline-any cline-no">&nbsp;</span>
383
- <span class="cline-any cline-neutral">&nbsp;</span>
384
- <span class="cline-any cline-neutral">&nbsp;</span>
385
- <span class="cline-any cline-no">&nbsp;</span>
386
- <span class="cline-any cline-no">&nbsp;</span>
387
- <span class="cline-any cline-no">&nbsp;</span>
388
- <span class="cline-any cline-no">&nbsp;</span>
389
- <span class="cline-any cline-no">&nbsp;</span>
390
- <span class="cline-any cline-no">&nbsp;</span>
391
- <span class="cline-any cline-neutral">&nbsp;</span>
392
- <span class="cline-any cline-neutral">&nbsp;</span>
393
- <span class="cline-any cline-no">&nbsp;</span>
394
- <span class="cline-any cline-no">&nbsp;</span>
395
- <span class="cline-any cline-neutral">&nbsp;</span>
396
- <span class="cline-any cline-no">&nbsp;</span>
397
- <span class="cline-any cline-no">&nbsp;</span>
398
- <span class="cline-any cline-no">&nbsp;</span>
399
- <span class="cline-any cline-no">&nbsp;</span>
400
- <span class="cline-any cline-neutral">&nbsp;</span>
401
- <span class="cline-any cline-no">&nbsp;</span>
402
- <span class="cline-any cline-no">&nbsp;</span>
403
- <span class="cline-any cline-no">&nbsp;</span>
404
- <span class="cline-any cline-no">&nbsp;</span>
405
- <span class="cline-any cline-no">&nbsp;</span>
406
- <span class="cline-any cline-no">&nbsp;</span>
407
- <span class="cline-any cline-no">&nbsp;</span>
408
- <span class="cline-any cline-no">&nbsp;</span>
409
- <span class="cline-any cline-no">&nbsp;</span>
410
- <span class="cline-any cline-no">&nbsp;</span>
411
- <span class="cline-any cline-neutral">&nbsp;</span>
412
- <span class="cline-any cline-no">&nbsp;</span>
413
- <span class="cline-any cline-neutral">&nbsp;</span>
414
- <span class="cline-any cline-no">&nbsp;</span>
415
- <span class="cline-any cline-no">&nbsp;</span>
416
- <span class="cline-any cline-neutral">&nbsp;</span>
417
- <span class="cline-any cline-no">&nbsp;</span>
418
- <span class="cline-any cline-no">&nbsp;</span>
419
- <span class="cline-any cline-no">&nbsp;</span>
420
- <span class="cline-any cline-no">&nbsp;</span>
421
- <span class="cline-any cline-no">&nbsp;</span>
422
- <span class="cline-any cline-no">&nbsp;</span>
423
- <span class="cline-any cline-no">&nbsp;</span>
424
- <span class="cline-any cline-no">&nbsp;</span>
425
- <span class="cline-any cline-no">&nbsp;</span>
426
- <span class="cline-any cline-no">&nbsp;</span>
427
- <span class="cline-any cline-no">&nbsp;</span>
222
+ <span class="cline-any cline-neutral">&nbsp;</span>
223
+ <span class="cline-any cline-yes">1x</span>
224
+ <span class="cline-any cline-neutral">&nbsp;</span>
225
+ <span class="cline-any cline-neutral">&nbsp;</span>
428
226
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">// SPDX-License-Identifier: MIT
429
227
  // Copyright (c) 2024–2026 Flavio De Musso
430
228
  &nbsp;
431
229
  import pc from 'picocolors'
432
230
  import type { Seed } from '@beechcms/core'
433
- import { SEED_REGISTRY, sortSeedsByDependencies } from '@beechcms/core'
231
+ import { SEED_REGISTRY, validateSeedDefinitions } from '@beechcms/core'
434
232
  &nbsp;
435
233
  export interface ValidateOptions {
436
234
  registry?: Record&lt;string, Seed&gt; | null
@@ -444,168 +242,67 @@ export interface SeedValidationError {
444
242
  }
445
243
  &nbsp;
446
244
  export function validateSeeds(registry: Record&lt;string, Seed&gt;): SeedValidationError[] {
447
- const result: SeedValidationError[] = []
448
- &nbsp;
449
- // ── Fatal check 1: unknown relation targets ──────────────────────────────
450
- for (const seed of Object.values(registry)) {
451
- const messages: string[] = []
452
- for (const branch of seed.branches) {
453
- if (branch.type === 'relation' &amp;&amp; branch.targetSeed) {
454
- if (!registry[branch.targetSeed]) {
455
- messages.push(
456
- `branch '${branch.alias}' targets unknown seed '${branch.targetSeed}'`,
457
- )
458
- }
459
- }
460
- }
461
- if (messages.length &gt; 0) {
462
- result.push({ slug: seed.slug, messages, fatal: true })
463
- }
464
- }
465
- &nbsp;
466
- // ── Fatal check 2: multi-relation with SET NULL ──────────────────────────
467
- for (const seed of Object.values(registry)) {
468
- const messages: string[] = []
469
- for (const branch of seed.branches) {
470
- if (branch.type === 'relation' &amp;&amp; branch.multiple === true) {
471
- if (branch.onDelete === 'SET NULL') {
472
- messages.push(
473
- `Branch '${branch.alias}': multi-relations cannot use ON DELETE SET NULL. ` +
474
- `Use 'CASCADE' or 'RESTRICT'.`,
475
- )
476
- }
477
- }
478
- }
479
- if (messages.length &gt; 0) {
480
- result.push({ slug: seed.slug, messages, fatal: true })
481
- }
482
- }
245
+ return validateSeedDefinitions(Object.values(registry))
246
+ }
483
247
  &nbsp;
484
- // ── Fatal check 3: junction table name collisions ────────────────────────
485
- {
486
- const junctionNames = new Set&lt;string&gt;()
487
- for (const seed of Object.values(registry)) {
488
- const messages: string[] = []
489
- for (const branch of seed.branches) {
490
- if (branch.type !== 'relation' || branch.multiple !== true) continue
491
- const name = `rel_${seed.slug}_${branch.alias}`
492
- if (name.length &gt; 256) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
493
- <span class="cstat-no" title="statement not covered" > messages.push(`Junction table name '${name}' exceeds 256 characters (${name.length})`)</span>
494
- <span class="cstat-no" title="statement not covered" > }</span>
495
- if (junctionNames.has(name)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
496
- <span class="cstat-no" title="statement not covered" > messages.push(`Junction table name collision: '${name}' already used by another seed/branch`)</span>
497
- <span class="cstat-no" title="statement not covered" > }</span>
498
- junctionNames.add(name)
499
- }
500
- if (messages.length &gt; 0) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
501
- <span class="cstat-no" title="statement not covered" > result.push({ slug: seed.slug, messages, fatal: true })</span>
502
- <span class="cstat-no" title="statement not covered" > }</span>
503
- }
504
- }
248
+ export async function validate(args: ValidateOptions): Promise&lt;void&gt; {
249
+ const registry = args.registry ?? <span class="branch-1 cbranch-no" title="branch not covered" >SEED_REGISTRY</span>
505
250
  &nbsp;
506
- // ── Fatal check 4: dependency cycles ────────────────────────────────────
507
- // Skip if unknown targets were found sortSeedsByDependencies would throw
508
- // on the same unknown targets, producing duplicate fatal messages.
509
- const hasUnknownTargets = result.some(e =&gt; e.fatal)
510
- if (!hasUnknownTargets) {
511
- try {
512
- sortSeedsByDependencies(Object.values(registry))
513
- } catch (err) {
514
- const msg = err instanceof Error ? err.<span class="branch-0 cbranch-no" title="branch not covered" >message : String(err)</span>
515
- result.push({ slug: '&lt;graph&gt;', messages: [msg], fatal: true })
516
- }
251
+ if (Object.keys(registry).length === 0) {
252
+ console.warn(pc.yellow('\n Warning: SEED_REGISTRY is empty. Create a seeds.ts in your project root.\n'))
253
+ return
517
254
  }
518
255
  &nbsp;
519
- // ── Warning checks (existing) ────────────────────────────────────────────
520
- const slugsSeen = new Set&lt;string&gt;()
521
- &nbsp;
522
- for (const seed of Object.values(registry)) {
523
- const messages: string[] = []
524
- &nbsp;
525
- if (slugsSeen.has(seed.slug)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
526
- <span class="cstat-no" title="statement not covered" > messages.push(`duplicate slug "${seed.slug}" — each seed must have a unique slug`)</span>
527
- <span class="cstat-no" title="statement not covered" > }</span>
528
- slugsSeen.add(seed.slug)
529
- &nbsp;
530
- const aliasesSeen = new Set&lt;string&gt;()
531
- for (const branch of seed.branches) {
532
- if (aliasesSeen.has(branch.alias)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
533
- <span class="cstat-no" title="statement not covered" > messages.push(`duplicate branch alias "${branch.alias}"`)</span>
534
- <span class="cstat-no" title="statement not covered" > }</span>
535
- aliasesSeen.add(branch.alias)
536
- }
256
+ console.log(pc.cyan('\n beech validate checking seeds\n'))
537
257
  &nbsp;
538
- const allAliases = new Set(seed.branches.map(b =&gt; b.alias))
539
- if (!allAliases.has(seed.displayNameAlias)) {
540
- messages.push(`displayNameAlias "${seed.displayNameAlias}" not found in branches`)
541
- }
258
+ const errors = validateSeeds(registry)
259
+ const fatalErrors = errors.filter(e =&gt; e.fatal)
260
+ const warnings = errors.filter(e =&gt; !e.fatal)
542
261
  &nbsp;
543
- if (messages.length &gt; 0) {
544
- result.push({ slug: seed.slug, messages, fatal: false })
262
+ // Print fatal errors first
263
+ for (const e of fatalErrors) {
264
+ console.log(pc.red(` ✗ ${e.slug} (fatal)`))
265
+ for (const msg of e.messages) {
266
+ console.log(pc.red(` → ${msg}`))
545
267
  }
546
268
  }
547
- &nbsp;
548
- return result
549
- }
550
- &nbsp;
551
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function validate(args: ValidateOptions): Promise&lt;void&gt; {</span></span>
552
- <span class="cstat-no" title="statement not covered" > const registry = args.registry ?? SEED_REGISTRY</span>
553
- &nbsp;
554
- <span class="cstat-no" title="statement not covered" > if (Object.keys(registry).length === 0) {</span>
555
- <span class="cstat-no" title="statement not covered" > console.warn(pc.yellow('\n Warning: SEED_REGISTRY is empty. Create a seeds.ts in your project root.\n'))</span>
556
- <span class="cstat-no" title="statement not covered" > return</span>
557
- <span class="cstat-no" title="statement not covered" > }</span>
558
- &nbsp;
559
- <span class="cstat-no" title="statement not covered" > console.log(pc.cyan('\n beech validate — checking seeds\n'))</span>
560
- &nbsp;
561
- <span class="cstat-no" title="statement not covered" > const errors = validateSeeds(registry)</span>
562
- <span class="cstat-no" title="statement not covered" > const fatalErrors = errors.filter(e =&gt; e.fatal)</span>
563
- <span class="cstat-no" title="statement not covered" > const warnings = errors.filter(e =&gt; !e.fatal)</span>
564
- &nbsp;
565
- // Print fatal errors first
566
- <span class="cstat-no" title="statement not covered" > for (const e of fatalErrors) {</span>
567
- <span class="cstat-no" title="statement not covered" > console.log(pc.red(` ✗ ${e.slug} (fatal)`))</span>
568
- <span class="cstat-no" title="statement not covered" > for (const msg of e.messages) {</span>
569
- <span class="cstat-no" title="statement not covered" > console.log(pc.red(` → ${msg}`))</span>
570
- <span class="cstat-no" title="statement not covered" > }</span>
571
- <span class="cstat-no" title="statement not covered" > }</span>
572
269
  &nbsp;
573
270
  // Print per-seed warnings
574
- <span class="cstat-no" title="statement not covered" > const warningMap = new Map(warnings.map(e =&gt; [e.slug, e.messages]))</span>
575
- <span class="cstat-no" title="statement not covered" > const allWarningSlugsSeen = new Set(warnings.map(e =&gt; e.slug))</span>
271
+ const warningMap = new Map(warnings.map(e =&gt; [e.slug, e.messages]))
272
+ const allWarningSlugsSeen = new Set(warnings.map(e =&gt; e.slug))
576
273
  &nbsp;
577
- <span class="cstat-no" title="statement not covered" > for (const seed of Object.values(registry)) {</span>
578
- <span class="cstat-no" title="statement not covered" > const msgs = warningMap.get(seed.slug)</span>
579
- <span class="cstat-no" title="statement not covered" > if (!msgs) {</span>
580
- <span class="cstat-no" title="statement not covered" > if (!allWarningSlugsSeen.has(seed.slug)) {</span>
274
+ for (const seed of Object.values(registry)) {
275
+ const msgs = warningMap.get(seed.slug)
276
+ if (!msgs) {
277
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (!allWarningSlugsSeen.has(seed.slug)) {
581
278
  // only print ✓ if no fatal error for this slug either
582
- <span class="cstat-no" title="statement not covered" > const hasFatal = fatalErrors.some(e =&gt; e.slug === seed.slug)</span>
583
- <span class="cstat-no" title="statement not covered" > if (!hasFatal) console.log(pc.green(` ✓ ${seed.slug}`))</span>
584
- <span class="cstat-no" title="statement not covered" > }</span>
585
- <span class="cstat-no" title="statement not covered" > } else {</span>
586
- <span class="cstat-no" title="statement not covered" > console.log(pc.yellow(` ⚠ ${seed.slug}`))</span>
587
- <span class="cstat-no" title="statement not covered" > for (const msg of msgs) {</span>
588
- <span class="cstat-no" title="statement not covered" > console.log(pc.yellow(` → ${msg}`))</span>
589
- <span class="cstat-no" title="statement not covered" > }</span>
590
- <span class="cstat-no" title="statement not covered" > }</span>
591
- <span class="cstat-no" title="statement not covered" > }</span>
279
+ const hasFatal = fatalErrors.some(e =&gt; e.slug === seed.slug)
280
+ if (!hasFatal) console.log(pc.green(` ✓ ${seed.slug}`))
281
+ }
282
+ } else {
283
+ console.log(pc.yellow(` ⚠ ${seed.slug}`))
284
+ for (const msg of msgs) {
285
+ console.log(pc.yellow(` → ${msg}`))
286
+ }
287
+ }
288
+ }
592
289
  &nbsp;
593
- <span class="cstat-no" title="statement not covered" > console.log('')</span>
290
+ console.log('')
594
291
  &nbsp;
595
- <span class="cstat-no" title="statement not covered" > const totalFatal = fatalErrors.reduce((n, e) =&gt; n + e.messages.length, 0)</span>
596
- <span class="cstat-no" title="statement not covered" > const totalWarnings = warnings.reduce((n, e) =&gt; n + e.messages.length, 0)</span>
292
+ const totalFatal = fatalErrors.reduce((n, e) =&gt; n + e.messages.length, 0)
293
+ const totalWarnings = warnings.reduce((n, e) =&gt; n + e.messages.length, 0)
597
294
  &nbsp;
598
- <span class="cstat-no" title="statement not covered" > if (totalFatal &gt; 0) {</span>
599
- <span class="cstat-no" title="statement not covered" > const s = totalFatal !== 1 ? 's' : ''</span>
600
- <span class="cstat-no" title="statement not covered" > console.log(pc.red(` Found ${totalFatal} fatal error${s}. Fix before loading.\n`))</span>
601
- <span class="cstat-no" title="statement not covered" > process.exit(1)</span>
602
- <span class="cstat-no" title="statement not covered" > } else if (totalWarnings &gt; 0) {</span>
603
- <span class="cstat-no" title="statement not covered" > const s = totalWarnings !== 1 ? 's' : ''</span>
604
- <span class="cstat-no" title="statement not covered" > console.log(pc.yellow(` Found ${totalWarnings} warning${s}. Review seeds above.\n`))</span>
605
- <span class="cstat-no" title="statement not covered" > } else {</span>
606
- <span class="cstat-no" title="statement not covered" > console.log(pc.green(' All seeds valid.\n'))</span>
607
- <span class="cstat-no" title="statement not covered" > }</span>
608
- <span class="cstat-no" title="statement not covered" >}</span>
295
+ if (totalFatal &gt; 0) {
296
+ const s = totalFatal !== 1 ? <span class="branch-0 cbranch-no" title="branch not covered" >'s' : '</span>'
297
+ console.log(pc.red(` Found ${totalFatal} fatal error${s}. Fix before loading.\n`))
298
+ process.exit(1)
299
+ } else if (totalWarnings &gt; 0) {
300
+ const s = totalWarnings !== 1 ? <span class="branch-0 cbranch-no" title="branch not covered" >'s' : '</span>'
301
+ console.log(pc.yellow(` Found ${totalWarnings} warning${s}. Review seeds above.\n`))
302
+ } else {
303
+ console.log(pc.green(' All seeds valid.\n'))
304
+ }
305
+ }
609
306
  &nbsp;</pre></td></tr></table></pre>
610
307
 
611
308
  <div class='push'></div><!-- for sticky footer -->
@@ -613,7 +310,7 @@ export function validateSeeds(registry: Record&lt;string, Seed&gt;): SeedValidat
613
310
  <div class='footer quiet pad2 space-top1 center small'>
614
311
  Code coverage generated by
615
312
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
616
- at 2026-06-03T22:56:37.415Z
313
+ at 2026-06-12T11:07:37.845Z
617
314
  </div>
618
315
  <script src="prettify.js"></script>
619
316
  <script>
@@ -0,0 +1,8 @@
1
+ export interface SeedLoadOptions {
2
+ dryRun: boolean;
3
+ diff: boolean;
4
+ local: boolean;
5
+ db?: string;
6
+ }
7
+ export declare function seedLoad(args: SeedLoadOptions): Promise<void>;
8
+ //# sourceMappingURL=seed-load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed-load.d.ts","sourceRoot":"","sources":["../../src/commands/seed-load.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAiFD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAenE"}