cistack 6.1.0 → 6.2.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/package.json +1 -1
- package/product-site/.github/workflows/pipeline.yml +14 -1
- package/product-site/components/CopyButton.tsx +54 -38
- package/product-site/components/HomeClient.tsx +490 -811
- package/product-site/components/InstallToggle.tsx +70 -34
- package/product-site/components/TerminalCard.tsx +9 -5
- package/product-site/components/TerminalCardMotion.tsx +21 -14
- package/product-site/components/site-motion.tsx +229 -0
- package/product-site/dictionaries/br.json +246 -107
- package/product-site/dictionaries/cn.json +246 -107
- package/product-site/dictionaries/de.json +237 -98
- package/product-site/dictionaries/en.json +228 -91
- package/product-site/dictionaries/es.json +240 -146
- package/product-site/dictionaries/fr.json +237 -143
- package/product-site/dictionaries/pt.json +246 -107
- package/product-site/package.json +1 -0
- package/product-site/scripts/validate-i18n.mjs +45 -0
- package/src/index.js +12 -13
|
@@ -1,137 +1,276 @@
|
|
|
1
1
|
{
|
|
2
|
+
"copy_button": {
|
|
3
|
+
"idle": "Copiar",
|
|
4
|
+
"success": "Copiado"
|
|
5
|
+
},
|
|
2
6
|
"navigation": {
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"docs": "Docs"
|
|
7
|
+
"repository": "GitHub",
|
|
8
|
+
"registry": "npm",
|
|
9
|
+
"reference": "Referência",
|
|
10
|
+
"version": "Versão",
|
|
11
|
+
"status": "Estável"
|
|
9
12
|
},
|
|
10
13
|
"hero": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"s2_label": "S_02 // SÍNTESE_PIPELINE",
|
|
15
|
-
"s2_title": "SEU PIPELINE",
|
|
16
|
-
"s3_label": "S_03 // VALIDAÇÃO_AÇÃO",
|
|
17
|
-
"s3_title": "ORQUESTRADO",
|
|
18
|
-
"description": "cistack realiza uma varredura profunda no seu repositório para gerar instantaneamente fluxos de trabalho do GitHub Actions prontos para produção em mais de 30 frameworks e 12 plataformas.",
|
|
14
|
+
"product_name": "cistack",
|
|
15
|
+
"tagline": "Gere pipelines CI/CD no GitHub Actions analisando o código que já tem.",
|
|
16
|
+
"intro": "O cistack analisa o seu projeto, deteta o stack e escreve workflows GitHub Actions prontos para produção: CI, implementação, Docker e releases. Pensado para repositórios reais, não demonstrações: lê ficheiros de lock, sinais de framework, configuração de release, workspaces monorepo, alojamento e metadados de ramos Git antes de gerar o YAML.",
|
|
19
17
|
"npx_command": "npx cistack",
|
|
20
|
-
"
|
|
21
|
-
"per_week": "
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
18
|
+
"weekly_downloads": "Transferências semanais",
|
|
19
|
+
"per_week": "última semana no npm",
|
|
20
|
+
"live_registry": "Em direto a partir do registo"
|
|
21
|
+
},
|
|
22
|
+
"preview": {
|
|
23
|
+
"title": "Pré-visualização",
|
|
24
|
+
"caption": "Saída CLI animada após analisar um projeto típico."
|
|
25
|
+
},
|
|
26
|
+
"why": {
|
|
27
|
+
"title": "Porquê o cistack",
|
|
28
|
+
"items": [
|
|
29
|
+
"Deteta automaticamente linguagens, frameworks, ferramentas de teste, fornecedores de alojamento e ferramentas de release",
|
|
30
|
+
"Utiliza o ramo Git predefinido do repositório quando disponível, em vez de assumir main",
|
|
31
|
+
"Suporta monorepos, workflows por pacote e comandos conscientes do gestor de pacotes",
|
|
32
|
+
"Gera configuração Dependabot alinhada com o ecossistema, incluindo Bun quando existe bun.lock",
|
|
33
|
+
"Funde de forma inteligente os workflows gerados com os ficheiros existentes sem sobrescrever à cega",
|
|
34
|
+
"Gera pipelines de implementação para Vercel, Netlify, Firebase, GitHub Pages, AWS, Azure, Heroku, Render e Railway",
|
|
35
|
+
"Inclui comandos integrados de auditoria e atualização de workflows",
|
|
36
|
+
"Suporta cistack.config.js tipado via index.d.ts",
|
|
37
|
+
"Com suíte de regressão automatizada (ramos, release, fusão inteligente, scripts monorepo, testes smoke da CLI)"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"install": {
|
|
41
|
+
"title": "Instalação",
|
|
42
|
+
"quick_command": "Instalação rápida",
|
|
43
|
+
"node_note": "O cistack suporta Node.js 16+; o projeto é verificado continuamente em Node.js 18, 20 e 22 no GitHub Actions."
|
|
44
|
+
},
|
|
45
|
+
"cli": {
|
|
46
|
+
"section_title": "Utilização da CLI",
|
|
47
|
+
"items": [
|
|
48
|
+
{
|
|
49
|
+
"title": "Gerar workflows",
|
|
50
|
+
"paragraphs": [
|
|
51
|
+
"generate é o comando predefinido: funcionam npx cistack e npx cistack generate.",
|
|
52
|
+
"Opções comuns:"
|
|
53
|
+
],
|
|
54
|
+
"snippets": [
|
|
55
|
+
"npx cistack",
|
|
56
|
+
"npx cistack generate",
|
|
57
|
+
"npx cistack generate --path /path/to/project",
|
|
58
|
+
"npx cistack generate --dry-run",
|
|
59
|
+
"npx cistack generate --explain",
|
|
60
|
+
"npx cistack generate --output .github/workflows",
|
|
61
|
+
"npx cistack generate --no-prompt"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"title": "Auditar workflows existentes",
|
|
66
|
+
"paragraphs": [
|
|
67
|
+
"Verifica o diretório de workflows gerados (concorrência em falta, ações desatualizadas, versões antigas do Node, cache de dependências, etc.). Se definir outputDir em cistack.config.js, audit e upgrade também usam esse diretório."
|
|
68
|
+
],
|
|
69
|
+
"snippets": ["npx cistack audit"]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"title": "Atualizar ações do workflow",
|
|
73
|
+
"paragraphs": [
|
|
74
|
+
"Atualiza as GitHub Actions conhecidas para as últimas versões estáveis suportadas."
|
|
75
|
+
],
|
|
76
|
+
"snippets": ["npx cistack upgrade", "npx cistack upgrade --dry-run"]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"title": "Criar configuração inicial",
|
|
80
|
+
"paragraphs": [
|
|
81
|
+
"Escreve cistack.config.js com as chaves de substituição suportadas."
|
|
82
|
+
],
|
|
83
|
+
"snippets": ["npx cistack init"]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"generated": {
|
|
88
|
+
"section_title": "O que é gerado",
|
|
89
|
+
"items": [
|
|
90
|
+
{
|
|
91
|
+
"title": "pipeline.yml",
|
|
92
|
+
"paragraphs": [
|
|
93
|
+
"Por predefinição, o cistack gera um único workflow GitHub Actions que agrupa trabalhos de CI, implementação, Docker e release para acompanhar todo o pipeline num só ficheiro.",
|
|
94
|
+
"Inclui lint, test, build, E2E, implementação, Docker e release quando o stack permite, usa o ramo predefinido detetado ou configurado, mantém pré-visualizações e releases no mesmo ficheiro e documenta os segredos necessários no cabeçalho."
|
|
95
|
+
],
|
|
96
|
+
"snippets": []
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"title": "dependabot.yml",
|
|
100
|
+
"paragraphs": [
|
|
101
|
+
"O Dependabot permanece num ficheiro separado em .github/dependabot.yml, pois não é um workflow GitHub Actions.",
|
|
102
|
+
"Para pré-visualizações em PRs Dependabot, adicione também credenciais como segredos Dependabot, não só Actions. Na Vercel: VERCEL_TOKEN, VERCEL_ORG_ID e VERCEL_PROJECT_ID."
|
|
103
|
+
],
|
|
104
|
+
"snippets": []
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"title": "Modo dividido (split)",
|
|
108
|
+
"paragraphs": [
|
|
109
|
+
"Se preferir o esquema antigo multi-ficheiro, defina workflowLayout como split em cistack.config.js. Em modo split, o cistack volta a escrever ci.yml, deploy.yml, docker.yml e release.yml em separado."
|
|
110
|
+
],
|
|
111
|
+
"snippets": [
|
|
112
|
+
"module.exports = {\n workflowLayout: 'split',\n};"
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
"detection": {
|
|
118
|
+
"section_title": "Deteção suportada",
|
|
119
|
+
"hosting_title": "Alojamento",
|
|
120
|
+
"hosting_tags": [
|
|
121
|
+
"Firebase",
|
|
122
|
+
"Vercel",
|
|
123
|
+
"Netlify",
|
|
124
|
+
"GitHub Pages",
|
|
125
|
+
"AWS",
|
|
126
|
+
"GCP App Engine",
|
|
127
|
+
"Azure",
|
|
128
|
+
"Heroku",
|
|
129
|
+
"Render",
|
|
130
|
+
"Railway",
|
|
131
|
+
"Docker"
|
|
132
|
+
],
|
|
133
|
+
"frameworks_title": "Frameworks",
|
|
134
|
+
"frameworks_tags": [
|
|
135
|
+
"Next.js",
|
|
136
|
+
"Nuxt",
|
|
137
|
+
"SvelteKit",
|
|
138
|
+
"Remix",
|
|
139
|
+
"Astro",
|
|
140
|
+
"Vite",
|
|
141
|
+
"React",
|
|
142
|
+
"Vue",
|
|
143
|
+
"Angular",
|
|
144
|
+
"Svelte",
|
|
145
|
+
"Gatsby",
|
|
146
|
+
"Express",
|
|
147
|
+
"Fastify",
|
|
148
|
+
"NestJS",
|
|
149
|
+
"Hono",
|
|
150
|
+
"Koa",
|
|
151
|
+
"Django",
|
|
152
|
+
"Flask",
|
|
153
|
+
"FastAPI",
|
|
154
|
+
"Rails",
|
|
155
|
+
"Spring Boot",
|
|
156
|
+
"Laravel",
|
|
157
|
+
"Go",
|
|
158
|
+
"Rust"
|
|
159
|
+
],
|
|
160
|
+
"testing_title": "Ferramentas de teste",
|
|
161
|
+
"testing_tags": [
|
|
162
|
+
"Jest",
|
|
163
|
+
"Vitest",
|
|
164
|
+
"Mocha",
|
|
165
|
+
"Cypress",
|
|
166
|
+
"Playwright",
|
|
167
|
+
"Pytest",
|
|
168
|
+
"RSpec",
|
|
169
|
+
"Go test",
|
|
170
|
+
"Cargo test",
|
|
171
|
+
"PHPUnit",
|
|
172
|
+
"Maven / JUnit",
|
|
173
|
+
"Storybook"
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
"configuration": {
|
|
177
|
+
"section_title": "Configuração",
|
|
178
|
+
"intro": "Crie cistack.config.js quando quiser substituir a deteção.",
|
|
179
|
+
"example_caption": "Exemplo",
|
|
180
|
+
"keys_title": "Chaves de configuração de nível superior",
|
|
181
|
+
"keys": [
|
|
182
|
+
"nodeVersion",
|
|
183
|
+
"packageManager",
|
|
184
|
+
"hosting",
|
|
185
|
+
"frameworks",
|
|
186
|
+
"testing",
|
|
187
|
+
"branches",
|
|
188
|
+
"workflowLayout",
|
|
189
|
+
"cache",
|
|
190
|
+
"monorepo",
|
|
191
|
+
"release",
|
|
192
|
+
"secrets",
|
|
193
|
+
"outputDir"
|
|
194
|
+
],
|
|
195
|
+
"branches_title": "Comportamento dos ramos",
|
|
196
|
+
"branches": [
|
|
197
|
+
"Se branches estiver definido na config, o cistack usa-o exatamente",
|
|
198
|
+
"Caso contrário, lê o ramo predefinido do repositório a partir dos metadados Git quando possível",
|
|
199
|
+
"Sem metadados Git, recua para valores seguros como main, master e develop consoante o tipo de workflow"
|
|
200
|
+
],
|
|
201
|
+
"config_snippet": "/** @type {import('cistack').Config} */\nmodule.exports = {\n nodeVersion: '20',\n packageManager: 'pnpm',\n branches: ['main', 'staging'],\n workflowLayout: 'single',\n hosting: ['Vercel'],\n outputDir: '.github/workflows',\n cache: {\n npm: true,\n cargo: true,\n pip: true,\n },\n monorepo: {\n perPackage: true,\n },\n release: {\n tool: 'semantic-release',\n },\n};"
|
|
202
|
+
},
|
|
203
|
+
"secrets": {
|
|
204
|
+
"section_title": "Segredos",
|
|
205
|
+
"body": "Os workflows de implementação e release gerados documentam os segredos necessários no topo de cada ficheiro. Adicione-os no GitHub: Definições → Secrets and variables → Actions."
|
|
26
206
|
},
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
"section2_title": "Instalação",
|
|
50
|
-
"command_registry": "REGISTRO_COMANDOS",
|
|
51
|
-
"commands": {
|
|
52
|
-
"audit": "Verifica fluxos de trabalho por ações desatualizadas",
|
|
53
|
-
"upgrade": "Atualiza todas as ações para as últimas versões",
|
|
54
|
-
"init": "Cria um arquivo de configuração de sobreposição"
|
|
55
|
-
},
|
|
56
|
-
"recommended_npx": "Recomendado: Use npx para uma geração única.",
|
|
57
|
-
"parameters_manifest": "MANIFESTO_PARÂMETROS",
|
|
58
|
-
"flags": {
|
|
59
|
-
"explain": "Mostra o raciocínio da stack detectada",
|
|
60
|
-
"path": "Caminho do diretório alvo para varredura",
|
|
61
|
-
"output": "Redefine o diretório de saída do fluxo de trabalho",
|
|
62
|
-
"dry_run": "Simula a saída sem escrever",
|
|
63
|
-
"no_prompt": "Ignora verificações de segurança interativas",
|
|
64
|
-
"verbose": "Ativa o rastreamento stdout máximo",
|
|
65
|
-
"force": "Ignora arquivos existentes e sobrescreve"
|
|
66
|
-
},
|
|
67
|
-
"detection_logic_title": "Lógica de Detecção",
|
|
68
|
-
"detection_logic_desc": "Gatilhos de reconhecimento automático baseados em sinais do sistema de arquivos.",
|
|
69
|
-
"signal_source": "Fonte do sinal:",
|
|
70
|
-
"framework_coverage": "Cobertura Framework",
|
|
71
|
-
"testing_tools": "Ferramentas de teste",
|
|
72
|
-
"section3_num": "03. Artefatos",
|
|
73
|
-
"section3_title": "Workflows Gerados",
|
|
74
|
-
"workflows": {
|
|
75
|
-
"ci": { "label": "Integração Contínua", "desc": "Executado em push/PR: Lint (ESLint, TS type-check), Test (matriz de versões Node), Build (produção), e E2E." },
|
|
76
|
-
"deploy": { "label": "Despuegue Contínuo", "desc": "Acionado na main: Despuegue de plataforma com ambientes PR Preview automáticos para Vercel e Netlify." },
|
|
77
|
-
"docker": { "label": "Build & Push Docker", "desc": "Acionado na main/tags: Build multi-plataforma via Docker Buildx, push GHCR, e cache GitHub Actions." },
|
|
78
|
-
"security": { "label": "Auditoria de Segurança", "desc": "Executado em push/PR/cronogramas semanais: Análise de dependências e auditoria profunda CodeQL para a linguagem detectada." }
|
|
79
|
-
},
|
|
80
|
-
"security_requirement": "Requisito de Segurança",
|
|
81
|
-
"encrypted_secrets": "Segredos Criptografados",
|
|
82
|
-
"add_secrets_at": "Adicionar segredos em:",
|
|
83
|
-
"section4_num": "04. Exemplos Estruturais",
|
|
84
|
-
"section4_title": "Cenários de Stacks Padrão",
|
|
85
|
-
"validated_output": "Saída Validada"
|
|
207
|
+
"quality": {
|
|
208
|
+
"section_title": "Desenvolvimento e qualidade",
|
|
209
|
+
"intro": "O projeto inclui uma suíte de regressão nas áreas historicamente mais frágeis:",
|
|
210
|
+
"items": [
|
|
211
|
+
"tratamento de substituições de configuração",
|
|
212
|
+
"deteção do ramo predefinido",
|
|
213
|
+
"seleção do ramo de implementação",
|
|
214
|
+
"ramo de produção Netlify",
|
|
215
|
+
"comportamento de fusão inteligente",
|
|
216
|
+
"procura de scripts de build por pacote em monorepo",
|
|
217
|
+
"deteção da configuração de release",
|
|
218
|
+
"geração do workflow de release",
|
|
219
|
+
"testes smoke da CLI em dry-run"
|
|
220
|
+
],
|
|
221
|
+
"commands_title": "Executar verificações localmente",
|
|
222
|
+
"commands": [
|
|
223
|
+
"npm test",
|
|
224
|
+
"npm run test:smoke",
|
|
225
|
+
"node bin/ciflow.js audit --path .",
|
|
226
|
+
"node bin/ciflow.js upgrade --path . --dry-run"
|
|
227
|
+
],
|
|
228
|
+
"repo_note": "Com o pacote publicado, o executável é cistack. No repositório cistack, o ponto de entrada local é bin/ciflow.js."
|
|
86
229
|
},
|
|
87
230
|
"footer": {
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"open_source": "Código Aberto",
|
|
94
|
-
"footer_desc": "Geração automatizada de infraestrutura CI/CD para a web moderna. Construído com precisão para desenvolvedores que valorizam visibilidade e segurança em seus pipelines de deploy.",
|
|
95
|
-
"global_install": "Instalação_Global",
|
|
96
|
-
"copyright": "CISTACK ENGINE — TODOS OS PIPELINES REIFICADOS."
|
|
231
|
+
"license": "Licença MIT",
|
|
232
|
+
"tagline": "Geração de workflows CI/CD a partir do repositório que já tem.",
|
|
233
|
+
"architect_credit": "Criado por",
|
|
234
|
+
"architect_name": "Edwin Vakayil",
|
|
235
|
+
"copyright_suffix": "cistack. Todos os direitos reservados quando aplicável."
|
|
97
236
|
},
|
|
98
237
|
"install_toggle": {
|
|
99
238
|
"recommended": "recomendado",
|
|
100
239
|
"npm_global": "npm install -g",
|
|
101
240
|
"recommended_badge": "Recomendado",
|
|
102
241
|
"global_badge": "Global",
|
|
103
|
-
"npx_desc": "
|
|
104
|
-
"npm_desc": "
|
|
242
|
+
"npx_desc": "Obtém sempre a versão mais recente. Sem instalação global.",
|
|
243
|
+
"npm_desc": "Ideal se usar o cistack em muitos repositórios."
|
|
105
244
|
},
|
|
106
245
|
"terminal": {
|
|
107
246
|
"label": "TERMINAL",
|
|
108
247
|
"mission": "MISSÃO_NÚCLEO // L_02",
|
|
109
|
-
"project_scanned": "✔ Projeto
|
|
110
|
-
"stack_detected": "✔ Stack
|
|
111
|
-
"detected_stack": "Stack
|
|
248
|
+
"project_scanned": "✔ Projeto analisado",
|
|
249
|
+
"stack_detected": "✔ Stack detetado",
|
|
250
|
+
"detected_stack": "Stack detetado",
|
|
112
251
|
"languages": "Linguagens:",
|
|
113
252
|
"frameworks": "Frameworks:",
|
|
114
|
-
"hosting": "
|
|
253
|
+
"hosting": "Alojamento:",
|
|
115
254
|
"testing": "Testes:",
|
|
116
|
-
"release_tool": "Ferramenta release:",
|
|
117
|
-
"look_correct": "
|
|
118
|
-
"generated_workflows": "✔ Gerados 3
|
|
119
|
-
"smart_merged": "↻
|
|
255
|
+
"release_tool": "Ferramenta de release:",
|
|
256
|
+
"look_correct": "Está correto? Gerar o pipeline com estes parâmetros? Sim",
|
|
257
|
+
"generated_workflows": "✔ Gerados 3 workflow(s) de CI",
|
|
258
|
+
"smart_merged": "↻ Fusão inteligente: ci.yml",
|
|
120
259
|
"updated_on": "atualizado \"on\" de nível superior",
|
|
121
260
|
"updated_concurrency": "atualizado \"concurrency\" de nível superior",
|
|
122
261
|
"added_lint": "adicionado job \"lint\"",
|
|
123
|
-
"updated_build": "job \"build\" →
|
|
124
|
-
"updated_needs": "job \"build\" →
|
|
125
|
-
"added_checkout": "job \"build\" →
|
|
126
|
-
"added_node": "job \"build\" →
|
|
127
|
-
"updated_step_build": "job \"build\" →
|
|
128
|
-
"added_upload": "job \"build\" →
|
|
262
|
+
"updated_build": "job \"build\" → atualizado \"name\"",
|
|
263
|
+
"updated_needs": "job \"build\" → atualizado \"needs\"",
|
|
264
|
+
"added_checkout": "job \"build\" → adicionado passo \"Checkout code\"",
|
|
265
|
+
"added_node": "job \"build\" → adicionado passo \"Set up Node.js\"",
|
|
266
|
+
"updated_step_build": "job \"build\" → atualizado passo \"Build\"",
|
|
267
|
+
"added_upload": "job \"build\" → adicionado passo \"Upload build artifact\"",
|
|
129
268
|
"written_deploy": "Escrito: deploy.yml",
|
|
130
269
|
"written_security": "Escrito: security.yml",
|
|
131
270
|
"written_dependabot": "Escrito: .github/dependabot.yml",
|
|
132
|
-
"done_msg": "Pronto!
|
|
133
|
-
"workflows_path": "
|
|
271
|
+
"done_msg": "Pronto! O seu pipeline GitHub Actions está preparado.",
|
|
272
|
+
"workflows_path": "Workflows → cistack/.github/workflows",
|
|
134
273
|
"dependabot_path": "Dependabot → cistack/.github/dependabot.yml",
|
|
135
|
-
"processing": "
|
|
274
|
+
"processing": "A processar saída…"
|
|
136
275
|
}
|
|
137
276
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const DICTIONARY_DIR = path.join(__dirname, "../dictionaries");
|
|
7
|
+
const SOURCE = "en.json";
|
|
8
|
+
|
|
9
|
+
function keyPaths(value, prefix = "") {
|
|
10
|
+
if (value === null || typeof value !== "object") {
|
|
11
|
+
return [prefix || "(root)"];
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
if (value.length === 0) return [prefix + "[]"];
|
|
15
|
+
return value.flatMap((item, i) => keyPaths(item, `${prefix}[${i}]`));
|
|
16
|
+
}
|
|
17
|
+
const keys = Object.keys(value).sort();
|
|
18
|
+
if (keys.length === 0) return [prefix || "(empty)"];
|
|
19
|
+
return keys.flatMap((k) => keyPaths(value[k], prefix ? `${prefix}.${k}` : k));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const sourceRaw = fs.readFileSync(path.join(DICTIONARY_DIR, SOURCE), "utf8");
|
|
23
|
+
const en = JSON.parse(sourceRaw);
|
|
24
|
+
const enPaths = new Set(keyPaths(en).sort());
|
|
25
|
+
|
|
26
|
+
let failed = false;
|
|
27
|
+
for (const file of fs.readdirSync(DICTIONARY_DIR)) {
|
|
28
|
+
if (!file.endsWith(".json") || file === SOURCE) continue;
|
|
29
|
+
const data = JSON.parse(fs.readFileSync(path.join(DICTIONARY_DIR, file), "utf8"));
|
|
30
|
+
const paths = new Set(keyPaths(data).sort());
|
|
31
|
+
const missing = [...enPaths].filter((p) => !paths.has(p));
|
|
32
|
+
const extra = [...paths].filter((p) => !enPaths.has(p));
|
|
33
|
+
if (missing.length || extra.length) {
|
|
34
|
+
console.error(`\n${file}:`);
|
|
35
|
+
if (missing.length) console.error(" missing:", missing.slice(0, 8).join(", "), missing.length > 8 ? `… +${missing.length - 8}` : "");
|
|
36
|
+
if (extra.length) console.error(" extra:", extra.slice(0, 8).join(", "), extra.length > 8 ? `… +${extra.length - 8}` : "");
|
|
37
|
+
failed = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (failed) {
|
|
42
|
+
console.error("\nvalidate-i18n: locale key paths must match en.json\n");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
console.log("validate-i18n: all locales match en.json key paths");
|
package/src/index.js
CHANGED
|
@@ -230,34 +230,33 @@ class CIFlow {
|
|
|
230
230
|
_printSummary(config, releaseInfo, envVars, monorepoPackages) {
|
|
231
231
|
const { hosting, frameworks, languages, testing } = config;
|
|
232
232
|
const line = (label, value, reasons = []) => {
|
|
233
|
-
console.log(` ${chalk.dim(label.padEnd(20))} ${chalk.cyan(value || chalk.italic('
|
|
233
|
+
console.log(` ${chalk.dim(label.padEnd(20))} ${chalk.cyan(value || chalk.italic('None'))}`);
|
|
234
234
|
if (this.explain && reasons && reasons.length > 0) {
|
|
235
235
|
for (const reason of reasons) {
|
|
236
|
-
console.log(`
|
|
236
|
+
console.log(` ${chalk.dim('-')} ${chalk.gray(reason)}`);
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
};
|
|
240
240
|
|
|
241
|
-
console.log('\n' + chalk.bold('
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
line('
|
|
245
|
-
line('
|
|
246
|
-
line('
|
|
247
|
-
line('
|
|
248
|
-
line('Release tool:', releaseInfo ? releaseInfo.tool : 'none', releaseInfo && releaseInfo.reasons);
|
|
241
|
+
console.log('\n' + chalk.bold(' Stack detection summary'));
|
|
242
|
+
|
|
243
|
+
line('Languages:', languages.map((l) => l.name).join(', '), languages[0] && languages[0].reasons);
|
|
244
|
+
line('Frameworks:', frameworks.map((f) => f.name).join(', '), frameworks[0] && frameworks[0].reasons);
|
|
245
|
+
line('Hosting:', hosting.map((h) => h.name).join(', ') || 'None', hosting[0] && hosting[0].reasons);
|
|
246
|
+
line('Testing:', testing.map((t) => t.name).join(', ') || 'None', testing[0] && testing[0].reasons);
|
|
247
|
+
line('Release tool:', releaseInfo ? releaseInfo.tool : 'None', releaseInfo && releaseInfo.reasons);
|
|
249
248
|
|
|
250
249
|
if (monorepoPackages.length > 0) {
|
|
251
|
-
line('Monorepo
|
|
250
|
+
line('Monorepo packages:', monorepoPackages.map((p) => p.name).join(', '));
|
|
252
251
|
}
|
|
253
252
|
|
|
254
253
|
if (envVars.sourceFile) {
|
|
255
|
-
line('
|
|
254
|
+
line('Environment file:', envVars.sourceFile);
|
|
256
255
|
if (envVars.secrets.length > 0) {
|
|
257
256
|
line(' Secrets:', envVars.secrets.join(', '));
|
|
258
257
|
}
|
|
259
258
|
if (envVars.public.length > 0) {
|
|
260
|
-
line(' Public
|
|
259
|
+
line(' Public variables:', envVars.public.join(', '));
|
|
261
260
|
}
|
|
262
261
|
}
|
|
263
262
|
|