jarvis-ai-framework 2.0.0 → 2.1.1
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/AGENTS.md +12 -9
- package/agents/AGENTS.md +9 -1
- package/agents/README.md +2 -2
- package/agents/engineering/data/eng.data-engineer.agent.md +2 -2
- package/agents/engineering/eng.agent.md +4 -6
- package/agents/engineering/eng.bug-hunter.md +10 -5
- package/agents/engineering/eng.cybersecurity.agent.md +2 -4
- package/agents/engineering/eng.dev-code-reviewer.md +4 -0
- package/agents/engineering/eng.docs-writer.md +3 -3
- package/agents/engineering/eng.frontend.agent.md +17 -8
- package/agents/engineering/eng.rpa.agent.md +3 -5
- package/agents/engineering/eng.ux-designer.agent.md +4 -0
- package/agents/engineering/qa/eng.qa.cypress-specialist.md +8 -5
- package/agents/engineering/qa/eng.qa.quality-champion-task-agent.md +4 -0
- package/agents/engineering/qa/eng.qa.quality-strategist.md +18 -8
- package/agents/engineering/qa/eng.qa.test-architect.md +17 -6
- package/agents/engineering/qa/eng.qa.test-planner.md +17 -8
- package/agents/engineering/qa/eng.qa.testing-engineer.md +26 -9
- package/agents/product/prod.discovery-interviewer.md +22 -3
- package/agents/product/prod.pm-checker.md +4 -0
- package/bin/commands/map.js +43 -0
- package/bin/commands/tokens.js +93 -0
- package/bin/jarvis.js +10 -0
- package/bin/lib/config/constants.js +11 -0
- package/bin/lib/core/profile-filter.js +113 -0
- package/bin/lib/core/scanner.js +2 -2
- package/bin/lib/core/token-report.js +90 -0
- package/bin/lib/flow-map/index.js +65 -0
- package/bin/lib/flow-map/parse.js +217 -0
- package/bin/lib/flow-map/render.js +86 -0
- package/bin/lib/flow-map/tree.js +199 -0
- package/members.md +1 -1
- package/package.json +4 -2
- package/rules/AGENTS.md +18 -7
- package/rules/engineering/eng-rules.md +2 -12
- package/rules/engineering/eng-security-rules.md +1 -2
- package/rules/engineering/eng.integrations-rules.md +0 -4
- package/rules/engineering/eng.skills-rules.md +0 -4
- package/rules/engineering/eng.specializations-rules.md +0 -4
- package/rules/product/README.md +1 -0
- package/rules/product/prod-rules.md +1 -4
- package/rules/product/prod.spec-rules.md +0 -4
- package/rules/rtk-rules.md +0 -1
- package/{rules → rules-on-demand}/engineering/eng.breakdown-subtasks-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.plan-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.pr-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.pre-pr-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.start-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.tech-spec-rules.md +1 -2
- package/{rules → rules-on-demand}/engineering/eng.work-rules.md +0 -4
- package/skills/AGENTS.md +22 -21
- package/skills/SKILLS-ROADMAP.md +0 -4
- package/skills/eng-ai-engineer/SKILL.md +6 -0
- package/skills/eng-backend/SKILL.md +6 -0
- package/skills/eng-backend-arch-c4/SKILL.md +10 -4
- package/skills/eng-backend-microservices-trace/SKILL.md +6 -0
- package/skills/eng-backend-nestjs/SKILL.md +16 -461
- package/skills/eng-backend-nestjs/references/1-arquitetura-modulos.md +54 -0
- package/skills/eng-backend-nestjs/references/2-guards-autenticacao.md +118 -0
- package/skills/eng-backend-nestjs/references/3-interceptors-pipes-filters.md +113 -0
- package/skills/eng-backend-nestjs/references/4-config-logging.md +61 -0
- package/skills/eng-backend-nestjs/references/5-testes.md +83 -0
- package/skills/eng-backend-nestjs/references/6-problemas-comuns.md +53 -0
- package/skills/eng-backend-rabbitmq/SKILL.md +15 -298
- package/skills/eng-backend-rabbitmq/references/1-referencia-endpoints.md +28 -0
- package/skills/eng-backend-rabbitmq/references/2-codigo-consumer-producer.md +90 -0
- package/skills/eng-backend-rabbitmq/references/3-arquiteturas-comuns.md +101 -0
- package/skills/eng-backend-rabbitmq/references/4-troubleshooting.md +93 -0
- package/skills/eng-data-bi/SKILL.md +6 -0
- package/skills/eng-data-debug/SKILL.md +6 -0
- package/skills/eng-data-engineer/SKILL.md +16 -7
- package/skills/eng-data-onboard/SKILL.md +6 -0
- package/skills/eng-data-orchestrator/SKILL.md +6 -0
- package/skills/eng-devops-performance-engineer/SKILL.md +6 -0
- package/skills/eng-frontend/SKILL.md +6 -0
- package/skills/eng-frontend-design-system/SKILL.md +13 -479
- package/skills/eng-frontend-design-system/references/1-estrutura-pacote.md +57 -0
- package/skills/eng-frontend-design-system/references/2-tokens.md +116 -0
- package/skills/eng-frontend-design-system/references/3-componentes.md +165 -0
- package/skills/eng-frontend-design-system/references/4-storybook.md +85 -0
- package/skills/eng-frontend-design-system/references/5-auditoria-versionamento.md +76 -0
- package/skills/eng-frontend-microfrontend/SKILL.md +17 -457
- package/skills/eng-frontend-microfrontend/references/1-criando-remote.md +109 -0
- package/skills/eng-frontend-microfrontend/references/2-configurando-shell.md +70 -0
- package/skills/eng-frontend-microfrontend/references/3-contratos-interface.md +73 -0
- package/skills/eng-frontend-microfrontend/references/4-shared-dependencies.md +48 -0
- package/skills/eng-frontend-microfrontend/references/5-event-bus.md +59 -0
- package/skills/eng-frontend-microfrontend/references/6-monorepo-deploy.md +77 -0
- package/skills/eng-frontend-microfrontend/references/7-troubleshooting.md +45 -0
- package/skills/eng-global-browser-extension-builder/SKILL.md +6 -0
- package/skills/eng-global-docs-write/SKILL.md +10 -5
- package/skills/eng-global-jira-comment/SKILL.md +6 -0
- package/skills/eng-global-pr/SKILL.md +7 -1
- package/skills/eng-global-task-comment/SKILL.md +6 -0
- package/skills/eng-qa-a11y-audit/SKILL.md +10 -4
- package/skills/eng-qa-bug-report/SKILL.md +18 -230
- package/skills/eng-qa-bug-report/references/1-integracao-task-managers.md +148 -0
- package/skills/eng-qa-bug-report/references/2-exemplos-de-uso.md +46 -0
- package/skills/eng-qa-bug-report/references/3-bug-to-test.md +45 -0
- package/skills/eng-qa-cypress-e2e/SKILL.md +6 -0
- package/skills/eng-qa-dev-guide/SKILL.md +9 -1
- package/skills/eng-qa-e2e/SKILL.md +9 -3
- package/skills/eng-qa-e2e-spec-writer/SKILL.md +15 -9
- package/skills/eng-qa-exploratory/SKILL.md +16 -9
- package/skills/eng-qa-gate/SKILL.md +11 -5
- package/skills/eng-qa-gate/assets/checklist-validacao.md +1 -1
- package/skills/eng-qa-graphql-contract/SKILL.md +9 -3
- package/skills/eng-qa-quality-report/SKILL.md +9 -3
- package/skills/eng-qa-test-plan/SKILL.md +6 -0
- package/skills/eng-qa-testsprite/SKILL.md +10 -4
- package/skills/eng-qa-unit-test/SKILL.md +7 -1
- package/skills/eng-scraper/SKILL.md +12 -436
- package/skills/eng-scraper/references/1-puppeteer.md +140 -0
- package/skills/eng-scraper/references/2-playwright-cheerio-pdf.md +82 -0
- package/skills/eng-scraper/references/3-anti-bot.md +94 -0
- package/skills/eng-scraper/references/4-resiliencia-etl-monitoramento.md +137 -0
- package/skills/eng-scraper-robot-builder/SKILL.md +6 -0
- package/skills/eng-security-cybersecurity/SKILL.md +13 -409
- package/skills/eng-security-cybersecurity/references/1-owasp-top-10.md +331 -0
- package/skills/eng-security-cybersecurity/references/2-secrets-management.md +31 -0
- package/skills/eng-security-cybersecurity/references/3-input-validation.md +43 -0
- package/skills/eng-security-cybersecurity/references/4-compliance.md +20 -0
- package/skills/eng-security-patch/SKILL.md +6 -0
- package/skills/eng-security-threat-model/SKILL.md +6 -0
- package/skills/eng-security-triage/SKILL.md +6 -0
- package/skills/jarvis-context-detect/SKILL.md +6 -0
- package/skills/jarvis-create-specialization/SKILL.md +6 -0
- package/skills/jarvis-docs-central/SKILL.md +6 -0
- package/skills/jarvis-docs-index/SKILL.md +10 -2
- package/skills/jarvis-evolution-architect/SKILL.md +439 -0
- package/skills/jarvis-evolution-architect/references/exemplos.md +297 -0
- package/skills/jarvis-evolution-architect/references/guia-de-uso.md +355 -0
- package/skills/jarvis-evolution-architect/references/lentes-e-conceitos.md +292 -0
- package/skills/jarvis-evolution-architect/references/visao-geral.md +272 -0
- package/skills/jarvis-init/SKILL.md +14 -7
- package/skills/jarvis-list-specializations/SKILL.md +6 -0
- package/skills/jarvis-report-issue/SKILL.md +6 -0
- package/skills/product-roadmap-report/SKILL.md +8 -0
- package/skills/product-specs/SKILL.md +9 -0
- package/skills/product-specs-update/SKILL.md +6 -0
- package/taxonomy.md +12 -12
- package/templates/AGENTS.md +2 -0
- package/templates/engineering/tech-spec-delivery-template.md +179 -0
- package/workflows/AGENTS.md +12 -2
- package/workflows/README.md +18 -16
- package/workflows/all-tools.md +7 -1
- package/workflows/engineering/data/data.contract.md +8 -0
- package/workflows/engineering/data/data.new-pipeline.md +10 -0
- package/workflows/engineering/eng.breakdown-subtasks.md +9 -0
- package/workflows/engineering/eng.bug-audit.md +9 -2
- package/workflows/engineering/eng.build-tech-spec.md +17 -146
- package/workflows/engineering/eng.create-ard-from-code.md +8 -0
- package/workflows/engineering/eng.create-ard.md +8 -0
- package/workflows/engineering/eng.create-rfc.md +7 -0
- package/workflows/engineering/eng.debug.md +3 -3
- package/workflows/engineering/eng.docs.md +9 -0
- package/workflows/engineering/eng.light-arch.md +7 -0
- package/workflows/engineering/eng.plan.md +15 -2
- package/workflows/engineering/eng.pr.md +19 -7
- package/workflows/engineering/eng.pre-pr.md +27 -1
- package/workflows/engineering/eng.review.md +13 -0
- package/workflows/engineering/eng.rpa.robot.md +16 -0
- package/workflows/engineering/eng.security-audit.md +7 -0
- package/workflows/engineering/eng.security-incident.md +6 -0
- package/workflows/engineering/eng.security-pipeline.md +9 -0
- package/workflows/engineering/eng.security-review.md +6 -0
- package/workflows/engineering/eng.start.md +22 -6
- package/workflows/engineering/eng.work.md +18 -2
- package/workflows/engineering/frontend/eng.frontend-component.md +7 -0
- package/workflows/engineering/frontend/eng.frontend-perf-audit.md +8 -0
- package/workflows/engineering/frontend/eng.frontend-review.md +8 -0
- package/workflows/engineering/qa/eng.qa-dev-quality-guide.md +6 -0
- package/workflows/engineering/qa/eng.qa-e2e-test-generation.md +6 -0
- package/workflows/engineering/qa/eng.qa-exploratory-session.md +8 -0
- package/workflows/engineering/qa/eng.qa-quality-gate-validation.md +7 -0
- package/workflows/engineering/qa/eng.qa-quality-report.md +7 -0
- package/workflows/engineering/qa/eng.qa-refinement-entry.md +7 -0
- package/workflows/engineering/qa/eng.qa-release-signoff.md +6 -0
- package/workflows/engineering/qa/eng.qa-sprint-planning.md +6 -0
- package/workflows/product/prod.roadmap.preview.md +9 -0
- package/workflows/product/prod.spec.ard.md +97 -0
- package/workflows/product/prod.spec.breakdown.md +10 -0
- package/workflows/product/prod.spec.clarify.md +8 -2
- package/workflows/product/prod.spec.discovery.md +10 -0
- package/workflows/product/prod.spec.epic.md +8 -0
- package/workflows/product/prod.spec.frd.md +7 -0
- package/workflows/product/prod.spec.issue.md +6 -0
- package/workflows/product/prod.spec.md +15 -1
- package/workflows/product/prod.spec.prd.md +7 -0
- package/workflows/taxonomy.md +58 -6
- package/workflows/warm-up.md +24 -9
- package/rules/engineering/eng.downstream-flow-rules.md +0 -297
|
@@ -85,465 +85,19 @@ O que será feito?
|
|
|
85
85
|
|
|
86
86
|
---
|
|
87
87
|
|
|
88
|
-
##
|
|
88
|
+
## Referências (leia só o tema que a tarefa pedir)
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
Leia **só** o arquivo do tema que a tarefa pedir; o restante fica fora do contexto.
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
│ └── exposed/ ← o que será exposto via Module Federation
|
|
102
|
-
│ ├── index.ts ← re-exporta tudo que é público
|
|
103
|
-
│ └── RemoteApp.tsx ← componente raiz exposto ao shell
|
|
104
|
-
├── vite.config.ts ← ou webpack.config.ts
|
|
105
|
-
├── package.json
|
|
106
|
-
└── tsconfig.json
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Por que `bootstrap.ts` é obrigatório?
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
// src/index.ts — entry point síncrono
|
|
113
|
-
import('./bootstrap') // import() dinâmico é necessário para Module Federation funcionar
|
|
114
|
-
|
|
115
|
-
// src/bootstrap.ts — inicialização real
|
|
116
|
-
import React from 'react'
|
|
117
|
-
import ReactDOM from 'react-dom/client'
|
|
118
|
-
import App from './App'
|
|
119
|
-
|
|
120
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
121
|
-
<React.StrictMode>
|
|
122
|
-
<App />
|
|
123
|
-
</React.StrictMode>
|
|
124
|
-
)
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
> Sem o `bootstrap.ts`, o eager consumption de shared libs causa erro em runtime.
|
|
128
|
-
|
|
129
|
-
### Configuração Vite (vite-plugin-federation)
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
// vite.config.ts do remote
|
|
133
|
-
import { defineConfig } from 'vite'
|
|
134
|
-
import react from '@vitejs/plugin-react'
|
|
135
|
-
import federation from '@originjs/vite-plugin-federation'
|
|
136
|
-
|
|
137
|
-
export default defineConfig({
|
|
138
|
-
plugins: [
|
|
139
|
-
react(),
|
|
140
|
-
federation({
|
|
141
|
-
name: '{nome-remote}', // identificador único do remote
|
|
142
|
-
filename: 'remoteEntry.js', // arquivo gerado
|
|
143
|
-
exposes: {
|
|
144
|
-
'./App': './src/exposed/RemoteApp', // o que o shell pode importar
|
|
145
|
-
'./routes': './src/exposed/routes', // rotas para shell carregar
|
|
146
|
-
},
|
|
147
|
-
shared: {
|
|
148
|
-
react: { singleton: true, requiredVersion: '^18.0.0' },
|
|
149
|
-
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
|
|
150
|
-
'react-router-dom': { singleton: true },
|
|
151
|
-
// design system — sempre singleton para evitar instâncias duplicadas
|
|
152
|
-
'@{org}/design-system': { singleton: true },
|
|
153
|
-
},
|
|
154
|
-
}),
|
|
155
|
-
],
|
|
156
|
-
build: {
|
|
157
|
-
target: 'esnext',
|
|
158
|
-
minify: false, // facilita debug; ativar em prod via CI flag
|
|
159
|
-
cssCodeSplit: false, // evita problemas com CSS em remotes
|
|
160
|
-
},
|
|
161
|
-
})
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Modo standalone (obrigatório para dev local)
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
// src/App.tsx — funciona sem shell
|
|
168
|
-
import { BrowserRouter } from 'react-router-dom'
|
|
169
|
-
import { AppRoutes } from './routes'
|
|
170
|
-
|
|
171
|
-
export default function App() {
|
|
172
|
-
return (
|
|
173
|
-
<BrowserRouter>
|
|
174
|
-
<AppRoutes />
|
|
175
|
-
</BrowserRouter>
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
```json
|
|
181
|
-
// package.json do remote
|
|
182
|
-
{
|
|
183
|
-
"scripts": {
|
|
184
|
-
"dev": "vite --port 3001", // standalone
|
|
185
|
-
"dev:federated": "vite --port 3001 --mode federated", // com Module Federation ativo
|
|
186
|
-
"build": "vite build",
|
|
187
|
-
"preview": "vite preview --port 3001"
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
|
|
194
|
-
## Configurando o Shell
|
|
195
|
-
|
|
196
|
-
```typescript
|
|
197
|
-
// vite.config.ts do shell
|
|
198
|
-
import federation from '@originjs/vite-plugin-federation'
|
|
199
|
-
|
|
200
|
-
export default defineConfig({
|
|
201
|
-
plugins: [
|
|
202
|
-
react(),
|
|
203
|
-
federation({
|
|
204
|
-
name: 'shell',
|
|
205
|
-
remotes: {
|
|
206
|
-
'{nome-remote}': 'http://localhost:3001/assets/remoteEntry.js',
|
|
207
|
-
// Em produção, usar variável de ambiente:
|
|
208
|
-
// '{nome-remote}': process.env.VITE_REMOTE_URL_NOME_REMOTE,
|
|
209
|
-
},
|
|
210
|
-
shared: {
|
|
211
|
-
react: { singleton: true },
|
|
212
|
-
'react-dom': { singleton: true },
|
|
213
|
-
'react-router-dom': { singleton: true },
|
|
214
|
-
'@{org}/design-system': { singleton: true },
|
|
215
|
-
},
|
|
216
|
-
}),
|
|
217
|
-
],
|
|
218
|
-
})
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Lazy loading de remotes no shell
|
|
222
|
-
|
|
223
|
-
```typescript
|
|
224
|
-
// src/routes/index.tsx — shell monta remotes por rota
|
|
225
|
-
import { lazy, Suspense } from 'react'
|
|
226
|
-
import { Routes, Route } from 'react-router-dom'
|
|
227
|
-
|
|
228
|
-
// Tipagem do remote (importar do contrato de interface)
|
|
229
|
-
const RemoteApp = lazy(() =>
|
|
230
|
-
import('{nome-remote}/App').then((m) => ({ default: m.default }))
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
function ErrorFallback({ error }: { error: Error }) {
|
|
234
|
-
return (
|
|
235
|
-
<div role="alert">
|
|
236
|
-
<p>Falha ao carregar módulo. <button onClick={() => window.location.reload()}>Tentar novamente</button></p>
|
|
237
|
-
</div>
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export function ShellRoutes() {
|
|
242
|
-
return (
|
|
243
|
-
<Routes>
|
|
244
|
-
<Route
|
|
245
|
-
path="/{caminho-remote}/*"
|
|
246
|
-
element={
|
|
247
|
-
<Suspense fallback={<div>Carregando...</div>}>
|
|
248
|
-
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
|
249
|
-
<RemoteApp />
|
|
250
|
-
</ErrorBoundary>
|
|
251
|
-
</Suspense>
|
|
252
|
-
}
|
|
253
|
-
/>
|
|
254
|
-
</Routes>
|
|
255
|
-
)
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## Contratos de Interface
|
|
262
|
-
|
|
263
|
-
O contrato é o **acordo formal** entre shell e remote — define o que o remote expõe e o que espera receber.
|
|
264
|
-
|
|
265
|
-
### Estrutura do pacote de contratos
|
|
266
|
-
|
|
267
|
-
```
|
|
268
|
-
packages/
|
|
269
|
-
└── mfe-contracts/
|
|
270
|
-
├── src/
|
|
271
|
-
│ ├── remotes/
|
|
272
|
-
│ │ ├── {nome-remote}.contract.ts ← contrato do remote
|
|
273
|
-
│ │ └── index.ts
|
|
274
|
-
│ ├── shell/
|
|
275
|
-
│ │ └── shell.context.ts ← o que o shell injeta nos remotes
|
|
276
|
-
│ └── index.ts
|
|
277
|
-
├── package.json
|
|
278
|
-
└── tsconfig.json
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
### Definindo um contrato
|
|
282
|
-
|
|
283
|
-
```typescript
|
|
284
|
-
// packages/mfe-contracts/src/remotes/{nome-remote}.contract.ts
|
|
285
|
-
|
|
286
|
-
// O que o remote expõe ao shell
|
|
287
|
-
export interface {NomeRemote}Exports {
|
|
288
|
-
default: React.ComponentType<{NomeRemote}Props>
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Props que o shell passa ao montar o remote
|
|
292
|
-
export interface {NomeRemote}Props {
|
|
293
|
-
basePath: string
|
|
294
|
-
onNavigate?: (path: string) => void
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Eventos que o remote emite no event bus
|
|
298
|
-
export interface {NomeRemote}Events {
|
|
299
|
-
'{nome-remote}:action-completed': { id: string; result: unknown }
|
|
300
|
-
'{nome-remote}:error': { code: string; message: string }
|
|
301
|
-
}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
### Contexto do shell (injetado em todos os remotes)
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
307
|
-
// packages/mfe-contracts/src/shell/shell.context.ts
|
|
308
|
-
export interface ShellContext {
|
|
309
|
-
user: {
|
|
310
|
-
id: string
|
|
311
|
-
name: string
|
|
312
|
-
permissions: string[]
|
|
313
|
-
}
|
|
314
|
-
theme: 'light' | 'dark'
|
|
315
|
-
locale: string
|
|
316
|
-
onNavigate: (path: string) => void
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Hook disponível em todos os remotes
|
|
320
|
-
export const ShellContextReact = React.createContext<ShellContext | null>(null)
|
|
321
|
-
|
|
322
|
-
export function useShellContext(): ShellContext {
|
|
323
|
-
const ctx = React.useContext(ShellContextReact)
|
|
324
|
-
if (!ctx) throw new Error('useShellContext deve ser usado dentro do ShellProvider')
|
|
325
|
-
return ctx
|
|
326
|
-
}
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
---
|
|
330
|
-
|
|
331
|
-
## Shared Dependencies
|
|
332
|
-
|
|
333
|
-
### Regras críticas
|
|
334
|
-
|
|
335
|
-
```
|
|
336
|
-
singleton: true → apenas uma instância em toda a aplicação (obrigatório para React, React DOM)
|
|
337
|
-
eager: false → NÃO usar eager para shared libs (causa bootstrap error)
|
|
338
|
-
requiredVersion → sempre declarar para evitar conflitos silenciosos
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### Checklist de shared deps
|
|
342
|
-
|
|
343
|
-
```typescript
|
|
344
|
-
shared: {
|
|
345
|
-
// Core React — sempre singleton
|
|
346
|
-
'react': { singleton: true, requiredVersion: '^18.0.0' },
|
|
347
|
-
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
|
|
348
|
-
|
|
349
|
-
// Router — singleton para evitar múltiplos contextos de roteamento
|
|
350
|
-
'react-router-dom': { singleton: true, requiredVersion: '^6.0.0' },
|
|
351
|
-
|
|
352
|
-
// Design system — singleton obrigatório (CSS e contexto de tema)
|
|
353
|
-
'@{org}/design-system': { singleton: true },
|
|
354
|
-
|
|
355
|
-
// Estado global — singleton se compartilhado entre remotes
|
|
356
|
-
'zustand': { singleton: true },
|
|
357
|
-
|
|
358
|
-
// NÃO compartilhar: libs utilitárias pequenas (date-fns, lodash)
|
|
359
|
-
// → melhor cada remote ter sua versão para evitar lock de versão
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
### Conflito de versão (diagnóstico)
|
|
364
|
-
|
|
365
|
-
```bash
|
|
366
|
-
# Ver qual versão de react cada remote está carregando
|
|
367
|
-
# No DevTools → Network → filtrar por "remoteEntry.js"
|
|
368
|
-
# Abrir arquivo e buscar por "shared"
|
|
369
|
-
|
|
370
|
-
# Via CLI — verificar versões no monorepo
|
|
371
|
-
pnpm list react --recursive
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
---
|
|
375
|
-
|
|
376
|
-
## Event Bus
|
|
377
|
-
|
|
378
|
-
Remote e shell se comunicam via evento — nunca via import direto.
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
// packages/mfe-contracts/src/event-bus.ts
|
|
382
|
-
|
|
383
|
-
type EventHandler<T> = (payload: T) => void
|
|
384
|
-
|
|
385
|
-
class MFEEventBus {
|
|
386
|
-
private listeners = new Map<string, Set<EventHandler<unknown>>>()
|
|
387
|
-
|
|
388
|
-
emit<T>(event: string, payload: T): void {
|
|
389
|
-
this.listeners.get(event)?.forEach((handler) => handler(payload as unknown))
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
on<T>(event: string, handler: EventHandler<T>): () => void {
|
|
393
|
-
if (!this.listeners.has(event)) {
|
|
394
|
-
this.listeners.set(event, new Set())
|
|
395
|
-
}
|
|
396
|
-
this.listeners.get(event)!.add(handler as EventHandler<unknown>)
|
|
397
|
-
|
|
398
|
-
// retorna função de cleanup
|
|
399
|
-
return () => this.listeners.get(event)?.delete(handler as EventHandler<unknown>)
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Singleton global — compartilhado via shell context
|
|
404
|
-
export const eventBus = new MFEEventBus()
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
```typescript
|
|
408
|
-
// Uso em um remote
|
|
409
|
-
import { useShellContext } from '@{org}/mfe-contracts'
|
|
410
|
-
|
|
411
|
-
function CheckoutButton({ orderId }: { orderId: string }) {
|
|
412
|
-
const { eventBus } = useShellContext()
|
|
413
|
-
|
|
414
|
-
return (
|
|
415
|
-
<button onClick={() => eventBus.emit('checkout:initiated', { orderId })}>
|
|
416
|
-
Finalizar compra
|
|
417
|
-
</button>
|
|
418
|
-
)
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// Uso no shell — escutar eventos de remotes
|
|
422
|
-
useEffect(() => {
|
|
423
|
-
const unsubscribe = eventBus.on('checkout:initiated', ({ orderId }) => {
|
|
424
|
-
navigate(`/checkout/${orderId}`)
|
|
425
|
-
})
|
|
426
|
-
return unsubscribe
|
|
427
|
-
}, [])
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
## Monorepo Frontend
|
|
433
|
-
|
|
434
|
-
### Estrutura recomendada
|
|
435
|
-
|
|
436
|
-
```
|
|
437
|
-
{repo}/
|
|
438
|
-
├── apps/
|
|
439
|
-
│ ├── shell/ ← host application
|
|
440
|
-
│ ├── {remote-a}/ ← micro frontend A
|
|
441
|
-
│ └── {remote-b}/ ← micro frontend B
|
|
442
|
-
├── packages/
|
|
443
|
-
│ ├── design-system/ ← componentes e tokens compartilhados
|
|
444
|
-
│ ├── mfe-contracts/ ← tipos TypeScript de contratos de interface
|
|
445
|
-
│ └── utils/ ← utilitários compartilhados
|
|
446
|
-
├── pnpm-workspace.yaml
|
|
447
|
-
└── turbo.json
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
```yaml
|
|
451
|
-
# pnpm-workspace.yaml
|
|
452
|
-
packages:
|
|
453
|
-
- 'apps/*'
|
|
454
|
-
- 'packages/*'
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
```json
|
|
458
|
-
// turbo.json
|
|
459
|
-
{
|
|
460
|
-
"pipeline": {
|
|
461
|
-
"build": {
|
|
462
|
-
"dependsOn": ["^build"],
|
|
463
|
-
"outputs": ["dist/**"]
|
|
464
|
-
},
|
|
465
|
-
"dev": {
|
|
466
|
-
"cache": false,
|
|
467
|
-
"persistent": true
|
|
468
|
-
},
|
|
469
|
-
"test": {
|
|
470
|
-
"dependsOn": ["^build"]
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
---
|
|
477
|
-
|
|
478
|
-
## Estratégia de Deploy
|
|
479
|
-
|
|
480
|
-
### Deploy independente (objetivo central do micro frontend)
|
|
481
|
-
|
|
482
|
-
```
|
|
483
|
-
Cada remote tem seu próprio pipeline de CI/CD:
|
|
484
|
-
push → build → test → deploy → atualizar URL no shell (via env var ou config service)
|
|
485
|
-
|
|
486
|
-
Shell NÃO precisa ser re-deployed quando um remote é atualizado.
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
### Variáveis de ambiente por remote
|
|
490
|
-
|
|
491
|
-
```bash
|
|
492
|
-
# .env.production do shell
|
|
493
|
-
VITE_REMOTE_URL_NOME_REMOTE=https://cdn.example.com/nome-remote/remoteEntry.js
|
|
494
|
-
VITE_REMOTE_URL_OUTRO_REMOTE=https://cdn.example.com/outro-remote/remoteEntry.js
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
### Versionamento de remotes
|
|
498
|
-
|
|
499
|
-
```
|
|
500
|
-
Sem breaking change na API exposta → patch ou minor → URL permanece a mesma
|
|
501
|
-
Breaking change na API exposta (props, eventos) → major → nova URL + migração no shell
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
---
|
|
505
|
-
|
|
506
|
-
## Troubleshooting
|
|
507
|
-
|
|
508
|
-
### Erro: "Shared module is not available for eager consumption"
|
|
509
|
-
|
|
510
|
-
```typescript
|
|
511
|
-
// ❌ Causa: eager: true em shared lib com React
|
|
512
|
-
shared: { react: { singleton: true, eager: true } } // NÃO FAZER
|
|
513
|
-
|
|
514
|
-
// ✅ Solução: usar bootstrap.ts com import() dinâmico
|
|
515
|
-
// src/index.ts
|
|
516
|
-
import('./bootstrap') // async bootstrap resolve o problema
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
### Erro: "Remote container is not available"
|
|
520
|
-
|
|
521
|
-
```bash
|
|
522
|
-
# 1. Verificar se o remote está rodando
|
|
523
|
-
curl http://localhost:3001/assets/remoteEntry.js
|
|
524
|
-
|
|
525
|
-
# 2. Verificar CORS no servidor do remote
|
|
526
|
-
# O remoteEntry.js precisa ser acessível pelo shell
|
|
527
|
-
|
|
528
|
-
# 3. Verificar se a URL no shell está correta
|
|
529
|
-
grep -r "remoteEntry" vite.config.ts
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
### Componente do remote não re-renderiza após update de state do shell
|
|
533
|
-
|
|
534
|
-
```typescript
|
|
535
|
-
// Causa provável: contexto do shell não está sendo re-injetado no remote
|
|
536
|
-
// Solução: passar o contexto via props no ponto de montagem, não via módulo compartilhado
|
|
537
|
-
|
|
538
|
-
// ❌ Problemático
|
|
539
|
-
import { useShellStore } from 'shell/store' // import direto entre remote e shell
|
|
540
|
-
|
|
541
|
-
// ✅ Correto
|
|
542
|
-
// Shell passa estado via props ao montar o remote
|
|
543
|
-
<RemoteApp user={currentUser} onNavigate={navigate} />
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
---
|
|
92
|
+
| Tema | Quando ler | Arquivo |
|
|
93
|
+
|------|-----------|---------|
|
|
94
|
+
| Criando um Remote | A tarefa criar um remote novo (estrutura, bootstrap, Vite e modo standalone) | `references/1-criando-remote.md` |
|
|
95
|
+
| Configurando o Shell | A tarefa configurar o shell ou o lazy loading de remotes | `references/2-configurando-shell.md` |
|
|
96
|
+
| Contratos de Interface | A tarefa definir ou alterar contratos entre shell e remotes | `references/3-contratos-interface.md` |
|
|
97
|
+
| Shared Dependencies | A tarefa envolver dependências compartilhadas ou conflito de versão | `references/4-shared-dependencies.md` |
|
|
98
|
+
| Event Bus | A tarefa envolver comunicação entre remotes por eventos | `references/5-event-bus.md` |
|
|
99
|
+
| Monorepo e Estratégia de Deploy | A tarefa envolver a estrutura do monorepo, o deploy independente ou o versionamento de remotes | `references/6-monorepo-deploy.md` |
|
|
100
|
+
| Troubleshooting de Micro Frontend | Houver erro de módulo compartilhado, remote indisponível ou componente que não re-renderiza | `references/7-troubleshooting.md` |
|
|
547
101
|
|
|
548
102
|
## Checklist de Novo Remote
|
|
549
103
|
|
|
@@ -557,6 +111,12 @@ import { useShellStore } from 'shell/store' // import direto entre remote e she
|
|
|
557
111
|
- [ ] URL de deploy configurada via variável de ambiente
|
|
558
112
|
- [ ] Breaking changes documentadas e comunicadas ao time do shell
|
|
559
113
|
|
|
114
|
+
### Skills invocados durante a execução do skill
|
|
115
|
+
|
|
116
|
+
| Passo | Skill | Condição |
|
|
117
|
+
|-------|-------|----------|
|
|
118
|
+
| — | Nenhuma — skill autocontida | — |
|
|
119
|
+
|
|
560
120
|
---
|
|
561
121
|
|
|
562
122
|
## Regras
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Criando um Remote
|
|
2
|
+
|
|
3
|
+
> Parte do skill `eng-frontend-microfrontend`. Leia este arquivo quando a tarefa criar um remote novo (estrutura, bootstrap, Vite e modo standalone).
|
|
4
|
+
|
|
5
|
+
## Criando um Remote
|
|
6
|
+
|
|
7
|
+
### Estrutura de um remote
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
apps/
|
|
11
|
+
└── {nome-remote}/
|
|
12
|
+
├── src/
|
|
13
|
+
│ ├── bootstrap.ts ← entry point async (necessário para Module Federation)
|
|
14
|
+
│ ├── index.ts ← importa e executa bootstrap
|
|
15
|
+
│ ├── App.tsx ← root do remote (para modo standalone)
|
|
16
|
+
│ ├── routes/ ← rotas do remote
|
|
17
|
+
│ ├── components/ ← componentes locais do remote
|
|
18
|
+
│ └── exposed/ ← o que será exposto via Module Federation
|
|
19
|
+
│ ├── index.ts ← re-exporta tudo que é público
|
|
20
|
+
│ └── RemoteApp.tsx ← componente raiz exposto ao shell
|
|
21
|
+
├── vite.config.ts ← ou webpack.config.ts
|
|
22
|
+
├── package.json
|
|
23
|
+
└── tsconfig.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Por que `bootstrap.ts` é obrigatório?
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// src/index.ts — entry point síncrono
|
|
30
|
+
import('./bootstrap') // import() dinâmico é necessário para Module Federation funcionar
|
|
31
|
+
|
|
32
|
+
// src/bootstrap.ts — inicialização real
|
|
33
|
+
import React from 'react'
|
|
34
|
+
import ReactDOM from 'react-dom/client'
|
|
35
|
+
import App from './App'
|
|
36
|
+
|
|
37
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
38
|
+
<React.StrictMode>
|
|
39
|
+
<App />
|
|
40
|
+
</React.StrictMode>
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> Sem o `bootstrap.ts`, o eager consumption de shared libs causa erro em runtime.
|
|
45
|
+
|
|
46
|
+
### Configuração Vite (vite-plugin-federation)
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// vite.config.ts do remote
|
|
50
|
+
import { defineConfig } from 'vite'
|
|
51
|
+
import react from '@vitejs/plugin-react'
|
|
52
|
+
import federation from '@originjs/vite-plugin-federation'
|
|
53
|
+
|
|
54
|
+
export default defineConfig({
|
|
55
|
+
plugins: [
|
|
56
|
+
react(),
|
|
57
|
+
federation({
|
|
58
|
+
name: '{nome-remote}', // identificador único do remote
|
|
59
|
+
filename: 'remoteEntry.js', // arquivo gerado
|
|
60
|
+
exposes: {
|
|
61
|
+
'./App': './src/exposed/RemoteApp', // o que o shell pode importar
|
|
62
|
+
'./routes': './src/exposed/routes', // rotas para shell carregar
|
|
63
|
+
},
|
|
64
|
+
shared: {
|
|
65
|
+
react: { singleton: true, requiredVersion: '^18.0.0' },
|
|
66
|
+
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
|
|
67
|
+
'react-router-dom': { singleton: true },
|
|
68
|
+
// design system — sempre singleton para evitar instâncias duplicadas
|
|
69
|
+
'@{org}/design-system': { singleton: true },
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
],
|
|
73
|
+
build: {
|
|
74
|
+
target: 'esnext',
|
|
75
|
+
minify: false, // facilita debug; ativar em prod via CI flag
|
|
76
|
+
cssCodeSplit: false, // evita problemas com CSS em remotes
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Modo standalone (obrigatório para dev local)
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// src/App.tsx — funciona sem shell
|
|
85
|
+
import { BrowserRouter } from 'react-router-dom'
|
|
86
|
+
import { AppRoutes } from './routes'
|
|
87
|
+
|
|
88
|
+
export default function App() {
|
|
89
|
+
return (
|
|
90
|
+
<BrowserRouter>
|
|
91
|
+
<AppRoutes />
|
|
92
|
+
</BrowserRouter>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
// package.json do remote
|
|
99
|
+
{
|
|
100
|
+
"scripts": {
|
|
101
|
+
"dev": "vite --port 3001", // standalone
|
|
102
|
+
"dev:federated": "vite --port 3001 --mode federated", // com Module Federation ativo
|
|
103
|
+
"build": "vite build",
|
|
104
|
+
"preview": "vite preview --port 3001"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Configurando o Shell
|
|
2
|
+
|
|
3
|
+
> Parte do skill `eng-frontend-microfrontend`. Leia este arquivo quando a tarefa configurar o shell ou o lazy loading de remotes.
|
|
4
|
+
|
|
5
|
+
## Configurando o Shell
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// vite.config.ts do shell
|
|
9
|
+
import federation from '@originjs/vite-plugin-federation'
|
|
10
|
+
|
|
11
|
+
export default defineConfig({
|
|
12
|
+
plugins: [
|
|
13
|
+
react(),
|
|
14
|
+
federation({
|
|
15
|
+
name: 'shell',
|
|
16
|
+
remotes: {
|
|
17
|
+
'{nome-remote}': 'http://localhost:3001/assets/remoteEntry.js',
|
|
18
|
+
// Em produção, usar variável de ambiente:
|
|
19
|
+
// '{nome-remote}': process.env.VITE_REMOTE_URL_NOME_REMOTE,
|
|
20
|
+
},
|
|
21
|
+
shared: {
|
|
22
|
+
react: { singleton: true },
|
|
23
|
+
'react-dom': { singleton: true },
|
|
24
|
+
'react-router-dom': { singleton: true },
|
|
25
|
+
'@{org}/design-system': { singleton: true },
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Lazy loading de remotes no shell
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// src/routes/index.tsx — shell monta remotes por rota
|
|
36
|
+
import { lazy, Suspense } from 'react'
|
|
37
|
+
import { Routes, Route } from 'react-router-dom'
|
|
38
|
+
|
|
39
|
+
// Tipagem do remote (importar do contrato de interface)
|
|
40
|
+
const RemoteApp = lazy(() =>
|
|
41
|
+
import('{nome-remote}/App').then((m) => ({ default: m.default }))
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
function ErrorFallback({ error }: { error: Error }) {
|
|
45
|
+
return (
|
|
46
|
+
<div role="alert">
|
|
47
|
+
<p>Falha ao carregar módulo. <button onClick={() => window.location.reload()}>Tentar novamente</button></p>
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function ShellRoutes() {
|
|
53
|
+
return (
|
|
54
|
+
<Routes>
|
|
55
|
+
<Route
|
|
56
|
+
path="/{caminho-remote}/*"
|
|
57
|
+
element={
|
|
58
|
+
<Suspense fallback={<div>Carregando...</div>}>
|
|
59
|
+
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
|
60
|
+
<RemoteApp />
|
|
61
|
+
</ErrorBoundary>
|
|
62
|
+
</Suspense>
|
|
63
|
+
}
|
|
64
|
+
/>
|
|
65
|
+
</Routes>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|