@jeffrey2423/coding-standards 1.0.0 → 2.0.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.
Files changed (28) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -174
  3. package/bin/cli.js +373 -20
  4. package/package.json +22 -3
  5. package/standards/backend/architecture/event-driven.md +112 -0
  6. package/standards/backend/architecture/microservice-anatomy.md +106 -0
  7. package/standards/backend/architecture/multitenancy.md +112 -0
  8. package/standards/backend/architecture/public-api-facade.md +112 -0
  9. package/standards/backend/architecture/shared-vs-owned.md +62 -0
  10. package/standards/{backend-standards.md → backend/backend-standards.md} +8 -1
  11. package/standards/{database-conventions.md → backend/database-conventions.md} +7 -0
  12. package/standards/backend/technology-stack.md +73 -0
  13. package/standards/core/ai-collaboration.md +64 -0
  14. package/standards/core/clean-architecture-ddd.md +69 -0
  15. package/standards/core/coding-conventions.md +66 -0
  16. package/standards/core/testing-strategy.md +46 -0
  17. package/standards/{mobile-flutter-standards.md → mobile/flutter/flutter-standards.md} +9 -1
  18. package/standards/{mobile-react-native-standards.md → mobile/react-native/react-native-standards.md} +9 -1
  19. package/standards/{technical-preferences-ux.md → web/_base/design-system-ux.md} +8 -1
  20. package/standards/web/_base/frontend-architecture.md +75 -0
  21. package/standards/{frontend-standards.md → web/_base/frontend-standards.md} +7 -0
  22. package/standards/web/_base/technology-stack.md +40 -0
  23. package/standards/web/microfrontends/module-federation-standard.md +216 -0
  24. package/standards/web/single-spa/single-spa-standard.md +196 -0
  25. package/standards/web/spa/spa-standard.md +53 -0
  26. package/standards/architecture-patterns.md +0 -444
  27. package/standards/technology-stack.md +0 -294
  28. package/standards/vite-config-standard.md +0 -531
