@oondemand/create-central-oon 0.3.8 → 0.3.10
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 +60 -4
- package/bin/cli.js +59 -13
- package/docs/BACKEND_PATTERNS.md +87 -0
- package/docs/CHECKLIST_IMPLEMENTACAO.md +41 -0
- package/docs/CODEX.md +46 -0
- package/docs/COLLECTIONS_AND_PIPELINES.md +66 -0
- package/docs/CONNECTORS_AND_INTEGRATIONS.md +66 -0
- package/docs/DO_AND_DONT.md +27 -0
- package/docs/FRONTEND_MANIFEST_REFERENCE.md +691 -0
- package/docs/FRONTEND_PATTERNS.md +77 -0
- package/docs/OONCORE_ARCHITECTURE.md +50 -0
- package/docs/RBAC_SECURITY.md +35 -0
- package/package.json +6 -3
- package/src/index.js +203 -4
- package/templates/_base/README.md +20 -3
- package/templates/_base/backend/package.json +1 -1
- package/templates/_base/frontend/package.json +1 -1
- package/templates/_base/package.json +15 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Padrões Frontend
|
|
2
|
+
|
|
3
|
+
O frontend da Central deve ser declarativo. Shell, providers, rotas, menu, datagrid, formulários, documentos e esteiras pertencem ao `@oondemand/oon-core-front`.
|
|
4
|
+
|
|
5
|
+
Para a lista completa de opções do manifesto, use `FRONTEND_MANIFEST_REFERENCE.md`.
|
|
6
|
+
|
|
7
|
+
## Estrutura esperada
|
|
8
|
+
|
|
9
|
+
```txt
|
|
10
|
+
frontend/
|
|
11
|
+
├── central.ui.json
|
|
12
|
+
└── src/
|
|
13
|
+
├── main.tsx
|
|
14
|
+
├── collections/
|
|
15
|
+
├── documents/
|
|
16
|
+
├── pipelines/
|
|
17
|
+
├── dashboards/
|
|
18
|
+
└── overrides/
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## central.ui.json
|
|
22
|
+
|
|
23
|
+
Use `central.ui.json` como entrada principal para declarar:
|
|
24
|
+
|
|
25
|
+
- menu;
|
|
26
|
+
- coleções;
|
|
27
|
+
- campos exibidos;
|
|
28
|
+
- filtros;
|
|
29
|
+
- ações;
|
|
30
|
+
- formulários;
|
|
31
|
+
- documentos;
|
|
32
|
+
- esteiras;
|
|
33
|
+
- dashboards;
|
|
34
|
+
- agrupamentos;
|
|
35
|
+
- layout v2;
|
|
36
|
+
- páginas por blocos;
|
|
37
|
+
- renderers por chave.
|
|
38
|
+
|
|
39
|
+
## Manifesto v1 e v2
|
|
40
|
+
|
|
41
|
+
- Manifesto sem `schemaVersion` mantém compatibilidade v1.
|
|
42
|
+
- Manifesto com `schemaVersion: 2` habilita composição por `layout`, `navigation`, `pages` e `blocks`.
|
|
43
|
+
- Componentes React não devem ser serializados no JSON; use chaves e registre os componentes no `registry` em TypeScript.
|
|
44
|
+
|
|
45
|
+
## Regras
|
|
46
|
+
|
|
47
|
+
- Não recrie layout completo se o Core já renderiza.
|
|
48
|
+
- Não duplique chamada REST manual se o SDK do Core já atende.
|
|
49
|
+
- Não coloque regra de permissão apenas no frontend.
|
|
50
|
+
- Não hardcode endpoints quando a metadata puder fornecer.
|
|
51
|
+
- Não crie variações visuais fora do padrão sem necessidade real.
|
|
52
|
+
- Use overrides pequenos, específicos e documentados.
|
|
53
|
+
|
|
54
|
+
## Overrides
|
|
55
|
+
|
|
56
|
+
Overrides são permitidos para:
|
|
57
|
+
|
|
58
|
+
- campo especial;
|
|
59
|
+
- ação específica;
|
|
60
|
+
- card customizado;
|
|
61
|
+
- cabeçalho customizado;
|
|
62
|
+
- dashboard customizado;
|
|
63
|
+
- integração visual pontual.
|
|
64
|
+
|
|
65
|
+
Overrides não devem virar uma reimplementação do Core.
|
|
66
|
+
|
|
67
|
+
## Experiência padrão
|
|
68
|
+
|
|
69
|
+
A Central deve manter o padrão OonCore:
|
|
70
|
+
|
|
71
|
+
- navegação consistente;
|
|
72
|
+
- datagrids densos;
|
|
73
|
+
- formulários claros;
|
|
74
|
+
- feedback visual;
|
|
75
|
+
- status por badges;
|
|
76
|
+
- ações rastreáveis;
|
|
77
|
+
- responsividade.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Arquitetura OonCore
|
|
2
|
+
|
|
3
|
+
O OonCore é a base para criar Centrais operacionais sob demanda com arquitetura padronizada, segura e evolutiva.
|
|
4
|
+
|
|
5
|
+
A Central gerada não deve nascer como um sistema completo do zero. Ela deve nascer como uma camada de domínio que consome os recursos do Core.
|
|
6
|
+
|
|
7
|
+
## Separação de responsabilidades
|
|
8
|
+
|
|
9
|
+
```txt
|
|
10
|
+
Central
|
|
11
|
+
├── backend/ domínio, regras, validações, integrações e esteiras
|
|
12
|
+
└── frontend/ declaração de telas, coleções, documentos e overrides
|
|
13
|
+
|
|
14
|
+
OonCore Back
|
|
15
|
+
├── boot Express
|
|
16
|
+
├── Mongo/Mongoose
|
|
17
|
+
├── autenticação
|
|
18
|
+
├── RBAC
|
|
19
|
+
├── CRUD metadata-driven
|
|
20
|
+
├── auditoria
|
|
21
|
+
├── triggers/hooks
|
|
22
|
+
└── APIs padrão
|
|
23
|
+
|
|
24
|
+
OonCore Front
|
|
25
|
+
├── shell React
|
|
26
|
+
├── providers
|
|
27
|
+
├── roteamento
|
|
28
|
+
├── menu
|
|
29
|
+
├── datagrid
|
|
30
|
+
├── formulários
|
|
31
|
+
├── documentos
|
|
32
|
+
├── esteiras
|
|
33
|
+
└── SDK REST
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Modelo mini-monolítico
|
|
37
|
+
|
|
38
|
+
Cada Central começa como um mini-monolito de negócio: pequeno, coeso, isolado e capaz de entregar valor rapidamente. Quando uma parte do domínio se tornar reutilizável, crítica ou independente, ela pode evoluir para conector, serviço compartilhado ou micro-serviço.
|
|
39
|
+
|
|
40
|
+
## Fonte de verdade
|
|
41
|
+
|
|
42
|
+
- Dados e regras ficam no backend.
|
|
43
|
+
- Metadata operacional é exposta pelo backend.
|
|
44
|
+
- Frontend renderiza a experiência a partir da metadata.
|
|
45
|
+
- Permissões são decididas no backend.
|
|
46
|
+
- Integrações são tratadas como conectores, mappings, triggers e esteiras de integração.
|
|
47
|
+
|
|
48
|
+
## Objetivo do Codex
|
|
49
|
+
|
|
50
|
+
O Codex deve acelerar a construção da Central usando a arquitetura existente. O objetivo não é gerar um app genérico, mas sim completar a camada de domínio com segurança e aderência ao Core.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# RBAC e Segurança
|
|
2
|
+
|
|
3
|
+
A segurança da Central deve ser aplicada no backend. O frontend pode ocultar ou exibir ações, mas não é a fonte de decisão.
|
|
4
|
+
|
|
5
|
+
## Regras obrigatórias
|
|
6
|
+
|
|
7
|
+
- Toda operação sensível deve validar usuário autenticado.
|
|
8
|
+
- Toda alteração de dados deve validar permissão.
|
|
9
|
+
- Toda ação de integração deve validar permissão e contexto.
|
|
10
|
+
- Nunca confiar em `tenantId`, `appId`, `perfil` ou `roles` enviados livremente pelo frontend.
|
|
11
|
+
- Segredos devem vir de variáveis de ambiente ou vault equivalente.
|
|
12
|
+
- Logs não devem expor tokens, senhas, app keys ou dados sensíveis desnecessários.
|
|
13
|
+
|
|
14
|
+
## RBAC
|
|
15
|
+
|
|
16
|
+
Use o RBAC do Core para:
|
|
17
|
+
|
|
18
|
+
- controlar acesso por app;
|
|
19
|
+
- controlar perfis;
|
|
20
|
+
- controlar ações;
|
|
21
|
+
- filtrar funcionalidades;
|
|
22
|
+
- proteger rotas;
|
|
23
|
+
- permitir evolução de permissões sem reconstruir telas.
|
|
24
|
+
|
|
25
|
+
## Checklist de segurança para Codex
|
|
26
|
+
|
|
27
|
+
Antes de concluir uma alteração, confirme:
|
|
28
|
+
|
|
29
|
+
- Existe validação de entrada?
|
|
30
|
+
- Existe validação de permissão no backend?
|
|
31
|
+
- Existe tratamento de erro?
|
|
32
|
+
- A operação gera rastreabilidade?
|
|
33
|
+
- Algum segredo foi colocado no código?
|
|
34
|
+
- Algum dado sensível foi exposto no frontend?
|
|
35
|
+
- O comportamento funciona para múltiplos usuários e múltiplos apps?
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oondemand/create-central-oon",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/oondemand/oon-platform.git",
|
|
7
7
|
"directory": "packages/create-central-oon"
|
|
8
8
|
},
|
|
9
|
-
"description": "Gerador de Centrais Oon com backend declarativo
|
|
9
|
+
"description": "Gerador de Centrais Oon com backend declarativo, frontend padrão e documentação interna OonCore para Codex.",
|
|
10
10
|
"main": "src/index.js",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": "./src/index.js"
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"bin",
|
|
20
20
|
"src",
|
|
21
21
|
"templates",
|
|
22
|
+
"docs",
|
|
22
23
|
"README.md"
|
|
23
24
|
],
|
|
24
25
|
"engines": {
|
|
@@ -30,7 +31,9 @@
|
|
|
30
31
|
"central",
|
|
31
32
|
"scaffold",
|
|
32
33
|
"create",
|
|
33
|
-
"generator"
|
|
34
|
+
"generator",
|
|
35
|
+
"codex",
|
|
36
|
+
"docs"
|
|
34
37
|
],
|
|
35
38
|
"license": "SEE LICENSE IN LICENSE",
|
|
36
39
|
"publishConfig": {
|
package/src/index.js
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const path = require("node:path");
|
|
5
|
+
const crypto = require("node:crypto");
|
|
5
6
|
const { spawnSync } = require("node:child_process");
|
|
6
7
|
const { copyTemplate } = require("./render");
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const PACKAGE_ROOT = path.join(__dirname, "..");
|
|
10
|
+
const TEMPLATES_DIR = path.join(PACKAGE_ROOT, "templates");
|
|
11
|
+
const DOCS_DIR = path.join(PACKAGE_ROOT, "docs");
|
|
9
12
|
|
|
10
13
|
const TEMPLATES = [
|
|
11
14
|
{ id: "basic", description: "Central mínima com uma coleção dinâmica (Pessoa)." },
|
|
@@ -52,6 +55,183 @@ function npmInstall(dir) {
|
|
|
52
55
|
return !r.status && !r.error;
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
function readPackageVersion() {
|
|
59
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8"));
|
|
60
|
+
return pkg.version;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function listDocFiles(dir = DOCS_DIR, prefix = "") {
|
|
64
|
+
if (!fs.existsSync(dir)) return [];
|
|
65
|
+
const files = [];
|
|
66
|
+
|
|
67
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
68
|
+
const relative = path.join(prefix, entry.name);
|
|
69
|
+
const absolute = path.join(dir, entry.name);
|
|
70
|
+
|
|
71
|
+
if (entry.isDirectory()) {
|
|
72
|
+
files.push(...listDocFiles(absolute, relative));
|
|
73
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
74
|
+
files.push(relative);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return files.sort((a, b) => a.localeCompare(b));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function docsHash(files = listDocFiles()) {
|
|
82
|
+
const hash = crypto.createHash("sha256");
|
|
83
|
+
for (const file of files) {
|
|
84
|
+
const normalized = file.split(path.sep).join("/");
|
|
85
|
+
hash.update(normalized);
|
|
86
|
+
hash.update("\n");
|
|
87
|
+
hash.update(fs.readFileSync(path.join(DOCS_DIR, file)));
|
|
88
|
+
hash.update("\n");
|
|
89
|
+
}
|
|
90
|
+
return hash.digest("hex");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function resolveCentralRoot(cwd = process.cwd()) {
|
|
94
|
+
const current = path.resolve(cwd);
|
|
95
|
+
const parent = path.dirname(current);
|
|
96
|
+
|
|
97
|
+
if (fs.existsSync(path.join(current, "backend")) && fs.existsSync(path.join(current, "frontend"))) {
|
|
98
|
+
return current;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (
|
|
102
|
+
["backend", "frontend"].includes(path.basename(current)) &&
|
|
103
|
+
fs.existsSync(path.join(parent, "backend")) &&
|
|
104
|
+
fs.existsSync(path.join(parent, "frontend"))
|
|
105
|
+
) {
|
|
106
|
+
return parent;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return current;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function removeDir(dir) {
|
|
113
|
+
if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function copyDocs(srcDir, destDir) {
|
|
117
|
+
if (!fs.existsSync(srcDir)) {
|
|
118
|
+
throw new Error(`Diretório de documentação não encontrado: ${srcDir}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
122
|
+
|
|
123
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
124
|
+
const from = path.join(srcDir, entry.name);
|
|
125
|
+
const to = path.join(destDir, entry.name);
|
|
126
|
+
|
|
127
|
+
if (entry.isDirectory()) {
|
|
128
|
+
copyDocs(from, to);
|
|
129
|
+
} else if (entry.isFile()) {
|
|
130
|
+
fs.copyFileSync(from, to);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function buildContext(files = listDocFiles()) {
|
|
136
|
+
const header = [
|
|
137
|
+
"# OonCore Contexto Consolidado para Codex",
|
|
138
|
+
"",
|
|
139
|
+
"> Arquivo gerado automaticamente por `create-central-oon docs --sync`.",
|
|
140
|
+
"> Não edite manualmente. A fonte de verdade está no pacote `@oondemand/create-central-oon` instalado.",
|
|
141
|
+
"",
|
|
142
|
+
"Este contexto consolida as regras mínimas para codificar Centrais Oon com segurança, usando o máximo dos recursos do OonCore.",
|
|
143
|
+
"",
|
|
144
|
+
].join("\n");
|
|
145
|
+
|
|
146
|
+
const sections = files
|
|
147
|
+
.map((file) => {
|
|
148
|
+
const normalized = file.split(path.sep).join("/");
|
|
149
|
+
const content = fs.readFileSync(path.join(DOCS_DIR, file), "utf8").trim();
|
|
150
|
+
return [
|
|
151
|
+
"---",
|
|
152
|
+
"",
|
|
153
|
+
`<!-- source: ${normalized} -->`,
|
|
154
|
+
"",
|
|
155
|
+
content,
|
|
156
|
+
"",
|
|
157
|
+
].join("\n");
|
|
158
|
+
})
|
|
159
|
+
.join("\n");
|
|
160
|
+
|
|
161
|
+
return `${header}\n${sections}`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildManifest(files = listDocFiles()) {
|
|
165
|
+
return {
|
|
166
|
+
source: "@oondemand/create-central-oon",
|
|
167
|
+
version: readPackageVersion(),
|
|
168
|
+
generatedAt: new Date().toISOString(),
|
|
169
|
+
docsMode: "generated-cache",
|
|
170
|
+
docsHash: docsHash(files),
|
|
171
|
+
files: files.map((file) => file.split(path.sep).join("/")),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function syncDocs(opts = {}) {
|
|
176
|
+
const root = resolveCentralRoot(opts.cwd);
|
|
177
|
+
const outDir = path.join(root, ".ooncore");
|
|
178
|
+
const docsOutDir = path.join(outDir, "docs");
|
|
179
|
+
const files = listDocFiles();
|
|
180
|
+
|
|
181
|
+
if (!files.length) {
|
|
182
|
+
throw new Error("Nenhum arquivo .md encontrado em packages/create-central-oon/docs.");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
186
|
+
removeDir(docsOutDir);
|
|
187
|
+
copyDocs(DOCS_DIR, docsOutDir);
|
|
188
|
+
|
|
189
|
+
const codexSource = path.join(DOCS_DIR, "CODEX.md");
|
|
190
|
+
if (fs.existsSync(codexSource)) {
|
|
191
|
+
fs.copyFileSync(codexSource, path.join(outDir, "CODEX.md"));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
fs.writeFileSync(path.join(outDir, "context.generated.md"), buildContext(files));
|
|
195
|
+
fs.writeFileSync(path.join(outDir, "manifest.json"), `${JSON.stringify(buildManifest(files), null, 2)}\n`);
|
|
196
|
+
|
|
197
|
+
console.log(`✔ Documentação OonCore sincronizada em ${path.relative(process.cwd(), outDir) || ".ooncore"}`);
|
|
198
|
+
console.log(` Versão: ${readPackageVersion()}`);
|
|
199
|
+
console.log(` Arquivos: ${files.length}`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function checkDocs(opts = {}) {
|
|
203
|
+
const root = resolveCentralRoot(opts.cwd);
|
|
204
|
+
const manifestPath = path.join(root, ".ooncore", "manifest.json");
|
|
205
|
+
const version = readPackageVersion();
|
|
206
|
+
const files = listDocFiles();
|
|
207
|
+
const currentHash = docsHash(files);
|
|
208
|
+
|
|
209
|
+
if (!fs.existsSync(manifestPath)) {
|
|
210
|
+
throw new Error("Documentação OonCore local não encontrada. Rode `npm run ooncore:docs`.");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
214
|
+
const problems = [];
|
|
215
|
+
|
|
216
|
+
if (manifest.source !== "@oondemand/create-central-oon") {
|
|
217
|
+
problems.push(`fonte esperada @oondemand/create-central-oon, encontrada ${manifest.source || "(vazia)"}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (manifest.version !== version) {
|
|
221
|
+
problems.push(`versão local ${manifest.version || "(vazia)"} diferente da instalada ${version}`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (manifest.docsHash !== currentHash) {
|
|
225
|
+
problems.push("hash da documentação local diferente da documentação instalada");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (problems.length) {
|
|
229
|
+
throw new Error(`Documentação OonCore desatualizada:\n- ${problems.join("\n- ")}\nRode \`npm run ooncore:docs\`.`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log(`✔ Documentação OonCore atualizada (versão ${version}).`);
|
|
233
|
+
}
|
|
234
|
+
|
|
55
235
|
async function run(opts) {
|
|
56
236
|
const template = TEMPLATES.find((t) => t.id === opts.template);
|
|
57
237
|
if (!template) {
|
|
@@ -81,13 +261,19 @@ async function run(opts) {
|
|
|
81
261
|
// 2. Overlay do template escolhido (vence sobre o _base).
|
|
82
262
|
copyTemplate(path.join(TEMPLATES_DIR, template.id), targetDir, tokens);
|
|
83
263
|
|
|
264
|
+
// 3. Contexto local para Codex derivado da documentação da versão instalada.
|
|
265
|
+
syncDocs({ cwd: targetDir });
|
|
266
|
+
|
|
84
267
|
console.log("✔ Arquivos gerados.");
|
|
85
268
|
|
|
86
269
|
if (opts.install) {
|
|
87
270
|
console.log("\n📦 Instalando dependências (best-effort)...");
|
|
271
|
+
const rootOk = fs.existsSync(path.join(targetDir, "package.json"))
|
|
272
|
+
? npmInstall(targetDir)
|
|
273
|
+
: true;
|
|
88
274
|
const backOk = npmInstall(path.join(targetDir, "backend"));
|
|
89
275
|
const frontOk = npmInstall(path.join(targetDir, "frontend"));
|
|
90
|
-
if (!backOk || !frontOk) {
|
|
276
|
+
if (!rootOk || !backOk || !frontOk) {
|
|
91
277
|
console.warn(
|
|
92
278
|
"\n⚠ npm install falhou em um dos projetos (esperado se os pacotes @oondemand/* ainda não foram publicados). Rode manualmente depois."
|
|
93
279
|
);
|
|
@@ -103,7 +289,11 @@ function printNextSteps(tokens, opts) {
|
|
|
103
289
|
✅ Central "${tokens.name}" pronta.
|
|
104
290
|
|
|
105
291
|
Próximos passos:
|
|
106
|
-
${cd} #
|
|
292
|
+
${cd} # Sincronizar/validar documentação local do Core para Codex
|
|
293
|
+
npm run ooncore:docs
|
|
294
|
+
npm run ooncore:docs:check
|
|
295
|
+
|
|
296
|
+
# Backend (só domínio — models/validations/triggers/...)
|
|
107
297
|
cd backend && cp .env.example .env && npm run dev
|
|
108
298
|
|
|
109
299
|
# Frontend (só declaração — central.ui.json)
|
|
@@ -114,4 +304,13 @@ Edite backend/src/models e frontend/central.ui.json para evoluir a Central.
|
|
|
114
304
|
`);
|
|
115
305
|
}
|
|
116
306
|
|
|
117
|
-
module.exports = {
|
|
307
|
+
module.exports = {
|
|
308
|
+
run,
|
|
309
|
+
listTemplates,
|
|
310
|
+
toSlug,
|
|
311
|
+
toPascal,
|
|
312
|
+
toTitle,
|
|
313
|
+
syncDocs,
|
|
314
|
+
checkDocs,
|
|
315
|
+
resolveCentralRoot,
|
|
316
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# __NAME__
|
|
2
2
|
|
|
3
|
-
Central Oon gerada com `create-central-oon`. É composta por dois projetos
|
|
4
|
-
mínimos que consomem o Core:
|
|
3
|
+
Central Oon gerada com `create-central-oon`. É composta por dois projetos mínimos que consomem o Core:
|
|
5
4
|
|
|
6
5
|
- **backend/** — só domínio (`src/models`, `validations`, `triggers`, …).
|
|
7
6
|
Sobe com `oonCore-back dev`. Toda a infra (boot, db, auth, RBAC, metadata,
|
|
@@ -10,9 +9,26 @@ mínimos que consomem o Core:
|
|
|
10
9
|
dev`. Shell, providers, roteamento, auth e telas vêm do
|
|
11
10
|
`@oondemand/oon-core-front`, renderizados a partir do `/core/metadata` do back.
|
|
12
11
|
|
|
12
|
+
## Documentação local do OonCore
|
|
13
|
+
|
|
14
|
+
A pasta `.ooncore/` é gerada automaticamente a partir da versão instalada do pacote `@oondemand/create-central-oon`.
|
|
15
|
+
|
|
16
|
+
Ela serve como contexto local para o Codex codificar sem depender de site externo.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm run ooncore:docs # sincroniza .ooncore/
|
|
20
|
+
npm run ooncore:docs:check # valida versão/hash da documentação local
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Não edite `.ooncore/context.generated.md` manualmente. Atualize o pacote e rode o sync.
|
|
24
|
+
|
|
13
25
|
## Rodando
|
|
14
26
|
|
|
15
27
|
```bash
|
|
28
|
+
# raiz da Central
|
|
29
|
+
npm install
|
|
30
|
+
npm run ooncore:docs:check
|
|
31
|
+
|
|
16
32
|
# backend
|
|
17
33
|
cd backend && cp .env.example .env && npm install && npm run dev
|
|
18
34
|
|
|
@@ -24,4 +40,5 @@ cd frontend && cp .env.example .env && npm install && npm run dev
|
|
|
24
40
|
|
|
25
41
|
1. Crie models em `backend/src/models` (só schema + CRUD).
|
|
26
42
|
2. Declare as telas em `frontend/central.ui.json` (coleções/esteiras/documentos).
|
|
27
|
-
3.
|
|
43
|
+
3. Use validations, triggers, hooks, mappings e integrations para regras e processos.
|
|
44
|
+
4. O resto — grid, form, rotas, menu — é montado pelo Core automaticamente.
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"sync:metadata": "oonCore-front sync:metadata"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@oondemand/oon-core-front": "^0.3.
|
|
13
|
+
"@oondemand/oon-core-front": "^0.3.10",
|
|
14
14
|
"@chakra-ui/react": "^3.13.0",
|
|
15
15
|
"@emotion/react": "^11.14.0",
|
|
16
16
|
"@tanstack/react-query": "^5.65.0",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__SLUG__",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Central Oon __NAME__ gerada com create-central-oon.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"ooncore:docs": "create-central-oon docs --sync",
|
|
8
|
+
"ooncore:docs:check": "create-central-oon docs --check",
|
|
9
|
+
"dev:backend": "npm run dev --prefix backend",
|
|
10
|
+
"dev:frontend": "npm run dev --prefix frontend"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@oondemand/create-central-oon": "^0.3.8"
|
|
14
|
+
}
|
|
15
|
+
}
|