nex-app 0.1.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/README.md +74 -0
- package/cli/create.js +116 -0
- package/cli/fallback.js +96 -0
- package/generator/agent-installer.js +33 -0
- package/generator/cursor-integration.js +202 -0
- package/generator/index.js +141 -0
- package/generator/package-manager.js +40 -0
- package/generator/template-engine.js +18 -0
- package/lib/marketplace-client.js +75 -0
- package/package.json +55 -0
- package/server/index.js +53 -0
- package/server/routes.js +89 -0
- package/templates/api-only/README.md.tpl +30 -0
- package/templates/api-only/package.json.tpl +20 -0
- package/templates/api-only/src/index.js.tpl +9 -0
- package/templates/blank/.nex-core/config.yaml.tpl +14 -0
- package/templates/blank/README.md.tpl +48 -0
- package/templates/blank/package.json.tpl +18 -0
- package/templates/blank/src/index.js.tpl +9 -0
- package/templates/full-stack/README.md.tpl +33 -0
- package/templates/full-stack/package.json.tpl +20 -0
- package/templates/full-stack/src/client/index.html.tpl +12 -0
- package/templates/full-stack/src/server/index.js.tpl +9 -0
- package/ui/assets/app.js +255 -0
- package/ui/assets/styles.css +416 -0
- package/ui/index.html +113 -0
- package/utils/browser.js +40 -0
- package/utils/environment.js +42 -0
- package/utils/port-finder.js +37 -0
- package/utils/validation.js +44 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine de templates - Substituição de placeholders
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export function renderTemplate(content, variables) {
|
|
6
|
+
let rendered = content
|
|
7
|
+
|
|
8
|
+
// Substituir placeholders {{variable}}
|
|
9
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
10
|
+
const regex = new RegExp(`\\{\\{${key}\\}\\}`, 'g')
|
|
11
|
+
rendered = rendered.replace(regex, String(value || ''))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Remover placeholders não substituídos (opcional)
|
|
15
|
+
rendered = rendered.replace(/\{\{[\w]+\}\}/g, '')
|
|
16
|
+
|
|
17
|
+
return rendered
|
|
18
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cliente para Marketplace API
|
|
3
|
+
* Por enquanto retorna lista mock, depois integrar com NEXMarketplace
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export async function searchAgents({ q = '', category }) {
|
|
7
|
+
// TODO: Integrar com NEXMarketplace.js real
|
|
8
|
+
// Por enquanto, retornar lista mock
|
|
9
|
+
|
|
10
|
+
const mockAgents = [
|
|
11
|
+
{
|
|
12
|
+
agent_id: 'anx',
|
|
13
|
+
name: 'ANX - Analysis Expert',
|
|
14
|
+
tagline: 'Requirements Analysis & Strategic Insights',
|
|
15
|
+
category: 'planning',
|
|
16
|
+
icon: '🎯',
|
|
17
|
+
total_installs: 2200,
|
|
18
|
+
average_rating: 4.8
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
agent_id: 'arx',
|
|
22
|
+
name: 'ARX - Architecture Expert',
|
|
23
|
+
tagline: 'System Architecture & Technical Design',
|
|
24
|
+
category: 'planning',
|
|
25
|
+
icon: '🏗️',
|
|
26
|
+
total_installs: 1800,
|
|
27
|
+
average_rating: 4.9
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
agent_id: 'pmx',
|
|
31
|
+
name: 'PMX - Product Management Expert',
|
|
32
|
+
tagline: 'Strategic Product Planning & PRD Generation',
|
|
33
|
+
category: 'planning',
|
|
34
|
+
icon: '📊',
|
|
35
|
+
total_installs: 1600,
|
|
36
|
+
average_rating: 4.7
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
agent_id: 'dvx',
|
|
40
|
+
name: 'DVX - Developer Expert',
|
|
41
|
+
tagline: 'Code Generation & Implementation',
|
|
42
|
+
category: 'execution',
|
|
43
|
+
icon: '💻',
|
|
44
|
+
total_installs: 2500,
|
|
45
|
+
average_rating: 4.9
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
agent_id: 'vex',
|
|
49
|
+
name: 'VEX - Conversion Hypnotist',
|
|
50
|
+
tagline: 'Persuasive Copy & Conversion Optimization',
|
|
51
|
+
category: 'bmad',
|
|
52
|
+
icon: '🎪',
|
|
53
|
+
total_installs: 720,
|
|
54
|
+
average_rating: 4.7
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
// Filtrar por busca
|
|
59
|
+
let filtered = mockAgents
|
|
60
|
+
if (q) {
|
|
61
|
+
const query = q.toLowerCase()
|
|
62
|
+
filtered = filtered.filter(agent =>
|
|
63
|
+
agent.name.toLowerCase().includes(query) ||
|
|
64
|
+
agent.tagline.toLowerCase().includes(query) ||
|
|
65
|
+
agent.agent_id.toLowerCase().includes(query)
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Filtrar por categoria
|
|
70
|
+
if (category) {
|
|
71
|
+
filtered = filtered.filter(agent => agent.category === category)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return filtered
|
|
75
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nex-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Create NEX projects with interactive installer (CLI + Web UI)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "cli/create.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"nex-app": "./cli/create.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"cli/",
|
|
12
|
+
"server/",
|
|
13
|
+
"ui/",
|
|
14
|
+
"generator/",
|
|
15
|
+
"templates/",
|
|
16
|
+
"utils/",
|
|
17
|
+
"lib/",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "node cli/create.js --version",
|
|
22
|
+
"test:cli": "node cli/create.js --no-browser",
|
|
23
|
+
"test:web": "node cli/create.js --web",
|
|
24
|
+
"prepublishOnly": "npm run test",
|
|
25
|
+
"publish": "node scripts/publish.js",
|
|
26
|
+
"publish:patch": "npm version patch && npm run publish",
|
|
27
|
+
"publish:minor": "npm version minor && npm run publish",
|
|
28
|
+
"publish:major": "npm version major && npm run publish"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"nex",
|
|
32
|
+
"nex-app",
|
|
33
|
+
"scaffold",
|
|
34
|
+
"generator",
|
|
35
|
+
"cli",
|
|
36
|
+
"web-installer"
|
|
37
|
+
],
|
|
38
|
+
"author": "INOSX (https://inosx.com)",
|
|
39
|
+
"license": "PROPRIETARY",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/INOSX/nex-store.git"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18.0.0"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"express": "^4.18.2",
|
|
49
|
+
"inquirer": "^9.2.15",
|
|
50
|
+
"chalk": "^5.3.0",
|
|
51
|
+
"open": "^8.4.2",
|
|
52
|
+
"fs-extra": "^11.2.0",
|
|
53
|
+
"yaml": "^2.3.4"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/server/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Servidor Express para Web UI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import express from 'express'
|
|
6
|
+
import { fileURLToPath } from 'url'
|
|
7
|
+
import { dirname, join } from 'path'
|
|
8
|
+
import { findFreePort } from '../utils/port-finder.js'
|
|
9
|
+
import routes from './routes.js'
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
12
|
+
const __dirname = dirname(__filename)
|
|
13
|
+
|
|
14
|
+
export async function startServer(initialCwd) {
|
|
15
|
+
const app = express()
|
|
16
|
+
|
|
17
|
+
// Middleware
|
|
18
|
+
app.use(express.json())
|
|
19
|
+
|
|
20
|
+
// Servir UI estática
|
|
21
|
+
app.use(express.static(join(__dirname, '../ui')))
|
|
22
|
+
|
|
23
|
+
// CORS apenas para localhost
|
|
24
|
+
app.use((req, res, next) => {
|
|
25
|
+
const origin = req.headers.origin
|
|
26
|
+
if (origin?.startsWith('http://localhost') || origin?.startsWith('http://127.0.0.1')) {
|
|
27
|
+
res.setHeader('Access-Control-Allow-Origin', origin)
|
|
28
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
|
|
29
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
|
|
30
|
+
}
|
|
31
|
+
if (req.method === 'OPTIONS') {
|
|
32
|
+
return res.sendStatus(200)
|
|
33
|
+
}
|
|
34
|
+
next()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
// Passar initialCwd para as rotas via app.locals
|
|
38
|
+
app.locals.initialCwd = initialCwd
|
|
39
|
+
|
|
40
|
+
// Rotas API
|
|
41
|
+
app.use('/api', routes)
|
|
42
|
+
|
|
43
|
+
// Encontrar porta livre
|
|
44
|
+
const port = await findFreePort(3000)
|
|
45
|
+
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
const server = app.listen(port, '127.0.0.1', () => {
|
|
48
|
+
resolve({ port, server })
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
server.on('error', reject)
|
|
52
|
+
})
|
|
53
|
+
}
|
package/server/routes.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rotas API do servidor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import express from 'express'
|
|
6
|
+
import path from 'path'
|
|
7
|
+
import { generateProject } from '../generator/index.js'
|
|
8
|
+
import { searchAgents } from '../lib/marketplace-client.js'
|
|
9
|
+
import { validateTemplate, validatePackageManager } from '../utils/validation.js'
|
|
10
|
+
|
|
11
|
+
const router = express.Router()
|
|
12
|
+
|
|
13
|
+
// Health check
|
|
14
|
+
router.get('/health', (req, res) => {
|
|
15
|
+
res.json({
|
|
16
|
+
status: 'ok',
|
|
17
|
+
timestamp: Date.now(),
|
|
18
|
+
version: '0.1.0'
|
|
19
|
+
})
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
// Buscar agentes (integração com Marketplace)
|
|
23
|
+
router.get('/agents/search', async (req, res) => {
|
|
24
|
+
try {
|
|
25
|
+
const { q = '', category } = req.query
|
|
26
|
+
|
|
27
|
+
const agents = await searchAgents({ q, category })
|
|
28
|
+
|
|
29
|
+
res.json({ agents })
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('Erro ao buscar agentes:', error)
|
|
32
|
+
res.status(500).json({
|
|
33
|
+
error: error.message,
|
|
34
|
+
agents: [] // Fallback: retornar vazio
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// Gerar projeto
|
|
40
|
+
router.post('/generate', async (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
const {
|
|
43
|
+
template,
|
|
44
|
+
agents = [],
|
|
45
|
+
packageManager = 'npm',
|
|
46
|
+
cursorIntegration = false,
|
|
47
|
+
options = {}
|
|
48
|
+
} = req.body
|
|
49
|
+
|
|
50
|
+
// No padrão BMAD/NEX, não pedimos nome do projeto
|
|
51
|
+
// Usamos o nome da pasta atual ou package.json existente
|
|
52
|
+
|
|
53
|
+
const templateValidation = validateTemplate(template)
|
|
54
|
+
if (!templateValidation.valid) {
|
|
55
|
+
return res.status(400).json({ error: templateValidation.error })
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const pmValidation = validatePackageManager(packageManager)
|
|
59
|
+
if (!pmValidation.valid) {
|
|
60
|
+
return res.status(400).json({ error: pmValidation.error })
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Obter diretório de trabalho inicial do app.locals
|
|
64
|
+
const initialCwd = req.app.locals.initialCwd || process.cwd()
|
|
65
|
+
|
|
66
|
+
// Gerar projeto no diretório atual (padrão BMAD/NEX - não cria nova pasta)
|
|
67
|
+
const projectPath = await generateProject({
|
|
68
|
+
template,
|
|
69
|
+
agents,
|
|
70
|
+
packageManager,
|
|
71
|
+
cursorIntegration,
|
|
72
|
+
options,
|
|
73
|
+
targetDir: initialCwd
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
res.json({
|
|
77
|
+
success: true,
|
|
78
|
+
path: projectPath,
|
|
79
|
+
message: `NEX inicializado com sucesso no diretório atual!`
|
|
80
|
+
})
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('Erro ao gerar projeto:', error)
|
|
83
|
+
res.status(500).json({
|
|
84
|
+
error: error.message
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
export default router
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
Projeto NEX API criado com create-nex-app.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Instalar dependências
|
|
9
|
+
{{packageManager}} install
|
|
10
|
+
|
|
11
|
+
# Iniciar API
|
|
12
|
+
{{packageManager}} start
|
|
13
|
+
|
|
14
|
+
# Modo desenvolvimento
|
|
15
|
+
{{packageManager}} run dev
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Estrutura
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
{{projectName}}/
|
|
22
|
+
├── src/
|
|
23
|
+
│ └── index.js # API Entry point
|
|
24
|
+
├── .nex-core/ # Configurações NEX
|
|
25
|
+
└── package.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Documentação
|
|
29
|
+
|
|
30
|
+
- [NEX Framework](https://github.com/INOSX/nex-store)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NEX API project created with create-nex-app",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node src/index.js",
|
|
9
|
+
"dev": "node --watch src/index.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"nex",
|
|
13
|
+
"api",
|
|
14
|
+
"backend",
|
|
15
|
+
"ai",
|
|
16
|
+
"agents"
|
|
17
|
+
],
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "PROPRIETARY"
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# NEX Core Configuration
|
|
2
|
+
# Este arquivo é mantido para compatibilidade
|
|
3
|
+
# A configuração principal está em nex/core/config.yaml (se Cursor integration estiver habilitada)
|
|
4
|
+
name: {{projectName}}
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
created_at: ${new Date().toISOString()}
|
|
7
|
+
|
|
8
|
+
# Agents
|
|
9
|
+
agents: []
|
|
10
|
+
|
|
11
|
+
# Settings
|
|
12
|
+
settings:
|
|
13
|
+
language: pt-BR
|
|
14
|
+
output_folder: .nex-core/documents
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
Projeto NEX criado com create-nex-app.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Instalar dependências
|
|
9
|
+
{{packageManager}} install
|
|
10
|
+
|
|
11
|
+
# Iniciar projeto
|
|
12
|
+
{{packageManager}} start
|
|
13
|
+
|
|
14
|
+
# Modo desenvolvimento (watch)
|
|
15
|
+
{{packageManager}} run dev
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Estrutura
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
{{projectName}}/
|
|
22
|
+
├── src/
|
|
23
|
+
│ └── index.js # Entry point
|
|
24
|
+
├── .nex-core/ # Configurações NEX
|
|
25
|
+
│ ├── agents/ # Agentes instalados
|
|
26
|
+
│ └── data/ # Dados dos agentes
|
|
27
|
+
└── package.json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## NEX CLI
|
|
31
|
+
|
|
32
|
+
Para gerenciar agentes e configurações:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Instalar agente
|
|
36
|
+
nex agent install <agent-id>
|
|
37
|
+
|
|
38
|
+
# Listar agentes
|
|
39
|
+
nex agent list
|
|
40
|
+
|
|
41
|
+
# Ver configuração
|
|
42
|
+
nex config show
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Documentação
|
|
46
|
+
|
|
47
|
+
- [NEX Framework](https://github.com/INOSX/nex-store)
|
|
48
|
+
- [NEX Marketplace](https://github.com/INOSX/nex-store)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NEX project created with create-nex-app",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node src/index.js",
|
|
9
|
+
"dev": "node --watch src/index.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"nex",
|
|
13
|
+
"ai",
|
|
14
|
+
"agents"
|
|
15
|
+
],
|
|
16
|
+
"author": "",
|
|
17
|
+
"license": "PROPRIETARY"
|
|
18
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
Projeto NEX Full Stack criado com create-nex-app.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Instalar dependências
|
|
9
|
+
{{packageManager}} install
|
|
10
|
+
|
|
11
|
+
# Iniciar servidor
|
|
12
|
+
{{packageManager}} start
|
|
13
|
+
|
|
14
|
+
# Modo desenvolvimento
|
|
15
|
+
{{packageManager}} run dev
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Estrutura
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
{{projectName}}/
|
|
22
|
+
├── src/
|
|
23
|
+
│ ├── server/ # Backend
|
|
24
|
+
│ │ └── index.js
|
|
25
|
+
│ └── client/ # Frontend
|
|
26
|
+
│ └── index.html
|
|
27
|
+
├── .nex-core/ # Configurações NEX
|
|
28
|
+
└── package.json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Documentação
|
|
32
|
+
|
|
33
|
+
- [NEX Framework](https://github.com/INOSX/nex-store)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NEX Full Stack project created with create-nex-app",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/server/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node src/server/index.js",
|
|
9
|
+
"dev": "node --watch src/server/index.js",
|
|
10
|
+
"build": "echo 'Build script - configure conforme necessário'"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"nex",
|
|
14
|
+
"full-stack",
|
|
15
|
+
"ai",
|
|
16
|
+
"agents"
|
|
17
|
+
],
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "PROPRIETARY"
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="pt-BR">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>{{projectName}}</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>{{projectName}}</h1>
|
|
10
|
+
<p>Frontend do projeto NEX</p>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|