synthesisui 0.16.160 → 0.16.162
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 +10 -2
- package/dist/commands/import.js +12 -2
- package/dist/commands/sync.js +64 -4
- package/dist/doctor/coverage.js +10 -1
- package/dist/measured-scope.js +29 -1
- package/package.json +1 -1
package/dist/commands/align.js
CHANGED
|
@@ -76,8 +76,16 @@ opts = {}) {
|
|
|
76
76
|
const scope = await measuredScope(root);
|
|
77
77
|
if (!scope.system && scope.usage.length === 0)
|
|
78
78
|
out.push({
|
|
79
|
-
says: `"${lock.slug}" does not record where it was measured, so a re-measure would read this whole repo instead of the folder the system came from.`,
|
|
80
|
-
|
|
79
|
+
says: `"${lock.slug}" does not record where it was measured, so a re-measure would read this whole repo instead of the folder the system came from. Sync asks once and remembers the answer.`,
|
|
80
|
+
/**
|
|
81
|
+
* O COMANDO QUE ELA JÁ RODA, e nunca um sexto.
|
|
82
|
+
*
|
|
83
|
+
* Isto dizia `import --dry --scope <folder>`, que não está no vocabulário de quem usa isto -
|
|
84
|
+
* `connect`, `login`, `doctor`, `sync`, `upgrade`, e a skill. O `align` é a única coisa que
|
|
85
|
+
* fala com a pessoa sem ela pedir, e falar ensinando uma palavra que ela nunca viu transfere
|
|
86
|
+
* para ela um problema que era nosso. O `sync` absorveu o caso - ver `askForScope`.
|
|
87
|
+
*/
|
|
88
|
+
run: "npx synthesisui sync",
|
|
81
89
|
});
|
|
82
90
|
const events = await readEvents(root).catch(() => []);
|
|
83
91
|
if (events.length > 0)
|
package/dist/commands/import.js
CHANGED
|
@@ -79,7 +79,7 @@ const MAX_PER_KIND = {
|
|
|
79
79
|
* comes from wherever the vocabulary is centralised, and each app is a consumer
|
|
80
80
|
* measured against it.
|
|
81
81
|
*/
|
|
82
|
-
async function siblingProjects(root) {
|
|
82
|
+
export async function siblingProjects(root) {
|
|
83
83
|
const apps = [];
|
|
84
84
|
const shared = [];
|
|
85
85
|
for (const group of ["apps", "packages", "libs"]) {
|
|
@@ -1205,7 +1205,17 @@ export async function takeCensus(root, opts) {
|
|
|
1205
1205
|
* product is broken, reasoning correctly from what they were shown. The gap was never
|
|
1206
1206
|
* the defect; the silence was (dono, 01/08).
|
|
1207
1207
|
*/
|
|
1208
|
-
|
|
1208
|
+
/**
|
|
1209
|
+
* O DENOMINADOR CONTA COMPONENTES, e contava ARQUIVOS.
|
|
1210
|
+
*
|
|
1211
|
+
* `looks` é por NOME e `componentFiles` é por arquivo, então um arquivo que exporta dois
|
|
1212
|
+
* componentes produzia "36 of 35 components came out with a look - 103%" (medido na biblioteca do
|
|
1213
|
+
* dono em 06/08). Uma porcentagem que passa de 100 por construção não é um arredondamento: é a
|
|
1214
|
+
* linha que declara a cobertura da esteira inteira se medindo contra outra unidade.
|
|
1215
|
+
*
|
|
1216
|
+
* `componentFiles` segue existindo para as formas de estilo, que SÃO por arquivo.
|
|
1217
|
+
*/
|
|
1218
|
+
const coverage = summarizeCoverage(shapes, defined.length || componentFiles, Object.keys(looks).length, Object.values(looks).reduce((n, look) => n +
|
|
1209
1219
|
Object.keys(look.base).length +
|
|
1210
1220
|
Object.keys(look.dark ?? {}).length +
|
|
1211
1221
|
Object.values(look.states).reduce((m, block) => m + Object.keys(block).length, 0) +
|
package/dist/commands/sync.js
CHANGED
|
@@ -3,10 +3,10 @@ import { join, resolve } from "node:path";
|
|
|
3
3
|
import { readToken, resolveRegistry } from "../config.js";
|
|
4
4
|
import { readEvents } from "../doctor/ledger.js";
|
|
5
5
|
import { checkableName, closeRequest, readRequests, verifyAndCloseRequests, } from "../doctor/requests.js";
|
|
6
|
-
import { measuredScope } from "../measured-scope.js";
|
|
6
|
+
import { measuredScope, rememberScope } from "../measured-scope.js";
|
|
7
7
|
import { body, paint, section, snippet } from "../output.js";
|
|
8
8
|
import { repoStateOf } from "../repo-state.js";
|
|
9
|
-
import { resolveReadParts, takeCensus } from "./import.js";
|
|
9
|
+
import { resolveReadParts, siblingProjects, takeCensus } from "./import.js";
|
|
10
10
|
/**
|
|
11
11
|
* What each decision means ON THIS MACHINE - the card decides, the sync
|
|
12
12
|
* enacts. The web never touches the local file; this line is printed right
|
|
@@ -206,8 +206,27 @@ export async function remeasure(args) {
|
|
|
206
206
|
* O servidor continua valendo como segunda fonte: um clone fresco tem o `.lock` e não tem censo.
|
|
207
207
|
*/
|
|
208
208
|
const local = await measuredScope(root);
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
let scope = local.system ?? stored.scope ?? null;
|
|
210
|
+
let usage = local.usage.length > 0 ? local.usage : (stored.usage ?? []);
|
|
211
|
+
/**
|
|
212
|
+
* E QUANDO NINGUÉM SABE, ESTE COMANDO PERGUNTA - uma vez, e grava a resposta.
|
|
213
|
+
*
|
|
214
|
+
* Um sistema que perdeu o escopo só tinha uma volta: `import --scope`. Isso é uma SEXTA palavra
|
|
215
|
+
* no vocabulário de quem usa isto (`connect`, `login`, `doctor`, `sync`, `upgrade`, e a skill), e
|
|
216
|
+
* uma mensagem que ensina uma palavra nova transfere para a pessoa um problema que era nosso.
|
|
217
|
+
*
|
|
218
|
+
* Então o comando que ela já roda absorve o caso: os candidatos saem do próprio repo, a resposta
|
|
219
|
+
* vai para o `.lock`, e a pergunta não volta.
|
|
220
|
+
*/
|
|
221
|
+
if (!scope) {
|
|
222
|
+
const asked = await askForScope(root);
|
|
223
|
+
if (asked) {
|
|
224
|
+
scope = asked.scope;
|
|
225
|
+
if (asked.usage.length > 0)
|
|
226
|
+
usage = asked.usage;
|
|
227
|
+
await rememberScope(root, slug, scope, usage);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
211
230
|
console.log(section("Measuring your repository again"));
|
|
212
231
|
console.log(body(paint.faint(`${scope ? `scope ${scope}` : "the whole repo"}${local.system && local.system !== stored.scope
|
|
213
232
|
? " · read from your own census, which is where the last measurement recorded it"
|
|
@@ -335,3 +354,44 @@ export async function installedSlug(root) {
|
|
|
335
354
|
}
|
|
336
355
|
return null;
|
|
337
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* DE ONDE ESTE SISTEMA FOI MEDIDO - perguntado uma vez, com os candidatos do próprio repo.
|
|
359
|
+
*
|
|
360
|
+
* Os nomes não são digitados: `siblingProjects` já separa o que é biblioteca compartilhada do que é
|
|
361
|
+
* app, que é exatamente a distinção entre o SISTEMA e quem o CONSOME. Um monorepo responde em uma
|
|
362
|
+
* tecla; um repo de app único nem chega aqui, porque a raiz é a resposta óbvia e ela não precisa de
|
|
363
|
+
* pergunta.
|
|
364
|
+
*
|
|
365
|
+
* Sem terminal interativo devolve `null` e a medição segue como antes - um CI não pode travar
|
|
366
|
+
* esperando alguém, e medir a raiz num CI é o comportamento que ele sempre teve.
|
|
367
|
+
*/
|
|
368
|
+
async function askForScope(root) {
|
|
369
|
+
const { apps, shared } = await siblingProjects(root);
|
|
370
|
+
if (shared.length === 0)
|
|
371
|
+
return null;
|
|
372
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
373
|
+
return null;
|
|
374
|
+
console.log(section("Where does this system come from?"));
|
|
375
|
+
console.log(body("Nothing here records it, so a re-measure would read this whole repo - which produces the average of every app you have, and that is a diagnosis rather than a system."));
|
|
376
|
+
shared.forEach((name, i) => {
|
|
377
|
+
console.log(body(` ${i + 1}. ${name}`));
|
|
378
|
+
});
|
|
379
|
+
console.log(body(` ${shared.length + 1}. the whole repo`));
|
|
380
|
+
if (apps.length > 0)
|
|
381
|
+
console.log(body(paint.faint(`${apps.length} app${apps.length === 1 ? "" : "s"} travel as evidence either way: ${apps.slice(0, 3).join(", ")}${apps.length > 3 ? ", …" : ""}`)));
|
|
382
|
+
const { createInterface } = await import("node:readline/promises");
|
|
383
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
384
|
+
try {
|
|
385
|
+
const answer = (await rl.question(" which one? [1]: ")).trim();
|
|
386
|
+
const pick = answer === "" ? 1 : Number(answer);
|
|
387
|
+
if (!Number.isInteger(pick) || pick < 1 || pick > shared.length)
|
|
388
|
+
return null;
|
|
389
|
+
return { scope: shared[pick - 1], usage: apps };
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
finally {
|
|
395
|
+
rl.close();
|
|
396
|
+
}
|
|
397
|
+
}
|
package/dist/doctor/coverage.js
CHANGED
|
@@ -92,7 +92,16 @@ export function countShape(source, name, into) {
|
|
|
92
92
|
}
|
|
93
93
|
export function summarizeCoverage(counts, components, read, declarations) {
|
|
94
94
|
return {
|
|
95
|
-
|
|
95
|
+
/**
|
|
96
|
+
* NUNCA MENOS QUE O QUE FOI LIDO.
|
|
97
|
+
*
|
|
98
|
+
* `read` conta LOOKS por nome e o denominador chegava contando ARQUIVOS - um arquivo que exporta
|
|
99
|
+
* dois componentes produzia `36 of 35 components came out with a look - 103%` na biblioteca do
|
|
100
|
+
* dono (06/08). O conserto de verdade é o chamador passar a mesma unidade, e ele passa; isto é a
|
|
101
|
+
* trava, para que a linha que declara a cobertura da esteira inteira não possa afirmar mais do
|
|
102
|
+
* que existe se outro chamador errar a unidade de novo.
|
|
103
|
+
*/
|
|
104
|
+
components: Math.max(components, read),
|
|
96
105
|
read,
|
|
97
106
|
declarations,
|
|
98
107
|
counts: [...counts.values()].sort((a, b) => b.files - a.files),
|
package/dist/measured-scope.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readdir, readFile, stat } from "node:fs/promises";
|
|
1
|
+
import { readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
const EMPTY = { system: null, usage: [], from: "none" };
|
|
4
4
|
/**
|
|
@@ -119,3 +119,31 @@ export function describeScope(m) {
|
|
|
119
119
|
];
|
|
120
120
|
return `read from your census: ${parts.join(" · ")}`;
|
|
121
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* GRAVA ONDE ESTE SISTEMA FOI MEDIDO, no ponteiro dele.
|
|
124
|
+
*
|
|
125
|
+
* Existe para uma resposta ser dada UMA vez. O escopo se perdeu do servidor em 06/08 e o único
|
|
126
|
+
* caminho de volta era um `import --scope`, que é um comando fora do vocabulário de quem usa isto -
|
|
127
|
+
* `connect`, `login`, `doctor`, `sync`, `upgrade` e a skill. Uma mensagem que ensina uma sexta
|
|
128
|
+
* palavra é pior que mensagem nenhuma: ela transfere para a pessoa um problema que era nosso.
|
|
129
|
+
*
|
|
130
|
+
* Silencioso quando não há lock: não é erro, é um repo sem sistema instalado.
|
|
131
|
+
*/
|
|
132
|
+
export async function rememberScope(root, slug, scope, usage) {
|
|
133
|
+
const path = join(root, "_synthesisui", "ds", slug, ".lock");
|
|
134
|
+
const raw = await readFile(path, "utf8").catch(() => null);
|
|
135
|
+
if (!raw)
|
|
136
|
+
return;
|
|
137
|
+
let lock;
|
|
138
|
+
try {
|
|
139
|
+
lock = JSON.parse(raw);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
await writeFile(path, `${JSON.stringify({
|
|
145
|
+
...lock,
|
|
146
|
+
...(scope ? { scope } : {}),
|
|
147
|
+
...(usage.length > 0 ? { usage } : {}),
|
|
148
|
+
}, null, 2)}\n`, "utf8");
|
|
149
|
+
}
|
package/package.json
CHANGED