@fluencypassdevs/cycle 1.17.1 → 1.18.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/bin/cli.mjs CHANGED
@@ -12,6 +12,8 @@ const command = process.argv[2]
12
12
 
13
13
  if (command === "mcp") {
14
14
  await import("./mcp.mjs")
15
+ } else if (command === "propose") {
16
+ await import("./propose.mjs")
15
17
  } else if (command === "init" || !command) {
16
18
  await import("./init.mjs")
17
19
  } else {
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * `npx cycle propose <arquivo>` — propõe um componente ao Design System a partir
5
+ * do PRÓPRIO projeto do dev, sem abrir o GitHub na mão.
6
+ *
7
+ * Lê o componente (idealmente de `src/components/ds-proposals/`), pergunta o
8
+ * contexto, e abre a issue "Proposta de Componente" no repo do DS via `gh`
9
+ * (login do próprio dev — todos são da org). Se o `gh` não existir, cai num
10
+ * fallback: salva o corpo num arquivo + imprime um link pré-preenchido.
11
+ *
12
+ * Flags: --name, --what, --where, --preview (não-interativo) · --dry-run (só imprime).
13
+ */
14
+
15
+ import fs from "fs"
16
+ import path from "path"
17
+ import { execFileSync, spawnSync } from "child_process"
18
+ import { createInterface } from "readline"
19
+
20
+ // ── Config específica do DS (o pulse tem a sua) ──
21
+ const DS = {
22
+ label: "Cycle",
23
+ repo: "Fluencypass/Cycle",
24
+ surfaceHint: "Tela de produto (app logado, painel, aula)",
25
+ }
26
+
27
+ const argv = process.argv.slice(2)
28
+ const flags = {}
29
+ const positionals = []
30
+ for (let i = 0; i < argv.length; i++) {
31
+ const a = argv[i]
32
+ if (a === "--dry-run") flags.dryRun = true
33
+ else if (a.startsWith("--")) flags[a.slice(2)] = argv[++i]
34
+ else positionals.push(a)
35
+ }
36
+
37
+ function fail(msg) {
38
+ console.error(`\n ✗ ${msg}\n`)
39
+ process.exit(1)
40
+ }
41
+
42
+ // 1. Arquivo do componente
43
+ let file = positionals[0]
44
+ if (!file) {
45
+ // tenta achar candidatos em ds-proposals/
46
+ const dir = path.join(process.cwd(), "src/components/ds-proposals")
47
+ const found = fs.existsSync(dir) ? fs.readdirSync(dir).filter((f) => /\.(tsx|jsx|ts)$/.test(f)) : []
48
+ if (found.length === 1) file = path.join(dir, found[0])
49
+ else if (found.length > 1) fail(`Vários candidatos em ds-proposals/. Especifique: npx cycle propose <arquivo>\n ${found.join("\n ")}`)
50
+ else fail("Uso: npx cycle propose <caminho-do-componente> (ex.: src/components/ds-proposals/meu-card.tsx)")
51
+ }
52
+ if (!fs.existsSync(file)) fail(`Arquivo não encontrado: ${file}`)
53
+ const code = fs.readFileSync(file, "utf-8")
54
+
55
+ // 2. Metadados (flags ou prompt)
56
+ const rl = createInterface({ input: process.stdin, output: process.stdout })
57
+ const ask = (q, def) =>
58
+ new Promise((res) => rl.question(` ${q}${def ? ` (${def})` : ""}: `, (a) => res(a.trim() || def || "")))
59
+
60
+ const name = flags.name || path.basename(file).replace(/\.(tsx|jsx|ts)$/, "")
61
+
62
+ console.log(`\n Propor componente ao ${DS.label} Design System\n ─────────────────────────────────────────────\n`)
63
+
64
+ const what = flags.what || (await ask("O que ele faz? (1 frase)"))
65
+ const where = flags.where || (await ask("Onde ele aparece?", DS.surfaceHint))
66
+ const preview = flags.preview || (await ask("Link de preview ou screenshot (opcional)"))
67
+ rl.close()
68
+
69
+ // 3. Corpo da issue
70
+ const title = `[Proposta] ${name}`
71
+ const body = `## Componente
72
+ **${name}**
73
+
74
+ ## O que faz
75
+ ${what || "(não informado)"}
76
+
77
+ ## Onde aparece
78
+ ${where}
79
+
80
+ ## Preview
81
+ ${preview || "(anexar print/link)"}
82
+
83
+ ## Código
84
+ \`\`\`tsx
85
+ ${code}
86
+ \`\`\`
87
+
88
+ ---
89
+ _Proposto via \`npx cycle propose\` a partir de um projeto consumidor._`
90
+
91
+ // 4. dry-run
92
+ if (flags.dryRun) {
93
+ console.log(`\n [dry-run] Issue que seria criada em ${DS.repo}:\n`)
94
+ console.log(` Título: ${title}`)
95
+ console.log(` Label: ds-proposal\n`)
96
+ console.log(body.split("\n").map((l) => " │ " + l).join("\n"))
97
+ console.log("")
98
+ process.exit(0)
99
+ }
100
+
101
+ // 5. Cria a issue via gh (ou fallback)
102
+ const hasGh = spawnSync("gh", ["--version"], { stdio: "ignore" }).status === 0
103
+ if (hasGh) {
104
+ const tmp = path.join(process.cwd(), `.ds-proposal-${name}.md`)
105
+ fs.writeFileSync(tmp, body)
106
+ try {
107
+ const url = execFileSync(
108
+ "gh",
109
+ ["issue", "create", "--repo", DS.repo, "--title", title, "--label", "ds-proposal", "--body-file", tmp],
110
+ { encoding: "utf-8" }
111
+ ).trim()
112
+ fs.unlinkSync(tmp)
113
+ console.log(`\n ✓ Proposta enviada! ${url}\n Você será notificado quando for revisada.\n`)
114
+ } catch (err) {
115
+ fs.unlinkSync(tmp)
116
+ fail(`Falha ao criar a issue via gh (${err.message}). Rode \`gh auth login\` e tente de novo, ou use o fallback abaixo.`)
117
+ }
118
+ } else {
119
+ const out = path.join(process.cwd(), `ds-proposal-${name}.md`)
120
+ fs.writeFileSync(out, body)
121
+ const url = `https://github.com/${DS.repo}/issues/new?labels=ds-proposal&title=${encodeURIComponent(title)}`
122
+ console.log(`\n 'gh' não encontrado. Fallback:\n`)
123
+ console.log(` 1. Corpo salvo em: ${out}`)
124
+ console.log(` 2. Abra: ${url}`)
125
+ console.log(` 3. Cole o conteúdo do arquivo no corpo da issue.\n`)
126
+ console.log(` (Instale o GitHub CLI — https://cli.github.com — pra automatizar isso.)\n`)
127
+ }
@@ -166,9 +166,10 @@ O DS **nao trava** o projeto. Se um componente REALMENTE nao existe (confirme an
166
166
  `components/ui/`. O componente ja funciona e pode ser usado no projeto.
167
167
  2. Componha com os atomos que ja existem (Button, Input...) e use SO tokens semanticos
168
168
  (`bg-brand`, `text-muted-foreground`) — nunca cor/spacing hardcoded.
169
- 3. Se for reutilizavel por outros projetos, **proponha a entrada no DS**: abra uma issue
170
- "Proposta de Componente" em https://github.com/Fluencypass/Cycle/issues/new/choose
171
- (cole o codigo + um print/link do preview). Guia completo: `CONTRIBUTING.md` no repo do DS.
169
+ 3. Se for reutilizavel por outros projetos, **proponha a entrada no DS** rodando no projeto:
170
+ \`npx cycle propose src/components/ds-proposals/<arquivo>\` (abre a issue automaticamente via
171
+ gh). Fallback manual: https://github.com/Fluencypass/Cycle/issues/new/choose. Guia:
172
+ https://design.fluencypass.com/cycle/contribuir
172
173
 
173
174
  **Regra de superficie**: o DS certo depende de ONDE o componente renderiza — tela de produto
174
175
  (app logado) = **Cycle**; landing/campanha de marketing = **Pulse**. Nunca misture os dois no
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluencypassdevs/cycle",
3
- "version": "1.17.1",
3
+ "version": "1.18.0",
4
4
  "description": "Cycle Design System — UI component library by Fluencypass (produto)",
5
5
  "license": "MIT",
6
6
  "repository": {