synthesisui 0.16.509 → 0.16.511

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.
@@ -1,14 +1,27 @@
1
+ import { existsSync } from "node:fs";
1
2
  import { readFile, writeFile } from "node:fs/promises";
2
3
  import { join } from "node:path";
3
4
  import { DEFAULT_CONFIG, resolveRegistry, writeProjectConfig, } from "../config.js";
4
5
  import { readProjectTheme, writeBesideTheirs, writeNewProjectRoot, writeNewProjectTheme, } from "../new-project-theme.js";
5
6
  import { openTheDoor } from "../door.js";
6
7
  import { body, section, snippet } from "../output.js";
7
- import { fetchDesignSystem } from "../registry.js";
8
+ import { fetchDesignSystem, RegistryError } from "../registry.js";
8
9
  import { resolveDeps, stylesFor, tailwindMajor } from "../stack.js";
9
10
  import { formMix, measuredStyle } from "../styles-flavour.js";
10
11
  import { desligarCaptura, ligarCaptura } from "../transcript.js";
11
12
  import { add } from "./add.js";
13
+ /** A recusa de uma pasta sem app: o que falta, quem cria, e o mesmo `init` para depois. */
14
+ export const noAppHere = (ds) => [
15
+ "There is no app here - this folder has no package.json.",
16
+ "init sets SynthesisUI up inside an app that already exists; it does not create one.",
17
+ "Create the Next.js app first, then run init inside it:",
18
+ "",
19
+ " npx create-next-app@latest my-app",
20
+ " cd my-app",
21
+ ` npx synthesisui@latest init${ds ? ` --ds ${ds}` : ""}`,
22
+ "",
23
+ "Nothing was written here.",
24
+ ].join("\n");
12
25
  const whereOf = (answer) => answer === "file" || answer === "1"
13
26
  ? "file"
14
27
  : answer === "separate" || answer === "2"