@@ -1,531 +0,0 @@
1
- # Vite Config - Estándar Microfrontends
2
-
3
- Guía de configuración estándar para microfrontends usando Single-SPA (default) y Module Federation (solo módulos compartidos).
4
-
5
- ---
6
-
7
- ## REGLA CRÍTICA: Single-SPA vs Module Federation
8
-
9
- | Tipo de Módulo | Tecnología | Cuándo Usar |
10
- |----------------|------------|-------------|
11
- | **MFE Estándar** | **Single-SPA** | ✅ DEFAULT - Todos los módulos de negocio (finance, hr, inventory, etc.) |
12
- | **Módulo Transversal** | **Module Federation** | ⚠️ SOLO cuando el ingeniero define explícitamente que debe ser compartido |
13
-
14
- ### ¿Cuándo usar Module Federation?
15
-
16
- Module Federation **SOLO** se usa para módulos que:
17
- 1. Son **transversales** (usados por múltiples MFEs)
18
- 2. El ingeniero los marca **explícitamente** como "federable"
19
- 3. Ejemplos: Componentes compartidos, utilidades comunes, design system
20
-
21
- ### ¿Cuándo usar Single-SPA?
22
-
23
- Single-SPA es el **DEFAULT** para:
24
- 1. Todos los módulos de negocio (finance, hr, inventory, sales, etc.)
25
- 2. Cualquier MFE que no sea explícitamente marcado como federable
26
- 3. Widgets independientes
27
-
28
- ---
29
-
30
- ## Dependencias Requeridas
31
-
32
- ### Para MFE Single-SPA (DEFAULT)
33
-
34
- ```bash
35
- # Core Single-SPA
36
- npm install single-spa-react
37
-
38
- # Vite Plugin (configura automáticamente entry points, externals, CSS)
39
- npm install vite-plugin-single-spa --save-dev
40
-
41
- # React (obligatorio)
42
- npm install react react-dom
43
- npm install @types/react @types/react-dom --save-dev
44
-
45
- # Común
46
- npm install @vitejs/plugin-react --save-dev
47
- ```
48
-
49
- ### Para Módulo Federable (SOLO si explícitamente requerido)
50
-
51
- ```bash
52
- # Module Federation
53
- npm install @module-federation/vite --save-dev
54
-
55
- # TanStack Router (si aplica)
56
- npm install @tanstack/react-router
57
-
58
- # Común
59
- npm install @vitejs/plugin-react --save-dev
60
- ```
61
-
62
- ---
63
-
64
- ## 1. Single-SPA (DEFAULT para todos los MFEs)
65
-
66
- ### 1.1 Configuración Vite (vite.config.ts)
67
-
68
- ```typescript
69
- // modules/{module-name}/vite.config.ts
70
- import { defineConfig } from 'vite';
71
- import react from '@vitejs/plugin-react';
72
- import vitePluginSingleSpa from 'vite-plugin-single-spa';
73
-
74
- export default defineConfig({
75
- plugins: [
76
- react(),
77
- vitePluginSingleSpa({
78
- serverPort: 3001, // Puerto único por módulo
79
- spaEntryPoints: 'src/spa.tsx', // Entry point Single-SPA
80
- cssStrategy: 'singleMife', // CSS se inyecta/remueve en mount/unmount
81
- projectId: '{module-name}-module', // ID único del proyecto
82
- }),
83
- ],
84
- server: {
85
- port: 3001,
86
- cors: true,
87
- },
88
- base: '/{module-name}/', // Prefijo de rutas
89
- });
90
- ```
91
-
92
- ### 1.2 Entry Point Single-SPA (src/spa.tsx)
93
-
94
- ```typescript
95
- // modules/{module-name}/src/spa.tsx
96
- import React from 'react';
97
- import ReactDOMClient from 'react-dom/client';
98
- import singleSpaReact from 'single-spa-react';
99
- import { cssLifecycleFactory } from 'vite-plugin-single-spa/ex';
100
- import App from './App';
101
-
102
- // Props que el App Shell puede pasar al MFE
103
- export interface CustomProps {
104
- i18n?: unknown;
105
- eventBus?: unknown;
106
- authContext?: unknown;
107
- }
108
-
109
- // Error boundary para errores en el MFE
110
- function ErrorFallback({ error }: { error: Error }) {
111
- return (
112
- <div className="flex items-center justify-center min-h-screen bg-red-50">
113
- <div className="max-w-md p-6 bg-white rounded-lg shadow-lg">
114
- <h2 className="text-xl font-semibold text-red-600 mb-2">
115
- Error en módulo
116
- </h2>
117
- <p className="text-gray-600 mb-4">{error.message}</p>
118
- <button
119
- onClick={() => window.location.reload()}
120
- className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
121
- >
122
- Recargar
123
- </button>
124
- </div>
125
- </div>
126
- );
127
- }
128
-
129
- // Crear lifecycles con single-spa-react
130
- const lifecycles = singleSpaReact({
131
- React,
132
- ReactDOMClient,
133
- rootComponent: App,
134
- errorBoundary: (err: Error) => <ErrorFallback error={err} />,
135
- // CRÍTICO: Especificar el contenedor del App Shell donde se montará el MFE
136
- domElementGetter: () => document.getElementById('single-spa-application')!,
137
- });
138
-
139
- // CSS lifecycle - inyecta CSS al montar, lo remueve al desmontar
140
- const cssLc = cssLifecycleFactory('spa');
141
-
142
- // ⚠️ REGLA CRÍTICA: domElementGetter
143
- // -------------------------------------
144
- // El App Shell de principal provee un contenedor específico donde se montan los MFEs:
145
- // <div id="single-spa-application">
146
- //
147
- // Sin domElementGetter:
148
- // - single-spa-react crea un <div> nuevo al final del <body>
149
- // - El MFE se renderiza FUERA del layout del App Shell
150
- // - El usuario NO verá el MFE aunque esté montado correctamente
151
- //
152
- // Con domElementGetter:
153
- // - El MFE se monta dentro del contenedor del App Shell
154
- // - Se integra correctamente con el layout (navegación, estilos)
155
- // - El usuario ve el MFE en la ubicación correcta
156
- //
157
- // TODOS los MFEs Single-SPA deben incluir esta configuración.
158
-
159
- // Exportar lifecycles combinados (CSS + React)
160
- export const bootstrap = [cssLc.bootstrap, lifecycles.bootstrap];
161
- export const mount = [cssLc.mount, lifecycles.mount];
162
- export const unmount = [cssLc.unmount, lifecycles.unmount];
163
- ```
164
-
165
- ### 1.3 Standalone Development (src/main.tsx)
166
-
167
- ```typescript
168
- // modules/{module-name}/src/main.tsx
169
- // Para desarrollo standalone (sin App Shell)
170
- import React from 'react';
171
- import ReactDOM from 'react-dom/client';
172
- import App from './App';
173
- import './index.css';
174
-
175
- ReactDOM.createRoot(document.getElementById('root')!).render(
176
- <React.StrictMode>
177
- <App />
178
- </React.StrictMode>
179
- );
180
- ```
181
-
182
- ### 1.4 App Shell - Registro de MFEs Single-SPA
183
-
184
- ```typescript
185
- // app-shell/src/microfrontends/register.ts
186
- import { registerApplication, start } from 'single-spa';
187
-
188
- // Registrar cada MFE
189
- registerApplication({
190
- name: 'finance',
191
- app: () => System.import('http://localhost:3001/finance/spa.js'),
192
- activeWhen: ['/finance'],
193
- customProps: {
194
- i18n: i18nInstance,
195
- eventBus: eventBus,
196
- authContext: authStore.getState(),
197
- },
198
- });
199
-
200
- registerApplication({
201
- name: 'inventory',
202
- app: () => System.import('http://localhost:3002/inventory/spa.js'),
203
- activeWhen: ['/inventory'],
204
- customProps: {
205
- i18n: i18nInstance,
206
- eventBus: eventBus,
207
- authContext: authStore.getState(),
208
- },
209
- });
210
-
211
- registerApplication({
212
- name: 'hr',
213
- app: () => System.import('http://localhost:3003/hr/spa.js'),
214
- activeWhen: ['/hr'],
215
- customProps: {
216
- i18n: i18nInstance,
217
- eventBus: eventBus,
218
- authContext: authStore.getState(),
219
- },
220
- });
221
-
222
- // Iniciar Single-SPA
223
- start();
224
- ```
225
-
226
- ### 1.5 Import Map (index.html del App Shell)
227
-
228
- ```html
229
- <!-- app-shell/index.html -->
230
- <script type="systemjs-importmap">
231
- {
232
- "imports": {
233
- "react": "https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js",
234
- "react-dom": "https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js",
235
- "single-spa": "https://cdn.jsdelivr.net/npm/single-spa@6/lib/system/single-spa.min.js"
236
- }
237
- }
238
- </script>
239
- <script src="https://cdn.jsdelivr.net/npm/systemjs@6/dist/system.min.js"></script>
240
- ```
241
-
242
- ---
243
-
244
- ## 2. Module Federation (SOLO para módulos transversales explícitos)
245
-
246
- > ⚠️ **IMPORTANTE**: Solo usar Module Federation cuando el ingeniero defina explícitamente que un módulo debe ser compartido/federable.
247
-
248
- ### 2.1 Exponer un Módulo Federable (Remote)
249
-
250
- ```typescript
251
- // shared-components/vite.config.ts
252
- import { defineConfig } from 'vite';
253
- import react from '@vitejs/plugin-react';
254
- import { federation } from '@module-federation/vite';
255
-
256
- export default defineConfig({
257
- plugins: [
258
- react(),
259
- federation({
260
- name: 'sharedComponents', // Nombre único del módulo federable
261
- filename: 'remoteEntry.js',
262
- exposes: {
263
- './Button': './src/components/Button.tsx',
264
- './Modal': './src/components/Modal.tsx',
265
- './DataTable': './src/components/DataTable.tsx',
266
- },
267
- shared: {
268
- react: { singleton: true, requiredVersion: '^18.3.1' },
269
- 'react-dom': { singleton: true, requiredVersion: '^18.3.1' }
270
- },
271
- }),
272
- ],
273
- server: {
274
- port: 3010,
275
- strictPort: true,
276
- cors: true,
277
- },
278
- build: {
279
- modulePreload: false,
280
- target: 'esnext',
281
- minify: false,
282
- cssCodeSplit: false,
283
- },
284
- });
285
- ```
286
-
287
- ### 2.2 Consumir Módulo Federable desde un MFE
288
-
289
- ```typescript
290
- // modules/finance/vite.config.ts (MFE que consume módulos federables)
291
- import { defineConfig } from 'vite';
292
- import react from '@vitejs/plugin-react';
293
- import vitePluginSingleSpa from 'vite-plugin-single-spa';
294
- import { federation } from '@module-federation/vite';
295
-
296
- export default defineConfig({
297
- plugins: [
298
- react(),
299
- vitePluginSingleSpa({
300
- serverPort: 3001,
301
- spaEntryPoints: 'src/spa.tsx',
302
- cssStrategy: 'singleMife',
303
- projectId: 'finance-module',
304
- }),
305
- // Solo agregar federation si necesita consumir módulos compartidos
306
- federation({
307
- name: 'finance',
308
- remotes: {
309
- sharedComponents: {
310
- type: 'module',
311
- name: 'sharedComponents',
312
- entry: 'http://localhost:3010/remoteEntry.js',
313
- entryGlobalName: 'sharedComponents',
314
- },
315
- },
316
- shared: {
317
- react: { singleton: true, requiredVersion: '^18.3.1' },
318
- 'react-dom': { singleton: true, requiredVersion: '^18.3.1' },
319
- },
320
- }),
321
- ],
322
- server: {
323
- port: 3001,
324
- cors: true,
325
- },
326
- base: '/finance/',
327
- });
328
- ```
329
-
330
- ### 2.3 Tipos para Módulos Federables
331
-
332
- ```typescript
333
- // types/remotes.d.ts
334
- declare module 'sharedComponents/Button' {
335
- const Button: React.ComponentType<ButtonProps>;
336
- export default Button;
337
- }
338
-
339
- declare module 'sharedComponents/Modal' {
340
- const Modal: React.ComponentType<ModalProps>;
341
- export default Modal;
342
- }
343
-
344
- declare module 'sharedComponents/DataTable' {
345
- const DataTable: React.ComponentType<DataTableProps>;
346
- export default DataTable;
347
- }
348
- ```
349
-
350
- ---
351
-
352
- ## 3. Convención de Puertos
353
-
354
- | Módulo | Puerto | Tipo | Descripción |
355
- |--------|--------|------|-------------|
356
- | app-shell | 3000 | Host | Orquestador Single-SPA |
357
- | finance | 3001 | Single-SPA | Módulo Finanzas |
358
- | inventory | 3002 | Single-SPA | Módulo Inventario |
359
- | hr | 3003 | Single-SPA | Módulo RRHH |
360
- | crm | 3004 | Single-SPA | Módulo CRM |
361
- | pos | 3005 | Single-SPA | Módulo POS |
362
- | shared-components | 3010 | Federation | Componentes compartidos (federable) |
363
- | shared-utils | 3011 | Federation | Utilidades compartidas (federable) |
364
-
365
- ---
366
-
367
- ## 4. Routing con TanStack Router
368
-
369
- ### 4.1 Router del MFE (Single-SPA)
370
-
371
- > ⚠️ **IMPORTANTE:** Todas las rutas deben tener prefijo único que coincida con `base` en vite.config.ts
372
-
373
- ```typescript
374
- // modules/finance/src/router.tsx
375
- import {
376
- createRouter,
377
- createRootRoute,
378
- createRoute,
379
- redirect,
380
- } from '@tanstack/react-router';
381
- import { MainLayout } from './components/layout/MainLayout';
382
- import Dashboard from './routes/dashboard';
383
- import AccountsIndex from './routes/accounts.index';
384
- import AccountDetail from './routes/accounts.$id';
385
-
386
- // Root route con layout
387
- const rootRoute = createRootRoute({
388
- component: MainLayout,
389
- });
390
-
391
- // Ruta índice - redirige al dashboard
392
- const indexRoute = createRoute({
393
- getParentRoute: () => rootRoute,
394
- path: '/',
395
- beforeLoad: () => {
396
- throw redirect({ to: '/finance/dashboard' });
397
- },
398
- });
399
-
400
- // Dashboard
401
- const dashboardRoute = createRoute({
402
- getParentRoute: () => rootRoute,
403
- path: '/finance/dashboard',
404
- component: Dashboard,
405
- });
406
-
407
- // Cuentas - listado
408
- const accountsRoute = createRoute({
409
- getParentRoute: () => rootRoute,
410
- path: '/finance/accounts',
411
- component: AccountsIndex,
412
- });
413
-
414
- // Cuentas - detalle
415
- const accountDetailRoute = createRoute({
416
- getParentRoute: () => rootRoute,
417
- path: '/finance/accounts/$id',
418
- component: AccountDetail,
419
- });
420
-
421
- const routeTree = rootRoute.addChildren([
422
- indexRoute,
423
- dashboardRoute,
424
- accountsRoute,
425
- accountDetailRoute,
426
- ]);
427
-
428
- export const router = createRouter({ routeTree });
429
-
430
- declare module '@tanstack/react-router' {
431
- interface Register {
432
- router: typeof router;
433
- }
434
- }
435
- ```
436
-
437
- ### 4.2 Convención de Prefijos de Rutas
438
-
439
- | Módulo | Puerto | Base (vite.config) | Prefijo Rutas |
440
- |--------|--------|---------------------|---------------|
441
- | app-shell | 3000 | `/` | `/` |
442
- | finance | 3001 | `/finance/` | `/finance/*` |
443
- | inventory | 3002 | `/inventory/` | `/inventory/*` |
444
- | hr | 3003 | `/hr/` | `/hr/*` |
445
-
446
- ---
447
-
448
- ## 5. Shared Dependencies (para ambos)
449
-
450
- ```typescript
451
- shared: {
452
- // SIEMPRE singleton para React
453
- react: { singleton: true, requiredVersion: '^18.3.1' },
454
- 'react-dom': { singleton: true, requiredVersion: '^18.3.1' },
455
-
456
- // Router y Query
457
- '@tanstack/react-router': { singleton: true },
458
- '@tanstack/react-query': { singleton: true },
459
-
460
- // State management
461
- 'zustand': { singleton: true },
462
-
463
- // i18n
464
- 'react-i18next': { singleton: true },
465
- 'i18next': { singleton: true },
466
- }
467
- ```
468
-
469
- ---
470
-
471
- ## 6. Checklist de Configuración
472
-
473
- ### MFE Single-SPA (DEFAULT)
474
-
475
- - [ ] `vite-plugin-single-spa` instalado y configurado
476
- - [ ] `single-spa-react` instalado
477
- - [ ] `src/spa.tsx` con lifecycles exportados
478
- - [ ] `cssLifecycleFactory` configurado para CSS isolation
479
- - [ ] `errorBoundary` implementado
480
- - [ ] **`domElementGetter` apuntando a `#single-spa-application`** ⚠️ CRÍTICO
481
- - [ ] Puerto único configurado
482
- - [ ] `base` configurado con prefijo (ej: `/finance/`)
483
- - [ ] Todas las rutas usan el prefijo
484
- - [ ] `cors: true` en server
485
- - [ ] `src/main.tsx` para desarrollo standalone
486
-
487
- ### Módulo Federable (SOLO si explícitamente requerido)
488
-
489
- - [ ] `@module-federation/vite` instalado
490
- - [ ] `name` único en federation config
491
- - [ ] `filename: 'remoteEntry.js'`
492
- - [ ] `exposes` con componentes/utilidades a compartir
493
- - [ ] `shared` con React y dependencias como singleton
494
- - [ ] Puerto único (rango 3010+)
495
- - [ ] `cors: true` en server
496
- - [ ] `modulePreload: false` en build
497
- - [ ] `cssCodeSplit: false` en build
498
- - [ ] Tipos declarados en consumidores
499
-
500
- ### App Shell
501
-
502
- - [ ] `single-spa` instalado
503
- - [ ] Import map con React y dependencias compartidas
504
- - [ ] `registerApplication` para cada MFE
505
- - [ ] `start()` llamado después de registrar
506
- - [ ] `customProps` con contexto compartido (i18n, auth, eventBus)
507
- - [ ] **Contenedor `<div id="single-spa-application">` en el layout** ⚠️ CRÍTICO para MFEs
508
-
509
- ---
510
-
511
- ## 7. Beneficios de Single-SPA como Default
512
-
513
- | Aspecto | Single-SPA | Module Federation |
514
- |---------|------------|-------------------|
515
- | **Aislamiento** | ✅ Completo (CSS, JS, lifecycle) | ⚠️ Parcial |
516
- | **Hot Reload** | ✅ Funciona bien | ⚠️ Problemas conocidos |
517
- | **CSS Isolation** | ✅ `cssLifecycleFactory` automático | ⚠️ Manual |
518
- | **Error Boundaries** | ✅ Built-in | ⚠️ Manual |
519
- | **Mount/Unmount** | ✅ Lifecycle completo | ⚠️ Solo lazy load |
520
- | **Complejidad** | ✅ Baja | ⚠️ Alta |
521
- | **Sharing código** | ⚠️ Via import maps | ✅ Nativo |
522
-
523
- ---
524
-
525
- ## 8. Referencias
526
-
527
- - [Single-SPA Documentation](https://single-spa.js.org/)
528
- - [single-spa-react](https://single-spa.js.org/docs/ecosystem-react/)
529
- - [vite-plugin-single-spa](https://github.com/nickt/vite-plugin-single-spa)
530
- - [Module Federation](https://module-federation.io/)
531
- - [Vite Documentation](https://vitejs.dev/)