responsive-system 1.5.4 → 1.6.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/dist/responsive-system.cjs +3 -3
- package/dist/responsive-system.cjs.map +1 -1
- package/dist/responsive-system.mjs +51 -48
- package/dist/responsive-system.mjs.map +1 -1
- package/package.json +3 -2
- package/scripts/postinstall.js +126 -4
- package/scripts/test-postinstall.js +252 -0
- package/src/layouts/DefaultLayout.tsx +1 -1
- package/src/layouts/MainLayout.tsx +8 -7
- package/src/layouts/SidebarLayout.tsx +1 -1
- package/src/providers/ResponsiveLayoutProvider.tsx +8 -4
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Script de prueba para validar el postinstall.js
|
|
5
|
+
* Simula un proyecto vacío y verifica que todo se genere correctamente
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs'
|
|
9
|
+
import path from 'path'
|
|
10
|
+
import { execSync } from 'child_process'
|
|
11
|
+
import { fileURLToPath } from 'url'
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
14
|
+
const __dirname = path.dirname(__filename)
|
|
15
|
+
|
|
16
|
+
// Crear directorio temporal para pruebas
|
|
17
|
+
const testDir = path.join(__dirname, '..', '.test-project')
|
|
18
|
+
const projectRoot = testDir
|
|
19
|
+
|
|
20
|
+
console.log('🧪 Iniciando pruebas del script postinstall...')
|
|
21
|
+
console.log(` Directorio de prueba: ${testDir}`)
|
|
22
|
+
console.log('')
|
|
23
|
+
|
|
24
|
+
// Limpiar directorio de prueba si existe
|
|
25
|
+
if (fs.existsSync(testDir)) {
|
|
26
|
+
console.log('🧹 Limpiando directorio de prueba anterior...')
|
|
27
|
+
try {
|
|
28
|
+
fs.rmSync(testDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 1000 })
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.log(' ⚠️ No se pudo limpiar completamente, continuando...')
|
|
31
|
+
// Intentar eliminar solo los archivos importantes
|
|
32
|
+
try {
|
|
33
|
+
const importantFiles = ['package.json', 'src', 'vite.config.ts', 'tailwind.config.js', 'postcss.config.js', 'tsconfig.json', 'tsconfig.node.json', 'index.html']
|
|
34
|
+
importantFiles.forEach(file => {
|
|
35
|
+
const filePath = path.join(testDir, file)
|
|
36
|
+
if (fs.existsSync(filePath)) {
|
|
37
|
+
try {
|
|
38
|
+
fs.rmSync(filePath, { recursive: true, force: true })
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// Ignorar errores individuales
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
} catch (e) {
|
|
45
|
+
// Continuar de todas formas
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Crear directorio de prueba
|
|
51
|
+
fs.mkdirSync(testDir, { recursive: true })
|
|
52
|
+
|
|
53
|
+
// Crear package.json vacío (simulando proyecto nuevo)
|
|
54
|
+
const testPackageJson = {
|
|
55
|
+
name: 'test-project',
|
|
56
|
+
version: '1.0.0',
|
|
57
|
+
type: 'module',
|
|
58
|
+
dependencies: {
|
|
59
|
+
'responsive-system': '^1.6.0'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fs.writeFileSync(
|
|
64
|
+
path.join(testDir, 'package.json'),
|
|
65
|
+
JSON.stringify(testPackageJson, null, 2)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
console.log('✅ package.json de prueba creado')
|
|
69
|
+
console.log('')
|
|
70
|
+
|
|
71
|
+
// Cambiar al directorio de prueba
|
|
72
|
+
process.chdir(testDir)
|
|
73
|
+
|
|
74
|
+
// Simular ejecución del postinstall
|
|
75
|
+
console.log('📦 Ejecutando postinstall...')
|
|
76
|
+
console.log('')
|
|
77
|
+
|
|
78
|
+
// Importar y ejecutar el postinstall
|
|
79
|
+
const postinstallPath = path.join(__dirname, 'postinstall.js')
|
|
80
|
+
|
|
81
|
+
// Ejecutar el script con node
|
|
82
|
+
try {
|
|
83
|
+
// Simular variables de entorno de postinstall
|
|
84
|
+
process.env.npm_lifecycle_event = 'postinstall'
|
|
85
|
+
|
|
86
|
+
// Ejecutar el script
|
|
87
|
+
execSync(`node "${postinstallPath}"`, {
|
|
88
|
+
stdio: 'inherit',
|
|
89
|
+
cwd: testDir,
|
|
90
|
+
env: {
|
|
91
|
+
...process.env,
|
|
92
|
+
npm_lifecycle_event: 'postinstall'
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
console.log('')
|
|
97
|
+
console.log('✅ Postinstall ejecutado')
|
|
98
|
+
console.log('')
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('❌ Error al ejecutar postinstall:', error.message)
|
|
101
|
+
process.exit(1)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Verificaciones
|
|
105
|
+
console.log('🔍 Verificando archivos generados...')
|
|
106
|
+
console.log('')
|
|
107
|
+
|
|
108
|
+
const checks = []
|
|
109
|
+
|
|
110
|
+
// 1. Verificar que main.tsx existe y tiene el layout correcto
|
|
111
|
+
const mainTsxPath = path.join(testDir, 'src', 'main.tsx')
|
|
112
|
+
if (fs.existsSync(mainTsxPath)) {
|
|
113
|
+
const mainTsxContent = fs.readFileSync(mainTsxPath, 'utf8')
|
|
114
|
+
|
|
115
|
+
// Verificar que tiene ResponsiveLayoutProvider con defaultLayout
|
|
116
|
+
if (mainTsxContent.includes('ResponsiveLayoutProvider')) {
|
|
117
|
+
if (mainTsxContent.includes('defaultLayout="default"')) {
|
|
118
|
+
checks.push({ name: 'main.tsx tiene defaultLayout="default"', ok: true })
|
|
119
|
+
} else {
|
|
120
|
+
checks.push({ name: 'main.tsx tiene defaultLayout="default"', ok: false, error: 'No se encontró defaultLayout="default"' })
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
checks.push({ name: 'main.tsx tiene ResponsiveLayoutProvider', ok: false, error: 'No se encontró ResponsiveLayoutProvider' })
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
checks.push({ name: 'main.tsx existe', ok: false, error: 'Archivo no encontrado' })
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 2. Verificar que App.tsx existe
|
|
130
|
+
const appTsxPath = path.join(testDir, 'src', 'App.tsx')
|
|
131
|
+
if (fs.existsSync(appTsxPath)) {
|
|
132
|
+
checks.push({ name: 'App.tsx existe', ok: true })
|
|
133
|
+
} else {
|
|
134
|
+
checks.push({ name: 'App.tsx existe', ok: false, error: 'Archivo no encontrado' })
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 3. Verificar que HomePage.tsx existe
|
|
138
|
+
const homePagePath = path.join(testDir, 'src', 'pages', 'HomePage.tsx')
|
|
139
|
+
if (fs.existsSync(homePagePath)) {
|
|
140
|
+
checks.push({ name: 'HomePage.tsx existe', ok: true })
|
|
141
|
+
} else {
|
|
142
|
+
checks.push({ name: 'HomePage.tsx existe', ok: false, error: 'Archivo no encontrado' })
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 4. Verificar que los componentes del layout "default" se generaron
|
|
146
|
+
const navigationPath = path.join(testDir, 'src', 'components', 'layout', 'Navigation.tsx')
|
|
147
|
+
const footerPath = path.join(testDir, 'src', 'components', 'layout', 'Footer.tsx')
|
|
148
|
+
const sidebarPath = path.join(testDir, 'src', 'components', 'layout', 'Sidebar.tsx')
|
|
149
|
+
|
|
150
|
+
if (fs.existsSync(navigationPath)) {
|
|
151
|
+
checks.push({ name: 'Navigation.tsx generado (layout default)', ok: true })
|
|
152
|
+
} else {
|
|
153
|
+
checks.push({ name: 'Navigation.tsx generado (layout default)', ok: false, error: 'Archivo no encontrado' })
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (fs.existsSync(footerPath)) {
|
|
157
|
+
checks.push({ name: 'Footer.tsx generado (layout default)', ok: true })
|
|
158
|
+
} else {
|
|
159
|
+
checks.push({ name: 'Footer.tsx generado (layout default)', ok: false, error: 'Archivo no encontrado' })
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Verificar que Sidebar NO se generó para layout "default"
|
|
163
|
+
if (!fs.existsSync(sidebarPath)) {
|
|
164
|
+
checks.push({ name: 'Sidebar.tsx NO generado (correcto para default)', ok: true })
|
|
165
|
+
} else {
|
|
166
|
+
checks.push({ name: 'Sidebar.tsx NO generado (correcto para default)', ok: false, error: 'Sidebar.tsx no debería existir para layout default' })
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 5. Verificar que useResponsive se copió
|
|
170
|
+
const useResponsivePath = path.join(testDir, 'src', 'hooks', 'useResponsive.ts')
|
|
171
|
+
if (fs.existsSync(useResponsivePath)) {
|
|
172
|
+
checks.push({ name: 'useResponsive.ts copiado', ok: true })
|
|
173
|
+
} else {
|
|
174
|
+
checks.push({ name: 'useResponsive.ts copiado', ok: false, error: 'Archivo no encontrado' })
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 6. Verificar que los archivos de configuración existen
|
|
178
|
+
const configFiles = [
|
|
179
|
+
{ path: 'vite.config.ts', name: 'vite.config.ts' },
|
|
180
|
+
{ path: 'tailwind.config.js', name: 'tailwind.config.js' },
|
|
181
|
+
{ path: 'postcss.config.js', name: 'postcss.config.js' },
|
|
182
|
+
{ path: 'tsconfig.json', name: 'tsconfig.json' },
|
|
183
|
+
{ path: 'tsconfig.node.json', name: 'tsconfig.node.json' },
|
|
184
|
+
{ path: 'index.html', name: 'index.html' },
|
|
185
|
+
{ path: 'src/index.css', name: 'src/index.css' }
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
configFiles.forEach(({ path: filePath, name }) => {
|
|
189
|
+
const fullPath = path.join(testDir, filePath)
|
|
190
|
+
if (fs.existsSync(fullPath)) {
|
|
191
|
+
checks.push({ name: `${name} existe`, ok: true })
|
|
192
|
+
} else {
|
|
193
|
+
checks.push({ name: `${name} existe`, ok: false, error: 'Archivo no encontrado' })
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
// 7. Verificar que package.json tiene las dependencias correctas
|
|
198
|
+
const finalPackageJson = JSON.parse(fs.readFileSync(path.join(testDir, 'package.json'), 'utf8'))
|
|
199
|
+
const requiredDeps = ['react', 'react-dom']
|
|
200
|
+
const requiredDevDeps = ['vite', '@vitejs/plugin-react', 'tailwindcss', '@tailwindcss/postcss', 'postcss', 'autoprefixer', 'typescript', '@types/react', '@types/react-dom']
|
|
201
|
+
|
|
202
|
+
requiredDeps.forEach(dep => {
|
|
203
|
+
if (finalPackageJson.dependencies && finalPackageJson.dependencies[dep]) {
|
|
204
|
+
checks.push({ name: `Dependency ${dep} agregada`, ok: true })
|
|
205
|
+
} else {
|
|
206
|
+
checks.push({ name: `Dependency ${dep} agregada`, ok: false, error: 'No encontrada en dependencies' })
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
requiredDevDeps.forEach(dep => {
|
|
211
|
+
if (finalPackageJson.devDependencies && finalPackageJson.devDependencies[dep]) {
|
|
212
|
+
checks.push({ name: `DevDependency ${dep} agregada`, ok: true })
|
|
213
|
+
} else {
|
|
214
|
+
checks.push({ name: `DevDependency ${dep} agregada`, ok: false, error: 'No encontrada en devDependencies' })
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
// Mostrar resultados
|
|
219
|
+
console.log('📊 Resultados de las verificaciones:')
|
|
220
|
+
console.log('')
|
|
221
|
+
|
|
222
|
+
let allPassed = true
|
|
223
|
+
checks.forEach(check => {
|
|
224
|
+
if (check.ok) {
|
|
225
|
+
console.log(` ✅ ${check.name}`)
|
|
226
|
+
} else {
|
|
227
|
+
console.log(` ❌ ${check.name}`)
|
|
228
|
+
if (check.error) {
|
|
229
|
+
console.log(` Error: ${check.error}`)
|
|
230
|
+
}
|
|
231
|
+
allPassed = false
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
console.log('')
|
|
236
|
+
|
|
237
|
+
if (allPassed) {
|
|
238
|
+
console.log('🎉 ¡Todas las verificaciones pasaron!')
|
|
239
|
+
console.log('')
|
|
240
|
+
console.log('💡 El script postinstall está funcionando correctamente.')
|
|
241
|
+
console.log(' Puedes publicar el paquete con confianza.')
|
|
242
|
+
} else {
|
|
243
|
+
console.log('⚠️ Algunas verificaciones fallaron.')
|
|
244
|
+
console.log(' Revisa los errores antes de publicar.')
|
|
245
|
+
process.exit(1)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
console.log('')
|
|
249
|
+
console.log(`📁 Directorio de prueba: ${testDir}`)
|
|
250
|
+
console.log(' Puedes revisar los archivos generados allí.')
|
|
251
|
+
console.log('')
|
|
252
|
+
|
|
@@ -19,10 +19,7 @@ interface MainLayoutProps {
|
|
|
19
19
|
const MainLayout: React.FC<MainLayoutProps> = ({ children, layout: layoutProp }) => {
|
|
20
20
|
const { layout } = useResponsiveLayout()
|
|
21
21
|
|
|
22
|
-
//
|
|
23
|
-
const currentLayout = layoutProp || layout.current
|
|
24
|
-
|
|
25
|
-
// Seleccionar el layout apropiado basado en el estado del contexto o prop
|
|
22
|
+
// Mapa de layouts disponibles
|
|
26
23
|
const layouts = {
|
|
27
24
|
default: DefaultLayout,
|
|
28
25
|
sidebar: SidebarLayout,
|
|
@@ -30,11 +27,15 @@ const MainLayout: React.FC<MainLayoutProps> = ({ children, layout: layoutProp })
|
|
|
30
27
|
minimal: MinimalLayout,
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
//
|
|
34
|
-
const
|
|
35
|
-
|
|
30
|
+
// Determinar qué layout usar: prop > contexto > default
|
|
31
|
+
const layoutToUse = layoutProp || layout.current || 'default'
|
|
32
|
+
|
|
33
|
+
// Validar que el layout sea válido, si no usar default
|
|
34
|
+
const validLayout = (layoutToUse && layouts[layoutToUse as keyof typeof layouts])
|
|
35
|
+
? layoutToUse
|
|
36
36
|
: 'default'
|
|
37
37
|
|
|
38
|
+
// Obtener el componente de layout
|
|
38
39
|
const LayoutComponent = layouts[validLayout as keyof typeof layouts] || DefaultLayout
|
|
39
40
|
|
|
40
41
|
return <LayoutComponent>{children}</LayoutComponent>
|
|
@@ -32,14 +32,13 @@ const ResponsiveLayoutProviderInner: React.FC<ResponsiveLayoutProviderInnerProps
|
|
|
32
32
|
const customResponsive = useResponsiveHook?.()
|
|
33
33
|
const responsive = customResponsive || internalResponsive
|
|
34
34
|
|
|
35
|
-
// Inicializar el estado con el
|
|
35
|
+
// Inicializar el estado con el layout normalizado usando función inicializadora
|
|
36
36
|
// Esto asegura que solo se ejecute una vez, incluso con React.StrictMode
|
|
37
37
|
const [currentLayout, setCurrentLayout] = useState(() => {
|
|
38
|
-
// Validar
|
|
38
|
+
// Validar y normalizar el defaultLayout directamente en la función inicializadora
|
|
39
39
|
if (defaultLayout && typeof defaultLayout === 'string' && LAYOUT_CONFIG[defaultLayout]) {
|
|
40
40
|
return defaultLayout
|
|
41
41
|
}
|
|
42
|
-
// Si no es válido, usar el layout por defecto
|
|
43
42
|
return DEFAULT_LAYOUT
|
|
44
43
|
})
|
|
45
44
|
|
|
@@ -88,10 +87,15 @@ export const ResponsiveLayoutProvider: React.FC<ResponsiveLayoutProviderProps> =
|
|
|
88
87
|
defaultLayout = DEFAULT_LAYOUT,
|
|
89
88
|
useResponsiveHook
|
|
90
89
|
}) => {
|
|
90
|
+
// Normalizar el defaultLayout antes de pasarlo al componente interno
|
|
91
|
+
const normalizedDefaultLayout = (defaultLayout && typeof defaultLayout === 'string' && LAYOUT_CONFIG[defaultLayout])
|
|
92
|
+
? defaultLayout
|
|
93
|
+
: DEFAULT_LAYOUT
|
|
94
|
+
|
|
91
95
|
return (
|
|
92
96
|
<ResponsiveProvider>
|
|
93
97
|
<ResponsiveLayoutProviderInner
|
|
94
|
-
defaultLayout={
|
|
98
|
+
defaultLayout={normalizedDefaultLayout}
|
|
95
99
|
useResponsiveHook={useResponsiveHook}
|
|
96
100
|
>
|
|
97
101
|
{children}
|