synthesisui 0.16.384 → 0.16.386
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/align.js +28 -5
- package/dist/commands/component.js +72 -8
- package/dist/commands/doctor.js +24 -1
- package/package.json +1 -1
package/dist/commands/align.js
CHANGED
|
@@ -278,6 +278,8 @@ opts = {}) {
|
|
|
278
278
|
? "This run measured the app, and that reading is still on this machine - the platform keeps scoring the previous one until you send it."
|
|
279
279
|
: `${events.length} checked write${events.length === 1 ? "" : "s"} recorded here and not sent - the platform is scoring this repo on older evidence.`,
|
|
280
280
|
run: "npx synthesisui sync",
|
|
281
|
+
/** Ver `Misalignment.fromThisRun`: o cabeçalho lê daqui, e não reimplementa a pergunta. */
|
|
282
|
+
fromThisRun: allFromThisRun,
|
|
281
283
|
});
|
|
282
284
|
}
|
|
283
285
|
/**
|
|
@@ -570,12 +572,33 @@ export function describeMisalignments(items,
|
|
|
570
572
|
from = "session") {
|
|
571
573
|
if (items.length === 0)
|
|
572
574
|
return "";
|
|
575
|
+
/**
|
|
576
|
+
* "STILL OUT OF ALIGNMENT" SOBRE O QUE O PRÓPRIO COMANDO ACABOU DE PRODUZIR - achado do dono em
|
|
577
|
+
* 06/09, e ele o descreveu na hora: *"depois do upgrade (pediu o sync novamente)"*.
|
|
578
|
+
*
|
|
579
|
+
* O QUE ELE VIU: o `sync` disse que as regras mudaram e mandou rodar `upgrade`. O `upgrade`
|
|
580
|
+
* materializou, MEDIU o app - e a medição nova é evidência que ainda não subiu -, então fechou
|
|
581
|
+
* dizendo "Still out of alignment" e mandou rodar `sync`. Dois comandos apontando um para o
|
|
582
|
+
* outro, com um cabeçalho que afirma que algo continua errado.
|
|
583
|
+
*
|
|
584
|
+
* NÃO É LOOP: o segundo `sync` fecha, porque o que falta é enviar o que este `upgrade` acabou de
|
|
585
|
+
* medir. Mas isso não está em lugar nenhum da tela, e quem lê não tem como distinguir progresso
|
|
586
|
+
* de giro - a diferença entre as duas é a única coisa que decide se ele roda de novo ou desiste.
|
|
587
|
+
*
|
|
588
|
+
* A INFORMAÇÃO JÁ EXISTIA UMA LINHA ABAIXO. `allFromThisRun` distingue "havia evidência velha
|
|
589
|
+
* parada aqui" de "esta execução acabou de medir", e a frase do item já diz *"This run measured
|
|
590
|
+
* the app"*. Só o CABEÇALHO tratava os dois casos como o mesmo. Quando todo achado é consequência
|
|
591
|
+
* desta execução, ele passa a dizer o que a próxima linha resolve - e não que algo falhou.
|
|
592
|
+
*/
|
|
593
|
+
const consequencia = from === "after" && items.every((i) => i.fromThisRun === true);
|
|
573
594
|
return [
|
|
574
|
-
|
|
575
|
-
? "
|
|
576
|
-
: from === "
|
|
577
|
-
? "
|
|
578
|
-
:
|
|
595
|
+
consequencia
|
|
596
|
+
? "One step left, and it closes what this run produced:"
|
|
597
|
+
: from === "after"
|
|
598
|
+
? "Still out of alignment:"
|
|
599
|
+
: from === "shell"
|
|
600
|
+
? "This repo is out of alignment with the design system that governs it:"
|
|
601
|
+
: "Before this session starts, this environment is out of alignment with the design system that governs it:",
|
|
579
602
|
...grouped(items),
|
|
580
603
|
].join("\n");
|
|
581
604
|
}
|
|
@@ -169,7 +169,29 @@ export async function component(slug, name, opts) {
|
|
|
169
169
|
*/
|
|
170
170
|
const theirs = res.recipe?.api;
|
|
171
171
|
const already = theirs?.file && existsSync(join(root, theirs.file)) ? theirs : null;
|
|
172
|
-
|
|
172
|
+
/**
|
|
173
|
+
* UM NOME PRÓPRIO JÁ É A RESPOSTA PARA A COLISÃO - achado do dono em 06/09, e é a SEGUNDA volta
|
|
174
|
+
* deste mesmo defeito.
|
|
175
|
+
*
|
|
176
|
+
* O QUE ELE FEZ: `component codelevel button --as=ButtonSample`, no repositório de onde o
|
|
177
|
+
* sistema foi importado. A recusa disparou, disse *"writing another one would leave you with
|
|
178
|
+
* two"* e ofereceu `--force` - com um `--as` na linha de comando, ignorado.
|
|
179
|
+
*
|
|
180
|
+
* OS DOIS ERROS DE UMA VEZ. O primeiro é a decisão: este guard responde "você já tem" sem
|
|
181
|
+
* nunca ler `opts.as`, embora `localName` - a função que resolve o nome - fique 70 linhas
|
|
182
|
+
* abaixo. O segundo é a frase: com um nome próprio NÃO ficariam dois `Button`; ficaria o dele
|
|
183
|
+
* e um `ButtonSample`. E a única saída oferecida, `--force`, escreve com o nome ORIGINAL - a
|
|
184
|
+
* única opção que de fato causaria a duplicação que a mensagem existe para evitar.
|
|
185
|
+
*
|
|
186
|
+
* A PRIMEIRA VOLTA está registrada em `component-as.spec.ts`: a recusa IMPRIMIA `--as` e a
|
|
187
|
+
* flag não existia em `ComponentOptions`. A flag nasceu; o guard não passou a consultá-la.
|
|
188
|
+
*
|
|
189
|
+
* E A POPULAÇÃO É O CLIENTE-ALVO INTEIRO. Medido na base viva em 06/09: no `codelevel`, **64
|
|
190
|
+
* dos 66** componentes (97%) apontam para um arquivo que existe no repositório dele - porque o
|
|
191
|
+
* sistema NASCEU dali. Nos 25 sistemas gerados aqui, **0 de ~45**. O comando funcionava para
|
|
192
|
+
* quem não é o cliente e recusava para quem é.
|
|
193
|
+
*/
|
|
194
|
+
if (already && !opts.force && !opts.as?.trim()) {
|
|
173
195
|
console.log(section("You already have this component"));
|
|
174
196
|
console.log(body(`\`${already.name}\` lives in ${already.file} - writing another one would leave you with two.`));
|
|
175
197
|
if (already.from) {
|
|
@@ -180,14 +202,44 @@ export async function component(slug, name, opts) {
|
|
|
180
202
|
console.log(body(`It is not re-exported from that folder's entry, so import it by path.`));
|
|
181
203
|
}
|
|
182
204
|
console.log("");
|
|
183
|
-
|
|
205
|
+
/**
|
|
206
|
+
* A SAÍDA QUE NÃO DUPLICA VEM PRIMEIRO, e ela é a que a pessoa quer em quase todo caso.
|
|
207
|
+
*
|
|
208
|
+
* `--force` continua existindo e continua last: ele escreve com o nome DELE, que é a única
|
|
209
|
+
* opção que realmente deixa dois. Oferecê-lo como única saída era mandar a pessoa fazer
|
|
210
|
+
* exatamente o que a frase acima diz para evitar.
|
|
211
|
+
*/
|
|
212
|
+
console.log(body(`To see what this recipe produces without touching your file, give it a name of its own:`));
|
|
213
|
+
console.log("");
|
|
214
|
+
console.log(snippet([
|
|
215
|
+
`npx synthesisui@latest component ${slug} ${res.name} --as ${res.name}-sample`,
|
|
216
|
+
]));
|
|
217
|
+
console.log("");
|
|
218
|
+
console.log(body("The recipe and the compiled CSS are on disk either way - only the .tsx was not written. Pass --force to overwrite yours instead."));
|
|
184
219
|
return;
|
|
185
220
|
}
|
|
186
|
-
|
|
221
|
+
/**
|
|
222
|
+
* A COLISÃO SE MEDE PELO NOME QUE VAI SER ESCRITO, e não pelo do blueprint.
|
|
223
|
+
*
|
|
224
|
+
* A metade que o guard acima não resolvia sozinha: passado o primeiro guard com `--as`, este
|
|
225
|
+
* procurava por `button`/`Button` - o nome do BLUEPRINT - e achava o componente dele de novo.
|
|
226
|
+
* Consertar um e deixar o outro deixaria o `--as` aceito e barrado uma linha depois, o que é
|
|
227
|
+
* pior que recusar de cara: a pessoa faz o que a tela mandou e recebe outra recusa.
|
|
228
|
+
*
|
|
229
|
+
* `local` já era calculado, 70 linhas abaixo, para decidir a PASTA. Ele sobe para cá porque é
|
|
230
|
+
* a mesma pergunta - qual nome este comando vai ocupar - e duas respostas para ela é o defeito.
|
|
231
|
+
*/
|
|
232
|
+
const local = localName(res.name, opts.as);
|
|
233
|
+
const localPascal = local
|
|
234
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
235
|
+
.filter(Boolean)
|
|
236
|
+
.map((p) => p[0].toUpperCase() + p.slice(1))
|
|
237
|
+
.join("");
|
|
238
|
+
const clash = await findCollision(root, config.componentsDir, local, localPascal);
|
|
187
239
|
if (!opts.force && (clash.exported || (clash.file && !clash.ours))) {
|
|
188
240
|
console.log(section("This name is already taken in your project"));
|
|
189
241
|
if (clash.exported) {
|
|
190
|
-
console.log(body(`\`${
|
|
242
|
+
console.log(body(`\`${localPascal}\` is already exported from ${clash.exported}.`));
|
|
191
243
|
}
|
|
192
244
|
if (clash.file && !clash.ours) {
|
|
193
245
|
console.log(body(`${clash.file} exists and we did not write it.`));
|
|
@@ -211,7 +263,7 @@ export async function component(slug, name, opts) {
|
|
|
211
263
|
* componente. O CSS não muda de nome: a receita é a do blueprint, e as classes dela são
|
|
212
264
|
* `.ds-<blueprint>` - o componente novo veste o mesmo desenho, com o nome dele no arquivo.
|
|
213
265
|
*/
|
|
214
|
-
|
|
266
|
+
/** Ver o cálculo acima: uma resposta só para "qual nome este comando ocupa". */
|
|
215
267
|
const compDir = join(root, config.componentsDir, local);
|
|
216
268
|
await mkdir(compDir, { recursive: true });
|
|
217
269
|
let filenames;
|
|
@@ -307,7 +359,19 @@ export async function component(slug, name, opts) {
|
|
|
307
359
|
console.log(body(`(If you haven't installed the system yet, run: synthesisui add ${slug})`));
|
|
308
360
|
console.log(section("Use it"));
|
|
309
361
|
if (!opts.artifactsOnly && config.target === "next") {
|
|
310
|
-
|
|
362
|
+
/**
|
|
363
|
+
* O EXEMPLO APONTA PARA O QUE FOI ESCRITO - a terceira metade do defeito do `--as` (06/09).
|
|
364
|
+
*
|
|
365
|
+
* Este bloco derivava o nome e o caminho de `res.name`, o nome do BLUEPRINT. Com
|
|
366
|
+
* `--as button-sample`, o arquivo vai para `components/button-sample/` e o exemplo mandava
|
|
367
|
+
* importar de `components/button` - um caminho que não existe. Um comando que escreve certo e
|
|
368
|
+
* instrui errado é pior que um que recusa: a pessoa copia a linha e o build quebra.
|
|
369
|
+
*
|
|
370
|
+
* `localName` é a mesma função dos dois guards acima. Uma resposta só para o nome, do primeiro
|
|
371
|
+
* guard até a última linha impressa.
|
|
372
|
+
*/
|
|
373
|
+
const usedName = localName(res.name, opts.as);
|
|
374
|
+
const pascalName = usedName
|
|
311
375
|
.split(/[^a-zA-Z0-9]+/)
|
|
312
376
|
.filter(Boolean)
|
|
313
377
|
.map((p) => p[0].toUpperCase() + p.slice(1))
|
|
@@ -318,7 +382,7 @@ export async function component(slug, name, opts) {
|
|
|
318
382
|
? ` ${firstAxis[0]}="${Object.keys(firstAxis[1])[0]}"`
|
|
319
383
|
: "";
|
|
320
384
|
console.log(snippet([
|
|
321
|
-
`import { ${pascalName} } from "@/${config.componentsDir}/${
|
|
385
|
+
`import { ${pascalName} } from "@/${config.componentsDir}/${usedName}";`,
|
|
322
386
|
"",
|
|
323
387
|
`<${pascalName}${exampleProp} />`,
|
|
324
388
|
]));
|
|
@@ -327,7 +391,7 @@ export async function component(slug, name, opts) {
|
|
|
327
391
|
console.log("");
|
|
328
392
|
console.log(body("Or ask your agent:"));
|
|
329
393
|
console.log(snippet([
|
|
330
|
-
`"Use the ${pascalName} component from ${config.componentsDir}/${
|
|
394
|
+
`"Use the ${pascalName} component from ${config.componentsDir}/${usedName} (SynthesisUI ${slug})."`,
|
|
331
395
|
]));
|
|
332
396
|
}
|
|
333
397
|
else {
|
package/dist/commands/doctor.js
CHANGED
|
@@ -22,6 +22,7 @@ import { actingSlug, describeScope, measuredScope, scopePaths, } from "../measur
|
|
|
22
22
|
import { body, paint, section, snippet } from "../output.js";
|
|
23
23
|
import { resolveDeps } from "../stack.js";
|
|
24
24
|
import { danglingTheirVars } from "../their-vars.js";
|
|
25
|
+
import { wiringPrompt } from "../wiring-prompt.js";
|
|
25
26
|
/**
|
|
26
27
|
* `synthesisui doctor` - the check nobody else ships.
|
|
27
28
|
*
|
|
@@ -995,7 +996,29 @@ export async function doctor(opts) {
|
|
|
995
996
|
console.log(body("are declared and nothing points at them, so the page renders in"));
|
|
996
997
|
console.log(body("whatever the framework picked."));
|
|
997
998
|
}
|
|
998
|
-
|
|
999
|
+
/**
|
|
1000
|
+
* A FIAÇÃO SAI DAQUI, e não de outro comando - achado do dono em 06/09, rodando o `upgrade`.
|
|
1001
|
+
*
|
|
1002
|
+
* O QUE ELE VIU: o doctor diz `installed - but not wired up yet` e *"none of the 66 tokens
|
|
1003
|
+
* reach the browser"*, e a linha seguinte mandava ler *"the output of `init`"*. `init` é o
|
|
1004
|
+
* comando de PRIMEIRA VEZ - ele instala um sistema em quem não tem nenhum. Quem chegou até
|
|
1005
|
+
* aqui já importou, materializou e rodou upgrade: mandá-lo ao `init` é devolver ao começo
|
|
1006
|
+
* alguém que está a um passo do fim.
|
|
1007
|
+
*
|
|
1008
|
+
* E O PASSO JÁ EXISTIA PRONTO. `wiringPrompt` mora em `wiring-prompt.ts`, exportado, e era
|
|
1009
|
+
* usado só pelo `init`. Imprimi-lo aqui não é texto novo: é a MESMA fonte chegando na tela
|
|
1010
|
+
* onde a pergunta nasce. Duas redações do mesmo passo divergiriam no primeiro conserto.
|
|
1011
|
+
*
|
|
1012
|
+
* O PROMPT E NÃO O SNIPPET, porque o caminho do `@import` é relativo à folha global DELE e
|
|
1013
|
+
* ninguém aqui sabe onde ela está. O prompt manda o agente rodar o doctor, ler o que ele
|
|
1014
|
+
* nomeia e fazer - que é o que funciona em projeto arbitrário.
|
|
1015
|
+
*/
|
|
1016
|
+
if (table.slug) {
|
|
1017
|
+
console.log("");
|
|
1018
|
+
console.log(body("Paste this into your agent - it does the wiring:"));
|
|
1019
|
+
console.log("");
|
|
1020
|
+
console.log(snippet(wiringPrompt(table.slug).split("\n")));
|
|
1021
|
+
}
|
|
999
1022
|
}
|
|
1000
1023
|
/**
|
|
1001
1024
|
* A FOLHA APONTA PARA O VOCABULÁRIO DELE, E UM NOME SUMIU - ver `their-vars.ts`.
|
package/package.json
CHANGED