@oondemand/create-central-oon 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/LICENSE +91 -0
- package/README.md +70 -0
- package/bin/cli.js +58 -0
- package/package.json +32 -0
- package/src/index.js +117 -0
- package/src/render.js +74 -0
- package/templates/_base/README.md +27 -0
- package/templates/_base/backend/central.config.js +33 -0
- package/templates/_base/backend/central.manifest.json +10 -0
- package/templates/_base/backend/env.example +12 -0
- package/templates/_base/backend/package.json +17 -0
- package/templates/_base/backend/src/collections/gitkeep +0 -0
- package/templates/_base/backend/src/controllers/gitkeep +0 -0
- package/templates/_base/backend/src/documents/gitkeep +0 -0
- package/templates/_base/backend/src/hooks/gitkeep +0 -0
- package/templates/_base/backend/src/integrations/gitkeep +0 -0
- package/templates/_base/backend/src/mappings/gitkeep +0 -0
- package/templates/_base/backend/src/models/gitkeep +0 -0
- package/templates/_base/backend/src/pipelines/gitkeep +0 -0
- package/templates/_base/backend/src/routes/gitkeep +0 -0
- package/templates/_base/backend/src/services/gitkeep +0 -0
- package/templates/_base/backend/src/triggers/gitkeep +0 -0
- package/templates/_base/backend/src/validations/gitkeep +0 -0
- package/templates/_base/frontend/central.ui.json +9 -0
- package/templates/_base/frontend/env.example +5 -0
- package/templates/_base/frontend/index.html +12 -0
- package/templates/_base/frontend/package.json +27 -0
- package/templates/_base/frontend/src/collections/gitkeep +0 -0
- package/templates/_base/frontend/src/dashboards/gitkeep +0 -0
- package/templates/_base/frontend/src/documents/gitkeep +0 -0
- package/templates/_base/frontend/src/main.tsx +12 -0
- package/templates/_base/frontend/src/overrides/gitkeep +0 -0
- package/templates/_base/frontend/src/pipelines/gitkeep +0 -0
- package/templates/_base/frontend/tsconfig.json +17 -0
- package/templates/_base/frontend/vite.config.ts +7 -0
- package/templates/_base/gitignore +6 -0
- package/templates/basic/backend/src/models/Pessoa.js +19 -0
- package/templates/basic/frontend/central.ui.json +9 -0
- package/templates/documentos-fiscais/backend/central.config.js +30 -0
- package/templates/documentos-fiscais/backend/src/models/DocumentoFiscal.js +23 -0
- package/templates/documentos-fiscais/frontend/central.ui.json +17 -0
- package/templates/multi-moedas/backend/central.config.js +30 -0
- package/templates/multi-moedas/backend/src/models/Cotacao.js +23 -0
- package/templates/multi-moedas/backend/src/models/Moeda.js +15 -0
- package/templates/multi-moedas/frontend/central.ui.json +12 -0
- package/templates/omie-sidecar/backend/central.config.js +31 -0
- package/templates/omie-sidecar/backend/src/mappings/pessoa-cliente.js +20 -0
- package/templates/omie-sidecar/backend/src/models/Pessoa.js +24 -0
- package/templates/omie-sidecar/backend/src/triggers/Pessoa.js +14 -0
- package/templates/omie-sidecar/frontend/central.ui.json +9 -0
- package/templates/pedidos-marketplace/backend/central.config.js +30 -0
- package/templates/pedidos-marketplace/backend/src/models/Pedido.js +22 -0
- package/templates/pedidos-marketplace/backend/src/models/Produto.js +16 -0
- package/templates/pedidos-marketplace/frontend/central.ui.json +11 -0
- package/templates/servicos-prestados/backend/central.config.js +30 -0
- package/templates/servicos-prestados/backend/src/models/Cliente.js +15 -0
- package/templates/servicos-prestados/backend/src/models/ServicoPrestado.js +22 -0
- package/templates/servicos-prestados/frontend/central.ui.json +11 -0
- package/templates/servicos-tomados/backend/central.config.js +30 -0
- package/templates/servicos-tomados/backend/src/models/Pessoa.js +15 -0
- package/templates/servicos-tomados/backend/src/models/Servico.js +22 -0
- package/templates/servicos-tomados/frontend/central.ui.json +11 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# LICENÇA DE USO RESTRITO DO CÓDIGO-FONTE OONDEMAND
|
|
2
|
+
**ODR‑NC v1.0 — Non‑Commercial, Internal‑Use Only**
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2025 OonDemand. Todos os direitos reservados.
|
|
5
|
+
|
|
6
|
+
## 1. Definições
|
|
7
|
+
**“Licenciante”**: OonDemand.
|
|
8
|
+
**“Código”**: todo o conteúdo deste repositório e seus derivados.
|
|
9
|
+
**“Licenciada”** ou **“Usuário Autorizado”**: a pessoa jurídica nominalmente autorizada pela Licenciante (via contrato ou arquivo `AUTORIZACOES.md`).
|
|
10
|
+
**“Uso Interno Não Comercial”**: uso exclusivo dentro da organização da Licenciada, para suas próprias operações internas, sem disponibilização a terceiros e sem geração de receita direta ou indireta a partir do Código, incluindo sem se limitar a: revenda, prestação de serviços a terceiros, franquia, SaaS, consultoria, sublicenciamento, distribuição ou incorporação em produtos/serviços comercializados.
|
|
11
|
+
|
|
12
|
+
## 2. Concessão Limitada
|
|
13
|
+
Sujeito ao cumprimento integral desta Licença, a Licenciante concede à Licenciada uma licença **não exclusiva, intransferível e revogável** para **acessar, visualizar, modificar, compilar e executar** o Código **exclusivamente para Uso Interno Não Comercial**. Nenhum direito é concedido para **distribuir, publicar, sublicenciar, ceder** ou **oferecer a terceiros** o Código (ou obras derivadas).
|
|
14
|
+
|
|
15
|
+
Qualquer **Uso Comercial** (incluindo oferta como serviço, SaaS, revenda, consultoria, integração para clientes externos ou uso em qualquer outra empresa do mesmo grupo econômico) **exige autorização prévia e expressa da Licenciante, por escrito** e com condições comerciais específicas. Na ausência de tal autorização, o Uso Comercial é **estritamente proibido**.
|
|
16
|
+
|
|
17
|
+
## 3. Restrições e Obrigações
|
|
18
|
+
A Licenciada se compromete a:
|
|
19
|
+
1. **Não** remover ou alterar avisos de copyright, marcas, avisos de confidencialidade e desta Licença;
|
|
20
|
+
2. **Não** publicar ou tornar o Código (ou parte significativa) acessível publicamente (incl. repositórios públicos, fóruns, pacotes);
|
|
21
|
+
3. **Não** distribuir, vender, revender, licenciar, sublicenciar, alugar, arrendar, franquear, ceder ou transferir o Código a terceiros;
|
|
22
|
+
4. **Não** utilizar o Código para treinar modelos de IA, realizar engenharia reversa de mecanismos de licenciamento ou produzir obra concorrente direta;
|
|
23
|
+
5. Adotar controles de acesso (RBAC), registro de auditoria e medidas razoáveis de segurança para impedir uso não autorizado; e
|
|
24
|
+
6. Garantir que terceiros (funcionários, prestadores) observem as mesmas obrigações de confidencialidade e uso restrito.
|
|
25
|
+
|
|
26
|
+
## 4. Propriedade Intelectual
|
|
27
|
+
O Código é protegido por leis de propriedade intelectual. **A titularidade integral permanece com a Licenciante**. Exceto pelos direitos limitados concedidos nesta Licença, **nenhum outro direito** (explícito, implícito, por estoppel) é concedido.
|
|
28
|
+
|
|
29
|
+
## 5. Autorização Expressa para Uso Comercial
|
|
30
|
+
Qualquer permissão de Uso Comercial deverá:
|
|
31
|
+
- Ser **prévia e por escrito**, concedida pela Licenciante;
|
|
32
|
+
- Constar em contrato específico **ou** no arquivo `AUTORIZACOES.md` deste repositório, com **razão social/CNPJ**, **escopo**, **prazo** e **condições comerciais**; e
|
|
33
|
+
- Ser **revogável** por descumprimento.
|
|
34
|
+
|
|
35
|
+
## 6. Cláusula Penal (Multa) por Uso Indevido
|
|
36
|
+
O uso em desacordo com esta Licença (incluindo Uso Comercial sem autorização) sujeitará a Licenciada ao pagamento de **cláusula penal não compensatória** no valor de **R$ 600.000,00 (seiscentos mil reais) por infração**, **cumulável** com:
|
|
37
|
+
- **R$ 5.000,00 (cinco mil reais) por dia** enquanto perdurar a infração; e
|
|
38
|
+
- Indenização adicional por **perdas e danos** e **honorários advocatícios**.
|
|
39
|
+
A aplicação desta cláusula penal **não limita** o direito da Licenciante de buscar tutela específica, inclusive **medidas liminares/inibitórias**.
|
|
40
|
+
|
|
41
|
+
## 7. Confidencialidade
|
|
42
|
+
O Código e a documentação correlata constituem **informação confidencial**. A Licenciada deve preservá-la com o mesmo grau de zelo usado para suas informações confidenciais, nunca inferior ao razoável.
|
|
43
|
+
|
|
44
|
+
## 8. Ausência de Garantias; Limitação de Responsabilidade
|
|
45
|
+
O Código é fornecido “**no estado em que se encontra**”, sem garantias de qualquer tipo. Na máxima extensão permitida em lei, a Licenciante **não responde** por danos indiretos, lucros cessantes, perda de dados ou danos especiais. A responsabilidade total da Licenciante, por qualquer teoria, **fica limitada ao valor total efetivamente pago** pela Licenciada em favor da Licenciante pelo direito de uso do Código, se houver.
|
|
46
|
+
|
|
47
|
+
## 9. Vigência, Revogação e Auditoria
|
|
48
|
+
Esta Licença vigora enquanto o Código estiver em posse da Licenciada e poderá ser **revogada** a qualquer tempo em caso de violação. A Licenciante poderá solicitar **evidências razoáveis de conformidade** (ex.: lista de usuários, ambientes de execução) mediante aviso prévio escrito de 5 dias úteis.
|
|
49
|
+
|
|
50
|
+
## 10. Terceiros e Dependências
|
|
51
|
+
Componentes de terceiros incluídos no repositório permanecem regidos por suas **próprias licenças**. Em caso de conflito, prevalece a licença do respectivo terceiro para tal componente.
|
|
52
|
+
|
|
53
|
+
## 11. Lei Aplicável e Foro
|
|
54
|
+
Aplica-se a legislação brasileira. Fica eleito o **Foro da Comarca de São Paulo/SP**, com renúncia a qualquer outro, por mais privilegiado que seja.
|
|
55
|
+
|
|
56
|
+
## 12. Disposições Finais
|
|
57
|
+
Se qualquer cláusula for considerada inválida, as demais permanecem válidas. Qualquer tolerância não implicará renúncia. Esta é a versão **ODR‑NC v1.0**. A Licenciante poderá publicar **atualizações** desta Licença; versões futuras não terão efeito retroativo sem aceite da Licenciada.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### Identificação de Autorização (opcional, para uso interno)
|
|
62
|
+
> Este repositório está licenciado para uso interno por: **[RAZÃO SOCIAL]**, **CNPJ [XX.XXX.XXX/0001-XX]**, conforme autorização datada de **[DATA]** e/ou contrato específico. Escopo: **[DESCREVER]**.
|
|
63
|
+
|
|
64
|
+
### Como cumprir esta Licença
|
|
65
|
+
1) Mantenha este arquivo `LICENSE.md` na raiz do repositório;
|
|
66
|
+
2) Liste autorizações de uso comercial, se houver, em `AUTORIZACOES.md`; e
|
|
67
|
+
3) Inclua o cabeçalho de licença abaixo em **cada arquivo-fonte**.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Cabeçalho de Licença para Arquivos-Fonte
|
|
72
|
+
Copie e adapte o bloco conforme a linguagem:
|
|
73
|
+
|
|
74
|
+
### Padrão (C/Java/JS/TS)
|
|
75
|
+
/*
|
|
76
|
+
OonDemand — Código-Fonte Proprietário
|
|
77
|
+
Licença ODR‑NC v1.0 — Uso interno não comercial. Proibida revenda/redistribuição/uso comercial sem autorização expressa da OonDemand. Violação sujeita à multa, conforme LICENSE.md.
|
|
78
|
+
(c) 2025 OonDemand. Todos os direitos reservados.
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
### Python
|
|
82
|
+
"""
|
|
83
|
+
OonDemand — Código-Fonte Proprietário
|
|
84
|
+
Licença ODR‑NC v1.0 — Uso interno não comercial. Proibida revenda/redistribuição/uso comercial sem autorização expressa da OonDemand. Violação sujeita à multa, conforme LICENSE.md.
|
|
85
|
+
(c) 2025 OonDemand. Todos os direitos reservados.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
### Shell/YAML
|
|
89
|
+
# OonDemand — Código-Fonte Proprietário
|
|
90
|
+
# Licença ODR‑NC v1.0 — Uso interno não comercial. Proibida revenda/redistribuição/uso comercial sem autorização expressa da OonDemand. Violação sujeita à multa, conforme LICENSE.md.
|
|
91
|
+
# (c) 2025 OonDemand. Todos os direitos reservados.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @oondemand/create-central-oon
|
|
2
|
+
|
|
3
|
+
Gerador de **Centrais Oon**. Cria, a partir do nome da Central, um `backend/` e
|
|
4
|
+
um `frontend/` **mínimos** — só domínio e declaração — prontos para consumir o
|
|
5
|
+
Core (`@oondemand/oon-core-back` e `@oondemand/oon-core-front`).
|
|
6
|
+
|
|
7
|
+
Substitui os geradores legados `@oondemand/create-ooncore-back|front`, que
|
|
8
|
+
copiavam o app inteiro. Aqui só nasce o esqueleto: nada de `server.js`,
|
|
9
|
+
`app.js`, `db.js`, middlewares, Dockerfile, manifestos k8s à mão ou router
|
|
10
|
+
manual — isso tudo vive no Core.
|
|
11
|
+
|
|
12
|
+
## Uso
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx create-central-oon central-transtour
|
|
16
|
+
npx create-central-oon central-transtour --template=omie-sidecar
|
|
17
|
+
npx create-central-oon "Minha Loja" --template=multi-moedas --no-install
|
|
18
|
+
npx create-central-oon --list
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Aliases: o binário também responde por `scaffold-central-oon`.
|
|
22
|
+
|
|
23
|
+
### Opções
|
|
24
|
+
|
|
25
|
+
| Flag | Efeito |
|
|
26
|
+
| ---------------- | ------------------------------------------------------------- |
|
|
27
|
+
| `--template=<t>` | Template inicial (default: `basic`). Veja `--list`. |
|
|
28
|
+
| `--here` | Gera na pasta atual em vez de criar `<nome>/`. |
|
|
29
|
+
| `--force` | Sobrescreve uma pasta existente não-vazia. |
|
|
30
|
+
| `--no-install` | Não roda `npm install` nos projetos gerados. |
|
|
31
|
+
| `--list` | Lista os templates e sai. |
|
|
32
|
+
|
|
33
|
+
## Templates
|
|
34
|
+
|
|
35
|
+
| Template | O que gera |
|
|
36
|
+
| --------------------- | ------------------------------------------------------------- |
|
|
37
|
+
| `basic` | Uma coleção dinâmica (`Pessoa`). |
|
|
38
|
+
| `omie-sidecar` | Coleção + integração Omie (mapping de cliente + trigger). |
|
|
39
|
+
| `servicos-tomados` | Prestadores + esteira de serviços por `statusProcessamento`. |
|
|
40
|
+
| `servicos-prestados` | Clientes + esteira de serviços prestados por `etapa`. |
|
|
41
|
+
| `pedidos-marketplace` | Catálogo de produtos + esteira de pedidos por `status`. |
|
|
42
|
+
| `documentos-fiscais` | Documento fiscal com aprovação (`CoreDocument`). |
|
|
43
|
+
| `multi-moedas` | `Moeda` + `Cotacao` com o módulo currencies. |
|
|
44
|
+
|
|
45
|
+
## Estrutura gerada
|
|
46
|
+
|
|
47
|
+
```txt
|
|
48
|
+
<central>/
|
|
49
|
+
├── README.md
|
|
50
|
+
├── backend/ # consome @oondemand/oon-core-back
|
|
51
|
+
│ ├── central.config.js # identidade + módulos + paths de domínio
|
|
52
|
+
│ ├── central.manifest.json # valores de deploy (render no Core)
|
|
53
|
+
│ └── src/{models,validations,triggers,hooks,mappings,documents,
|
|
54
|
+
│ pipelines,integrations,routes,controllers,services}/
|
|
55
|
+
└── frontend/ # consome @oondemand/oon-core-front
|
|
56
|
+
├── central.ui.json # declaração das telas (coleções/esteiras/docs)
|
|
57
|
+
└── src/
|
|
58
|
+
├── main.tsx # só `startFromManifest(manifest, { apiBaseUrl })`
|
|
59
|
+
└── {collections,documents,pipelines,dashboards,overrides}/
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Próximos passos após gerar
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd <central>/backend && cp .env.example .env && npm run dev # expõe /core/metadata
|
|
66
|
+
cd ../frontend && cp .env.example .env && npm run dev # renderiza pela metadata
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Evoluir = criar models em `backend/src/models` e declarar telas em
|
|
70
|
+
`frontend/central.ui.json`. Grid, form, rotas e menu são montados pelo Core.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CLI do create-central-oon (Fase 4 — Seção 5/25).
|
|
6
|
+
*
|
|
7
|
+
* npx create-central-oon <nome-da-central> [opções]
|
|
8
|
+
*
|
|
9
|
+
* Opções:
|
|
10
|
+
* --template=<t> Template inicial (default: basic). Veja --list.
|
|
11
|
+
* --here Gera na pasta atual em vez de criar <nome>/.
|
|
12
|
+
* --force Sobrescreve pasta existente.
|
|
13
|
+
* --no-install Não roda npm install nos projetos gerados.
|
|
14
|
+
* --list Lista os templates disponíveis e sai.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { run, listTemplates } = require("../src/index");
|
|
18
|
+
|
|
19
|
+
function parseArgs(argv) {
|
|
20
|
+
const opts = { template: "basic", here: false, force: false, install: true, list: false };
|
|
21
|
+
const positionals = [];
|
|
22
|
+
for (const arg of argv) {
|
|
23
|
+
if (arg === "--here") opts.here = true;
|
|
24
|
+
else if (arg === "--force") opts.force = true;
|
|
25
|
+
else if (arg === "--no-install") opts.install = false;
|
|
26
|
+
else if (arg === "--list") opts.list = true;
|
|
27
|
+
else if (arg.startsWith("--template=")) opts.template = arg.slice("--template=".length);
|
|
28
|
+
else if (arg === "--template") opts.template = argv[argv.indexOf(arg) + 1];
|
|
29
|
+
else if (!arg.startsWith("-")) positionals.push(arg);
|
|
30
|
+
}
|
|
31
|
+
opts.name = positionals[0];
|
|
32
|
+
return opts;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function main() {
|
|
36
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
37
|
+
|
|
38
|
+
if (opts.list) {
|
|
39
|
+
console.log("Templates disponíveis:\n");
|
|
40
|
+
for (const t of listTemplates()) console.log(` ${t.id.padEnd(20)} ${t.description}`);
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!opts.name) {
|
|
45
|
+
console.error("Uso: npx create-central-oon <nome-da-central> [--template=basic]");
|
|
46
|
+
console.error(" npx create-central-oon --list");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
await run(opts);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error("\n✖", err.message);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oondemand/create-central-oon",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Gerador de Centrais Oon: cria backend + frontend mínimos (só domínio + declaração) prontos para consumir @oondemand/oon-core-back e @oondemand/oon-core-front.",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"create-central-oon": "bin/cli.js",
|
|
11
|
+
"scaffold-central-oon": "bin/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin",
|
|
15
|
+
"src",
|
|
16
|
+
"templates",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"oondemand",
|
|
24
|
+
"ooncore",
|
|
25
|
+
"central",
|
|
26
|
+
"scaffold",
|
|
27
|
+
"create",
|
|
28
|
+
"generator"
|
|
29
|
+
],
|
|
30
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
31
|
+
"publishConfig": { "access": "public" }
|
|
32
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
const { spawnSync } = require("node:child_process");
|
|
6
|
+
const { copyTemplate } = require("./render");
|
|
7
|
+
|
|
8
|
+
const TEMPLATES_DIR = path.join(__dirname, "..", "templates");
|
|
9
|
+
|
|
10
|
+
const TEMPLATES = [
|
|
11
|
+
{ id: "basic", description: "Central mínima com uma coleção dinâmica (Pessoa)." },
|
|
12
|
+
{ id: "omie-sidecar", description: "Coleção + integração Omie (mapping de cliente)." },
|
|
13
|
+
{ id: "servicos-tomados", description: "Serviços tomados com esteira por status." },
|
|
14
|
+
{ id: "servicos-prestados", description: "Serviços prestados com esteira por etapa." },
|
|
15
|
+
{ id: "pedidos-marketplace", description: "Pedidos de marketplace com esteira." },
|
|
16
|
+
{ id: "documentos-fiscais", description: "Documentos fiscais com aprovação." },
|
|
17
|
+
{ id: "multi-moedas", description: "Moedas + cotações (módulo currencies)." },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
function listTemplates() {
|
|
21
|
+
return TEMPLATES;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function toSlug(value) {
|
|
25
|
+
return String(value)
|
|
26
|
+
.normalize("NFD")
|
|
27
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
28
|
+
.trim()
|
|
29
|
+
.toLowerCase()
|
|
30
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
31
|
+
.replace(/^-+|-+$/g, "");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function toPascal(slug) {
|
|
35
|
+
return slug
|
|
36
|
+
.split("-")
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.map((p) => p.charAt(0).toUpperCase() + p.slice(1))
|
|
39
|
+
.join("");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function toTitle(slug) {
|
|
43
|
+
return slug
|
|
44
|
+
.split("-")
|
|
45
|
+
.filter(Boolean)
|
|
46
|
+
.map((p) => p.charAt(0).toUpperCase() + p.slice(1))
|
|
47
|
+
.join(" ");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function npmInstall(dir) {
|
|
51
|
+
const r = spawnSync("npm", ["install"], { stdio: "inherit", cwd: dir });
|
|
52
|
+
return !r.status && !r.error;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function run(opts) {
|
|
56
|
+
const template = TEMPLATES.find((t) => t.id === opts.template);
|
|
57
|
+
if (!template) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`Template "${opts.template}" não existe. Use --list para ver os disponíveis.`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const slug = toSlug(opts.name);
|
|
64
|
+
if (!slug) throw new Error("Nome de Central inválido.");
|
|
65
|
+
|
|
66
|
+
const tokens = { slug, name: toTitle(slug), pascal: toPascal(slug) };
|
|
67
|
+
|
|
68
|
+
const targetDir = opts.here ? process.cwd() : path.join(process.cwd(), slug);
|
|
69
|
+
|
|
70
|
+
if (!opts.here && fs.existsSync(targetDir)) {
|
|
71
|
+
const empty = fs.readdirSync(targetDir).length === 0;
|
|
72
|
+
if (!empty && !opts.force) {
|
|
73
|
+
throw new Error(`A pasta "${slug}" já existe e não está vazia. Use --force para sobrescrever.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(`\n⚙ Criando Central "${tokens.name}" (template: ${template.id})`);
|
|
78
|
+
|
|
79
|
+
// 1. Estrutura comum (backend + frontend mínimos, só domínio/declaração).
|
|
80
|
+
copyTemplate(path.join(TEMPLATES_DIR, "_base"), targetDir, tokens);
|
|
81
|
+
// 2. Overlay do template escolhido (vence sobre o _base).
|
|
82
|
+
copyTemplate(path.join(TEMPLATES_DIR, template.id), targetDir, tokens);
|
|
83
|
+
|
|
84
|
+
console.log("✔ Arquivos gerados.");
|
|
85
|
+
|
|
86
|
+
if (opts.install) {
|
|
87
|
+
console.log("\n📦 Instalando dependências (best-effort)...");
|
|
88
|
+
const backOk = npmInstall(path.join(targetDir, "backend"));
|
|
89
|
+
const frontOk = npmInstall(path.join(targetDir, "frontend"));
|
|
90
|
+
if (!backOk || !frontOk) {
|
|
91
|
+
console.warn(
|
|
92
|
+
"\n⚠ npm install falhou em um dos projetos (esperado se os pacotes @oondemand/* ainda não foram publicados). Rode manualmente depois."
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
printNextSteps(tokens, opts);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function printNextSteps(tokens, opts) {
|
|
101
|
+
const cd = opts.here ? "" : ` cd ${tokens.slug}\n`;
|
|
102
|
+
console.log(`
|
|
103
|
+
✅ Central "${tokens.name}" pronta.
|
|
104
|
+
|
|
105
|
+
Próximos passos:
|
|
106
|
+
${cd} # Backend (só domínio — models/validations/triggers/...)
|
|
107
|
+
cd backend && cp .env.example .env && npm run dev
|
|
108
|
+
|
|
109
|
+
# Frontend (só declaração — central.ui.json)
|
|
110
|
+
cd ../frontend && cp .env.example .env && npm run dev
|
|
111
|
+
|
|
112
|
+
O backend expõe /core/metadata; o frontend renderiza as telas a partir dele.
|
|
113
|
+
Edite backend/src/models e frontend/central.ui.json para evoluir a Central.
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = { run, listTemplates, toSlug, toPascal, toTitle };
|
package/src/render.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
|
|
6
|
+
/** Extensões tratadas como texto (recebem substituição de tokens). */
|
|
7
|
+
const TEXT_EXT = new Set([
|
|
8
|
+
".js",
|
|
9
|
+
".jsx",
|
|
10
|
+
".ts",
|
|
11
|
+
".tsx",
|
|
12
|
+
".json",
|
|
13
|
+
".md",
|
|
14
|
+
".html",
|
|
15
|
+
".css",
|
|
16
|
+
".env",
|
|
17
|
+
".example",
|
|
18
|
+
".gitignore",
|
|
19
|
+
".gitkeep",
|
|
20
|
+
".yml",
|
|
21
|
+
".yaml",
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
/** Nomes "seguros" no template -> dotfile real no destino gerado. */
|
|
25
|
+
const DOTFILE_MAP = {
|
|
26
|
+
gitkeep: ".gitkeep",
|
|
27
|
+
gitignore: ".gitignore",
|
|
28
|
+
"env.example": ".env.example",
|
|
29
|
+
npmrc: ".npmrc",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function isText(file) {
|
|
33
|
+
if (path.basename(file).startsWith(".env")) return true;
|
|
34
|
+
return TEXT_EXT.has(path.extname(file));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Substitui __NAME__ / __SLUG__ / __PASCAL__ no conteúdo. */
|
|
38
|
+
function applyTokens(content, tokens) {
|
|
39
|
+
return content
|
|
40
|
+
.replace(/__NAME__/g, tokens.name)
|
|
41
|
+
.replace(/__SLUG__/g, tokens.slug)
|
|
42
|
+
.replace(/__PASCAL__/g, tokens.pascal);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Copia recursivamente `srcDir` para `destDir`, substituindo tokens em
|
|
47
|
+
* arquivos de texto. Arquivos já existentes no destino são sobrescritos
|
|
48
|
+
* (overlay): o template escolhido vence sobre o _base.
|
|
49
|
+
*/
|
|
50
|
+
function copyTemplate(srcDir, destDir, tokens) {
|
|
51
|
+
if (!fs.existsSync(srcDir)) return;
|
|
52
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
53
|
+
|
|
54
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
55
|
+
const from = path.join(srcDir, entry.name);
|
|
56
|
+
// Dotfiles ficam sem o ponto no template (npm não publica alguns dotfiles)
|
|
57
|
+
// e recebem o ponto ao gerar.
|
|
58
|
+
const destName = DOTFILE_MAP[entry.name] ?? entry.name;
|
|
59
|
+
const to = path.join(destDir, destName);
|
|
60
|
+
|
|
61
|
+
if (entry.isDirectory()) {
|
|
62
|
+
copyTemplate(from, to, tokens);
|
|
63
|
+
} else {
|
|
64
|
+
const raw = fs.readFileSync(from);
|
|
65
|
+
if (isText(from)) {
|
|
66
|
+
fs.writeFileSync(to, applyTokens(raw.toString("utf8"), tokens));
|
|
67
|
+
} else {
|
|
68
|
+
fs.writeFileSync(to, raw);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = { copyTemplate, applyTokens, isText };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# __NAME__
|
|
2
|
+
|
|
3
|
+
Central Oon gerada com `create-central-oon`. É composta por dois projetos
|
|
4
|
+
mínimos que consomem o Core:
|
|
5
|
+
|
|
6
|
+
- **backend/** — só domínio (`src/models`, `validations`, `triggers`, …).
|
|
7
|
+
Sobe com `oonCore-back dev`. Toda a infra (boot, db, auth, RBAC, metadata,
|
|
8
|
+
CRUD, deploy) vem do `@oondemand/oon-core-back`.
|
|
9
|
+
- **frontend/** — só declaração (`central.ui.json`). Sobe com `oonCore-front
|
|
10
|
+
dev`. Shell, providers, roteamento, auth e telas vêm do
|
|
11
|
+
`@oondemand/oon-core-front`, renderizados a partir do `/core/metadata` do back.
|
|
12
|
+
|
|
13
|
+
## Rodando
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# backend
|
|
17
|
+
cd backend && cp .env.example .env && npm install && npm run dev
|
|
18
|
+
|
|
19
|
+
# frontend (noutro terminal)
|
|
20
|
+
cd frontend && cp .env.example .env && npm install && npm run dev
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Evoluindo a Central
|
|
24
|
+
|
|
25
|
+
1. Crie models em `backend/src/models` (só schema + CRUD).
|
|
26
|
+
2. Declare as telas em `frontend/central.ui.json` (coleções/esteiras/documentos).
|
|
27
|
+
3. O resto — grid, form, rotas, menu — é montado pelo Core automaticamente.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuração da Central __NAME__ (Seção 8). Apenas identidade, módulos
|
|
3
|
+
* ativos e os paths de domínio. Sem db/auth/deploy — isso vive no Core e nas
|
|
4
|
+
* variáveis de ambiente.
|
|
5
|
+
*/
|
|
6
|
+
module.exports = {
|
|
7
|
+
name: "__NAME__",
|
|
8
|
+
slug: "__SLUG__",
|
|
9
|
+
|
|
10
|
+
// Módulos opinativos do Core ligados nesta Central.
|
|
11
|
+
modules: {
|
|
12
|
+
collections: true,
|
|
13
|
+
documents: false,
|
|
14
|
+
pipelines: false,
|
|
15
|
+
integrations: false,
|
|
16
|
+
omie: false,
|
|
17
|
+
assistants: false,
|
|
18
|
+
currencies: false,
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
// Paths de domínio (carregados por convenção pelo Core no boot).
|
|
22
|
+
domain: {
|
|
23
|
+
models: "src/models",
|
|
24
|
+
validations: "src/validations",
|
|
25
|
+
triggers: "src/triggers",
|
|
26
|
+
hooks: "src/hooks",
|
|
27
|
+
mappings: "src/mappings",
|
|
28
|
+
documents: "src/documents",
|
|
29
|
+
pipelines: "src/pipelines",
|
|
30
|
+
integrations: "src/integrations",
|
|
31
|
+
routes: "src/routes",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Identidade
|
|
2
|
+
SERVICE_NAME=__SLUG__
|
|
3
|
+
SERVICE_VERSION=0.1.0
|
|
4
|
+
PORT=4000
|
|
5
|
+
NODE_ENV=development
|
|
6
|
+
|
|
7
|
+
# Banco
|
|
8
|
+
MONGO_URI=mongodb://localhost:27017/__SLUG__
|
|
9
|
+
|
|
10
|
+
# Autenticação (provedor padrão: Meus Apps)
|
|
11
|
+
MEUS_APPS_BACKEND_URL=https://meus-apps.example.com
|
|
12
|
+
APP_KEY=
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__SLUG__-backend",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Backend da Central __NAME__ — só domínio, consome @oondemand/oon-core-back.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "oonCore-back dev",
|
|
8
|
+
"start": "oonCore-back start",
|
|
9
|
+
"activate": "oonCore-back activate",
|
|
10
|
+
"build:image": "oonCore-back build:image",
|
|
11
|
+
"k8s:render": "oonCore-back k8s:render",
|
|
12
|
+
"deploy": "oonCore-back deploy"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@oondemand/oon-core-back": "^0.1.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -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>__NAME__</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__SLUG__-frontend",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "oonCore-front dev",
|
|
8
|
+
"build": "oonCore-front build",
|
|
9
|
+
"preview": "oonCore-front preview",
|
|
10
|
+
"sync:metadata": "oonCore-front sync:metadata"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@oondemand/oon-core-front": "^0.1.0",
|
|
14
|
+
"@chakra-ui/react": "^3.13.0",
|
|
15
|
+
"@emotion/react": "^11.14.0",
|
|
16
|
+
"@tanstack/react-query": "^5.65.0",
|
|
17
|
+
"@tanstack/react-table": "^8.20.6",
|
|
18
|
+
"react": "^18.3.1",
|
|
19
|
+
"react-dom": "^18.3.1",
|
|
20
|
+
"react-router-dom": "^6.28.2"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
24
|
+
"typescript": "^5.5.0",
|
|
25
|
+
"vite": "^6.0.5"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { startFromManifest } from "@oondemand/oon-core-front";
|
|
2
|
+
import manifest from "../central.ui.json";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Toda a Central __NAME__ inicia por aqui. Sem providers, router, auth, layout
|
|
6
|
+
* ou páginas — só o manifesto declarativo `central.ui.json`. O Core resolve as
|
|
7
|
+
* telas a partir do `/core/metadata` do backend.
|
|
8
|
+
*/
|
|
9
|
+
startFromManifest(manifest, {
|
|
10
|
+
apiBaseUrl: import.meta.env.VITE_API_URL ?? "http://localhost:4000",
|
|
11
|
+
meusAppsUrl: import.meta.env.VITE_MEUS_APPS_URL,
|
|
12
|
+
});
|
|
File without changes
|