@@ -51,6 +64,17 @@ async function askWhere(tokensFile, separate, entry, intro) {
51
64
  */
52
65
  export async function init(opts) {
53
66
  const root = opts.dir ?? process.cwd();
67
+ /**
68
+ * SEM APP, O `init` RECUSA ANTES DE ESCREVER - jornada "o CLI na primeira página", E01 (12/10, medido de novo na
69
+ * 0.16.509 em 23/10). Numa pasta vazia, `init --target next --ds moss` escrevia `_synthesisui/`, baixava o sistema e
70
+ * mandava rodar o `connect`, sem dizer que não havia app nenhum. E a pasta que ficava atrás travava o passo que
71
+ * faltava: o `create-next-app` recusa um diretório com arquivos que ele não conhece, e `_synthesisui/` é um deles.
72
+ *
73
+ * O `init` não cria o app - quem cria é o `create-next-app`, e a recusa diz o comando. `--target general` é o caso
74
+ * sem Next, e segue sem `package.json`.
75
+ */
76
+ if (opts.target !== "general" && !existsSync(join(root, "package.json")))
77
+ throw new RegistryError(noAppHere(opts.ds));
54
78
  /**
55
79
  * O SISTEMA EXISTE ANTES DE QUALQUER ARQUIVO - bateria ampliada, item 21 (29/09). `init --ds teste-nunca-existiu`
56
80
  * recusava bem ("No design system ... that this machine can see"), mas só depois de escrever `_synthesisui/config.json`,
@@ -2,7 +2,7 @@ import { mkdir, stat, writeFile } from "node:fs/promises";
2
2
  import { dirname, join, relative } from "node:path";
3
3
  import { readProjectConfig, resolveRegistry } from "../config.js";
4
4
  import { installedSheetCss, RECIPE_HEADER, recipeRulesFor, } from "../recipe-css.js";
5
- import { fetchDesignSystem, fetchTemplate } from "../registry.js";
5
+ import { fetchDesignSystem, fetchPages, fetchTemplate } from "../registry.js";
6
6
  import { inTheirTongue, projectTongue, tongueFromArtifacts, } from "../their-tongue.js";
7
7
  import { keptLine, recordWritten, editedHere as theirEdits, } from "../written.js";
8
8
  /**
@@ -46,6 +46,28 @@ function withoutTheSheetInstruction(code) {
46
46
  * path classes; the co-located CSS (Next target) carries the responsive media
47
47
  * queries + the CSS-only hamburger, so it re-vests once `tokens.css` is in.
48
48
  */
49
+ /**
50
+ * `template <slug>` SEM NOME - as páginas prontas do sistema (jornada "o CLI na primeira página", E02). Antes, a única
51
+ * resposta era pedir os dois argumentos, e o nome só se descobria tentando. Sem página nenhuma, o caminho que existe é
52
+ * a landing por seções, e a lista diz isso em vez de ficar vazia.
53
+ */
54
+ export async function listPages(slug, registry) {
55
+ const pages = await fetchPages(resolveRegistry(registry), slug);
56
+ if (pages === null) {
57
+ console.log(`The registry did not list the pages of "${slug}". Try \`synthesisui template ${slug} <name>\`.`);
58
+ return;
59
+ }
60
+ if (pages.length === 0) {
61
+ console.log(`"${slug}" has no ready pages.`);
62
+ console.log(`A landing is put together from its sections: synthesisui landing ${slug} "<what the page is for>"`);
63
+ return;
64
+ }
65
+ console.log(`"${slug}" has ${pages.length} ready page${pages.length === 1 ? "" : "s"}:`);
66
+ for (const page of pages)
67
+ console.log(` ${page}`);
68
+ console.log("");
69
+ console.log(` synthesisui template ${slug} ${pages[0]}`);
70
+ }
49
71
  export async function template(slug, name, opts) {
50
72
  const base = resolveRegistry(opts.registry);
51
73
  const root = opts.dir ?? process.cwd();
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ import { request } from "./commands/request.js";
34
34
  import { status } from "./commands/status.js";
35
35
  import { summary } from "./commands/summary.js";
36
36
  import { sync } from "./commands/sync.js";
37
- import { template } from "./commands/template.js";
37
+ import { listPages, template } from "./commands/template.js";
38
38
  import { upgrade } from "./commands/upgrade.js";
39
39
  import { use } from "./commands/use.js";
40
40
  import { appendEvent } from "./doctor/ledger.js";
@@ -62,6 +62,7 @@ Usage - deterministic, FREE:
62
62
  synthesisui blueprint | component the same command, spelled in full
63
63
  synthesisui template <slug> <name> materialize a whole page from a DS template
64
64
  (--as landing-home names the output - multi-page safe)
65
+ synthesisui template <slug> the ready pages that system has
65
66
  synthesisui upgrade <slug> update an installed DS + regenerate your components + migration brief
66
67
  synthesisui colours [slug] write the colours you chose on the site into your CSS, in your names (asks first)
67
68
  synthesisui use <slug> "<intent>" print a ready-to-paste agent prompt to build/modify on-system
@@ -172,8 +173,8 @@ Examples:
172
173
  synthesisui adopt # you already have a system: start here
173
174
  synthesisui import --dry # see the census before anything is sent
174
175
  synthesisui login
175
- synthesisui init # an empty project: one command, then ask your agent
176
- synthesisui init --target next --ds halogen bootstrap + bring a system in
176
+ synthesisui init # inside a new app (create-next-app first): one command, then ask your agent
177
+ synthesisui init --ds halogen # the same, with a system from the gallery
177
178
  synthesisui doctor
178
179
  synthesisui doctor apps/web packages/ui # scope the read in a monorepo
179
180
  synthesisui doctor --strict
@@ -608,11 +609,16 @@ async function main() {
608
609
  }
609
610
  const slug = args[0];
610
611
  const name = args[1];
611
- if (!slug || !name) {
612
+ if (!slug) {
612
613
  console.error("error: provide slug and template name - `synthesisui template <slug> <name>`");
613
614
  process.exitCode = 1;
614
615
  return;
615
616
  }
617
+ /** SEM NOME, A LISTA - o que o sistema tem, em vez de pedir um nome que só se descobre tentando (E02, 12/10). */
618
+ if (!name) {
619
+ await listPages(slug, registry);
620
+ return;
621
+ }
616
622
  let version;
617
623
  if (typeof flags.version === "string") {
618
624
  version = Number.parseInt(flags.version.replace(/^v/i, ""), 10);
package/dist/registry.js CHANGED
@@ -70,6 +70,23 @@ export async function fetchDesignSystem(base, slug, version) {
70
70
  * Fetches a whole page generated from a DS template (`?template=&target=`). The
71
71
  * server codegens it from `document.layouts[<template>]`; the CLI just writes it.
72
72
  */
73
+ /**
74
+ * AS PÁGINAS PRONTAS DE UM SISTEMA - `template <slug>` sem nome (jornada "o CLI na primeira página", E02). `null` quando
75
+ * o registro ainda não sabe responder (anterior a `?pages=1`): ele devolve o documento, que não tem `pages`.
76
+ */
77
+ export async function fetchPages(base, slug) {
78
+ const url = new URL(`${base}/api/registry/ds/${encodeURIComponent(slug)}`);
79
+ url.searchParams.set("pages", "1");
80
+ const res = await request(url.toString());
81
+ if (res.status === 404)
82
+ throw new RegistryError(`No design system "${slug}" that this machine can see. \`synthesisui list\` shows what is public.`);
83
+ if (!res.ok)
84
+ throw new RegistryError(`Registry responded ${res.status} while listing the pages of "${slug}".`);
85
+ const body = (await res.json().catch(() => ({})));
86
+ return Array.isArray(body.pages)
87
+ ? body.pages.filter((p) => typeof p === "string")
88
+ : null;
89
+ }
73
90
  export async function fetchTemplate(base, slug, template, target, version, as_) {
74
91
  const url = new URL(`${base}/api/registry/ds/${encodeURIComponent(slug)}`);
75
92
  url.searchParams.set("template", template);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.509",
3
+ "version": "0.16.511",
4
4
  "description": "Bring SynthesisUI design systems into any project - tokens, typed components, whole pages and an agent-ready CLAUDE.md manifest.",
5
5
  "type": "module",
6
6
  "bin": {