@oktis-works/cms 0.1.14 → 0.2.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/dist/assets.d.ts +94 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +671 -0
- package/dist/assets.js.map +1 -0
- package/dist/bluegreen.d.ts +121 -0
- package/dist/bluegreen.d.ts.map +1 -0
- package/dist/bluegreen.js +393 -0
- package/dist/bluegreen.js.map +1 -0
- package/dist/commands.d.ts +6 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +116 -61
- package/dist/commands.js.map +1 -1
- package/dist/config-wizard.d.ts +39 -0
- package/dist/config-wizard.d.ts.map +1 -0
- package/dist/config-wizard.js +308 -0
- package/dist/config-wizard.js.map +1 -0
- package/dist/docker.d.ts +148 -0
- package/dist/docker.d.ts.map +1 -0
- package/dist/docker.js +324 -0
- package/dist/docker.js.map +1 -0
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +51 -0
- package/dist/doctor.js.map +1 -1
- package/dist/env-file.d.ts +45 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +200 -0
- package/dist/env-file.js.map +1 -0
- package/dist/env-schema.d.ts +28 -0
- package/dist/env-schema.d.ts.map +1 -0
- package/dist/env-schema.js +497 -0
- package/dist/env-schema.js.map +1 -0
- package/dist/guards.d.ts +40 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +159 -0
- package/dist/guards.js.map +1 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +12 -3
- package/dist/parser.js.map +1 -1
- package/dist/project-config.js +2 -2
- package/dist/prompt.d.ts +81 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +379 -0
- package/dist/prompt.js.map +1 -0
- package/dist/redeploy.d.ts +109 -0
- package/dist/redeploy.d.ts.map +1 -0
- package/dist/redeploy.js +363 -0
- package/dist/redeploy.js.map +1 -0
- package/dist/scaffold-docs.d.ts +25 -6
- package/dist/scaffold-docs.d.ts.map +1 -1
- package/dist/scaffold-docs.js +711 -33
- package/dist/scaffold-docs.js.map +1 -1
- package/dist/scaffold.d.ts +17 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +77 -14
- package/dist/scaffold.js.map +1 -1
- package/dist/theme-build.d.ts +35 -0
- package/dist/theme-build.d.ts.map +1 -0
- package/dist/theme-build.js +86 -0
- package/dist/theme-build.js.map +1 -0
- package/dist/update.d.ts +51 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +210 -0
- package/dist/update.js.map +1 -0
- package/package.json +7 -7
package/dist/scaffold-docs.js
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
// @oktis-works/cms - Documentação gerada no scaffold do projeto
|
|
2
2
|
// README.md (uso local/Docker + visão do sistema), PLUGIN.md e THEME.md
|
|
3
3
|
// (guias de desenvolvimento de extensões). Só escreve se o arquivo não existir.
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
//
|
|
5
|
+
// O exemplo de manifest usa o CMS_VERSION real: é o MESMO valor que o
|
|
6
|
+
// `okcms plugin:create`/`theme:create` grava em `compatibility.okcms`, então
|
|
7
|
+
// o doc nunca fica desatualizado em relação ao scaffold.
|
|
8
|
+
//
|
|
9
|
+
// Cada documento existe em duas línguas (en/pt), mas o ARQUIVO gerado tem
|
|
10
|
+
// sempre o mesmo nome — a língua é escolhida no `okcms init` (prompt com TTY,
|
|
11
|
+
// `--lang en|pt` sem TTY) e não muda o path. No repositório, os guias derivados
|
|
12
|
+
// (docs/plugin-development*.md) existem nos dois nomes, com banner de idioma.
|
|
13
|
+
import { CMS_VERSION } from '@oktis-works/validation';
|
|
14
|
+
/** Línguas suportadas (ordem = ordem do menu do init). */
|
|
15
|
+
export const DOCS_LANGS = ['en', 'pt'];
|
|
16
|
+
/**
|
|
17
|
+
* Default: inglês — é o que o Enter do prompt escolhe e o único valor em
|
|
18
|
+
* modo não-interativo (CI/scripts), onde o prompt nunca aparece.
|
|
19
|
+
*/
|
|
20
|
+
export const DEFAULT_DOCS_LANG = 'en';
|
|
21
|
+
/**
|
|
22
|
+
* Normaliza o valor de `--lang`. Devolve `null` para valor desconhecido (ou
|
|
23
|
+
* vazio): o chamador decide entre erro (flag explícita) e default (flag ausente).
|
|
24
|
+
*/
|
|
25
|
+
export function parseDocsLang(value) {
|
|
26
|
+
if (value === undefined || value === null)
|
|
27
|
+
return null;
|
|
28
|
+
const normalized = value.trim().toLowerCase();
|
|
29
|
+
if (normalized === '')
|
|
30
|
+
return null;
|
|
31
|
+
if (['en', 'en-us', 'en-gb', 'english', 'ingles', 'inglês'].includes(normalized)) {
|
|
32
|
+
return 'en';
|
|
33
|
+
}
|
|
34
|
+
if (['pt', 'pt-br', 'ptb', 'br', 'portuguese', 'portugues', 'português'].includes(normalized)) {
|
|
35
|
+
return 'pt';
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/** Rótulo legível da língua (mensagens da CLI). */
|
|
40
|
+
export function docsLangLabel(lang) {
|
|
41
|
+
return lang === 'pt' ? 'português' : 'inglês';
|
|
42
|
+
}
|
|
43
|
+
/** README.md do projeto scaffoldado — versão em português. */
|
|
44
|
+
function projectReadmePt(projectName) {
|
|
6
45
|
return `# ${projectName}
|
|
7
46
|
|
|
8
47
|
Projeto OkCMS criado com \`okcms init\`. Este guia explica o sistema e como
|
|
@@ -34,6 +73,11 @@ CMS API-first, multi-tenant e extensível. Quatro apps + uma CLI:
|
|
|
34
73
|
| \`plugins/\`, \`themes/\` | Extensões do projeto |
|
|
35
74
|
| \`migrations/\` | SQL de migrations (\`okcms db:migrate\`) |
|
|
36
75
|
| \`docker-compose.yml\` | Infra local: PostgreSQL + Redis (com healthcheck e volume) |
|
|
76
|
+
| \`docker/Dockerfile\`, \`.dockerignore\` | Imagem única \`okcms/app\` — 4 entrypoints: api, admin, web, worker |
|
|
77
|
+
| \`docker-compose.infra.yml\` | Projeto \`okcms\`: rede, postgres (só 127.0.0.1), redis (só interna) e proxy |
|
|
78
|
+
| \`docker-compose.deploy.yml\` | As 8 services blue/green: api, web, admin, worker × blue, green |
|
|
79
|
+
| \`deploy/nginx/\` | Template do proxy + \`conf.d/00-upstreams.conf\` (reescrito no swap) |
|
|
80
|
+
| \`.deploy/\` | Estado do deploy: lane ativa, lane anterior e histórico (não versionado) |
|
|
37
81
|
|
|
38
82
|
## Começando (desenvolvimento local)
|
|
39
83
|
|
|
@@ -71,8 +115,8 @@ npx okcms start
|
|
|
71
115
|
npx okcms doctor
|
|
72
116
|
\`\`\`
|
|
73
117
|
|
|
74
|
-
Ports padrão (ajustáveis no \`.env\`): **API 3000** (\`PORT\`) · **
|
|
75
|
-
(\`
|
|
118
|
+
Ports padrão (ajustáveis no \`.env\`): **API 3000** (\`PORT\`) · **Web 3001**
|
|
119
|
+
(\`WEB_PORT\`) · **Admin 3011** (\`ADMIN_PORT\`).
|
|
76
120
|
|
|
77
121
|
## Começando (Docker)
|
|
78
122
|
|
|
@@ -86,6 +130,16 @@ O \`.env\` gerado já aponta para \`localhost\`, que é onde o compose expõe as
|
|
|
86
130
|
portas do Postgres (5432) e do Redis (6379). Os apps em si rodam via
|
|
87
131
|
\`okcms start\` — o compose é só a infraestrutura.
|
|
88
132
|
|
|
133
|
+
Para subir a aplicação **inteira em Docker** (api, admin, web e worker em
|
|
134
|
+
containers, atrás de um nginx), use o deploy blue/green:
|
|
135
|
+
|
|
136
|
+
\`\`\`bash
|
|
137
|
+
npx okcms update --mode deploy
|
|
138
|
+
\`\`\`
|
|
139
|
+
|
|
140
|
+
Esse é o caminho de produção — ver o guia completo em
|
|
141
|
+
[docs/docker-deploy.md](https://github.com/oktis-works/cms/blob/main/docs/docker-deploy.md).
|
|
142
|
+
|
|
89
143
|
## Produção
|
|
90
144
|
|
|
91
145
|
Em produção **não use \`okcms start\` como supervisor** — ele é conveniência
|
|
@@ -104,8 +158,8 @@ startup\` na inicialização do servidor e \`pm2 reload\` individual
|
|
|
104
158
|
module.exports = {
|
|
105
159
|
apps: [
|
|
106
160
|
{ name: 'okcms-api', script: 'bunx', args: '@oktis-works/api', env: { NODE_ENV: 'production', PORT: 3000 } },
|
|
107
|
-
{ name: 'okcms-admin', script: 'bunx', args: '@oktis-works/admin', env: { NODE_ENV: 'production', PORT:
|
|
108
|
-
{ name: 'okcms-web', script: 'bunx', args: '@oktis-works/web', env: { NODE_ENV: 'production',
|
|
161
|
+
{ name: 'okcms-admin', script: 'bunx', args: '@oktis-works/admin', env: { NODE_ENV: 'production', PORT: 3011 } },
|
|
162
|
+
{ name: 'okcms-web', script: 'bunx', args: '@oktis-works/web', env: { NODE_ENV: 'production', WEB_PORT: 3001 } },
|
|
109
163
|
{ name: 'okcms-worker', script: 'bunx', args: '@oktis-works/worker', env: { NODE_ENV: 'production', WORKER_MODE: 'pm2' } },
|
|
110
164
|
],
|
|
111
165
|
};
|
|
@@ -124,26 +178,41 @@ pm2 unmonitor okcms-api && pm2 delete okcms-api # remover
|
|
|
124
178
|
- Como cada app é um executável independente, o \`okcms start\` não é
|
|
125
179
|
necessário em produção — o pm2 supervisoria cada um diretamente.
|
|
126
180
|
|
|
127
|
-
### Caminho 2: Docker
|
|
181
|
+
### Caminho 2: Docker blue/green (recomendado)
|
|
128
182
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
repositório do OkCMS — o build precisa do contexto do monorepo:
|
|
183
|
+
O projeto já nasce com tudo que o deploy precisa (o \`okcms init\` escreve
|
|
184
|
+
\`docker/\`, os dois composes e o \`deploy/\` do proxy). Um deploy é um único
|
|
185
|
+
comando a partir do host:
|
|
133
186
|
|
|
134
187
|
\`\`\`bash
|
|
135
|
-
|
|
136
|
-
cd cms
|
|
137
|
-
docker build -f apps/api/Dockerfile -t okcms-api:v1 .
|
|
138
|
-
docker run -d --env-file /caminho/para/.env -p 3000:3000 okcms-api:v1
|
|
188
|
+
npx okcms update --mode deploy # sem TTY; com TTY abre o wizard
|
|
139
189
|
\`\`\`
|
|
140
190
|
|
|
141
|
-
|
|
142
|
-
|
|
191
|
+
A aplicação roda em **duas lanes** (\`okcms-blue\` e \`okcms-green\`) atrás de
|
|
192
|
+
um nginx público. Cada deploy:
|
|
193
|
+
|
|
194
|
+
1. builda a imagem nova numa lane que **não recebe tráfego**;
|
|
195
|
+
2. roda \`okcms db:migrate\` **no host** (falhou = nada mudou);
|
|
196
|
+
3. sobe o edge da lane nova e espera o healthcheck de cada contêiner;
|
|
197
|
+
4. troca o proxy reescrevendo \`00-upstreams.conf\` + \`nginx -s reload\`
|
|
198
|
+
(conexões existentes vivas);
|
|
199
|
+
5. **drena** o worker antigo (SIGTERM + \`stop_grace_period\`), sobe o novo;
|
|
200
|
+
6. derruba a lane antiga — **sem \`-v\`**: o volume de mídia é compartilhado.
|
|
201
|
+
|
|
202
|
+
**Rollback** = rodar o mesmo comando de novo, ou apontar o upstream de volta
|
|
203
|
+
para a outra lane. Detalhes, portas e segurança em
|
|
204
|
+
[docs/docker-deploy.md](https://github.com/oktis-works/cms/blob/main/docs/docker-deploy.md).
|
|
205
|
+
|
|
206
|
+
Alternativa manual (sem a CLI): \`docker build -f docker/Dockerfile\` com o
|
|
207
|
+
contexto do monorepo e \`docker run --env-file .env\` — funcional, mas entrega
|
|
208
|
+
os 6 passos acima na mão. Prefira o comando da CLI.
|
|
209
|
+
|
|
143
210
|
- Postgres/Redis de produção: serviços gerenciados ou containers próprios com
|
|
144
|
-
volume e backup — não use o \`docker-compose.yml\` de dev.
|
|
145
|
-
-
|
|
146
|
-
|
|
211
|
+
volume e backup — não use o \`docker-compose.yml\` de dev. O
|
|
212
|
+
\`docker-compose.infra.yml\` do projeto é o mínimo aceitável (postgres só
|
|
213
|
+
em \`127.0.0.1\`, redis sem porta nenhuma).
|
|
214
|
+
- **Migração como passo de deploy**: já é feito pelo \`--mode deploy\`, entre
|
|
215
|
+
o build e o primeiro tráfego.
|
|
147
216
|
|
|
148
217
|
### Checklist (ambos os caminhos)
|
|
149
218
|
|
|
@@ -165,19 +234,29 @@ docker run -d --env-file /caminho/para/.env -p 3000:3000 okcms-api:v1
|
|
|
165
234
|
|
|
166
235
|
| Comando | O que faz |
|
|
167
236
|
|---|---|
|
|
168
|
-
| \`okcms init <dir>\` | Cria o projeto (arquivos + docs) e instala as dependências |
|
|
169
|
-
| \`okcms start [--api
|
|
237
|
+
| \`okcms init <dir>\` | Cria o projeto (arquivos + docs em \`--lang en\\|pt\`) e instala as dependências |
|
|
238
|
+
| \`okcms start [--api\\|--admin\\|--web\\|--worker\\|--all]\` | Sobe os apps (default: todos) |
|
|
170
239
|
| \`okcms stop\` / \`okcms status\` | Para / mostra os processos (pidfiles) |
|
|
171
|
-
| \`okcms doctor\` | Diagnóstico: node, \`.env\`, database (\`DB_*\` ou \`DATABASE_URL\`), config |
|
|
240
|
+
| \`okcms doctor\` | Diagnóstico: node, \`.env\`, database (\`DB_*\` ou \`DATABASE_URL\`), config, docker, compose, lane e proxy |
|
|
241
|
+
| \`okcms config\` | Wizard de configuração do \`.env\` (Enter mantém, Ctrl+C descarta) · \`--list\` · \`--set K=V\` · \`--section <s>\` |
|
|
172
242
|
| \`okcms db:migrate\` · \`db:rollback\` · \`db:status\` | Migrations da pasta \`migrations/\` (\`--tenant\` opcional) |
|
|
173
243
|
| \`okcms db:backup\` · \`db:restore -f <arquivo>\` | Backup/restore do Postgres |
|
|
174
244
|
| \`okcms plugin:create -n <nome>\` | Scaffold de plugin — guia em [PLUGIN.md](./PLUGIN.md) |
|
|
175
245
|
| \`okcms plugin:install -n <caminho>\` | Instala plugin de um caminho local + registra |
|
|
176
246
|
| \`okcms plugin:list\` · \`plugin:search\` · \`plugin:manage\` | Lista, busca (npm) e habilita/desabilita plugins |
|
|
177
|
-
| \`okcms theme:create -n <nome> --style css
|
|
247
|
+
| \`okcms theme:create -n <nome> --style css\\|scss\\|tailwind\` | Scaffold de tema — guia em [THEME.md](./THEME.md) |
|
|
178
248
|
| \`okcms theme:install\` · \`theme:list\` · \`theme:search\` · \`theme:manage\` | Gestão de temas (\`--set-active\` define o ativo) |
|
|
179
249
|
| \`okcms theme:build -n <nome>\` | Compila SCSS/Tailwind → \`dist/theme.css\` isolado |
|
|
180
|
-
| \`okcms update
|
|
250
|
+
| \`okcms update\` | Wizard: **só baixar pacotes** ou **deploy Docker blue/green** (\`--mode download\\|deploy\`) |
|
|
251
|
+
| \`okcms update -i\` | Só baixa/aplica os pacotes \`@oktis-works/*\` (comportamento clássico, não-TTY) |
|
|
252
|
+
| \`okcms update --mode deploy\` | Deploy blue/green completo: build → migrations → healthcheck → swap → worker |
|
|
253
|
+
| \`okcms redeploy\` | Depois de instalar plugin/tema: SQL do plugin → \`migrations/\`, \`dist/theme.css\` do tema e deploy blue/green (\`--dry-run\` só mostra o plano) |
|
|
254
|
+
| \`okcms seed\` | Semeia dados iniciais (roles + settings) — idempotente |
|
|
255
|
+
| \`okcms user:create\` | Cria usuário e atribui um papel dentro do tenant |
|
|
256
|
+
| \`okcms system:status\` | Status do sistema (ambiente + saúde do banco) |
|
|
257
|
+
| \`okcms media:migrate\` | Migra arquivos de mídia entre drivers (\`local\` ↔ \`s3\`/\`r2\`/\`minio\`) |
|
|
258
|
+
| \`okcms prerender\` | Gera HTML estático das páginas publicadas (best-effort) |
|
|
259
|
+
| \`okcms build\` | Build dos apps em monorepo (\`--apps api,admin,web\`) |
|
|
181
260
|
|
|
182
261
|
## Banco de dados
|
|
183
262
|
|
|
@@ -191,8 +270,37 @@ docker run -d --env-file /caminho/para/.env -p 3000:3000 okcms-api:v1
|
|
|
191
270
|
## Atualizando
|
|
192
271
|
|
|
193
272
|
\`\`\`bash
|
|
194
|
-
npx okcms update
|
|
195
|
-
npx okcms update -i
|
|
273
|
+
npx okcms update # com TTY: escolhe entre baixar pacotes ou deploy
|
|
274
|
+
npx okcms update -i # só baixa/aplica os pacotes (igual sempre foi)
|
|
275
|
+
npx okcms update --mode deploy # deploy blue/green completo
|
|
276
|
+
npx okcms update --mode deploy --yes # sem prompts (CI/CD)
|
|
277
|
+
\`\`\`
|
|
278
|
+
|
|
279
|
+
Em **não-TTY** (script/CI) o default continua sendo \`download\` — um \`-i\`
|
|
280
|
+
em cron nunca passa a fazer deploy por acidente. Só \`--mode deploy\` aciona
|
|
281
|
+
o Docker.
|
|
282
|
+
|
|
283
|
+
Flags de deploy: \`--no-cache\` (rebuild limpo) · \`--remove-orphans\`
|
|
284
|
+
(default) · \`--keep-orphans\` · \`--yes\` (sem prompts).
|
|
285
|
+
|
|
286
|
+
### Aplicando um plugin ou tema novo
|
|
287
|
+
|
|
288
|
+
Instalar extensão não muda o que está no ar: \`plugins/\` e \`themes/\` entram
|
|
289
|
+
na imagem no build, e \`themes/<n>/dist/theme.css\` é compilado **no host**.
|
|
290
|
+
Depois de \`plugin:install\` / \`theme:install\`, rode:
|
|
291
|
+
|
|
292
|
+
\`\`\`bash
|
|
293
|
+
npx okcms redeploy
|
|
294
|
+
\`\`\`
|
|
295
|
+
|
|
296
|
+
Ele copia \`plugins/<n>/migrations/*.sql\` para \`migrations/\` (idempotente),
|
|
297
|
+
compila o estilo de cada tema com entrada e refaz o deploy blue/green — sem
|
|
298
|
+
\`bun add\`. Use \`--dry-run\` para ver o plano, \`--plugin <nome>\` /
|
|
299
|
+
\`--theme <nome>\` para restringir o preparo, \`--skip-migrations\` e
|
|
300
|
+
\`--skip-theme-build\` para pular etapas.
|
|
301
|
+
|
|
302
|
+
\`\`\`bash
|
|
303
|
+
npx okcms doctor # confere docker, compose v2, lane e proxy antes/depois
|
|
196
304
|
\`\`\`
|
|
197
305
|
|
|
198
306
|
## Próximos passos
|
|
@@ -201,8 +309,277 @@ npx okcms update -i # aplica a atualização
|
|
|
201
309
|
- Criar/ativar um tema → [THEME.md](./THEME.md)
|
|
202
310
|
`;
|
|
203
311
|
}
|
|
204
|
-
/**
|
|
205
|
-
|
|
312
|
+
/** README.md do projeto scaffoldado — versão em inglês. */
|
|
313
|
+
function projectReadmeEn(projectName) {
|
|
314
|
+
return `# ${projectName}
|
|
315
|
+
|
|
316
|
+
OkCMS project created with \`okcms init\`. This guide explains the system and
|
|
317
|
+
how to run it in local development and with Docker.
|
|
318
|
+
|
|
319
|
+
## What is OkCMS
|
|
320
|
+
|
|
321
|
+
An API-first, multi-tenant, extensible CMS. Four apps + one CLI:
|
|
322
|
+
|
|
323
|
+
| App | Package | Role |
|
|
324
|
+
|---|---|---|
|
|
325
|
+
| **API** | \`@oktis-works/api\` | REST server (Hono) at \`/api/v1\`: content, auth, media, plugins |
|
|
326
|
+
| **Admin** | \`@oktis-works/admin\` | Admin panel (Astro + SolidJS) |
|
|
327
|
+
| **Web** | \`@oktis-works/web\` | Public site (Astro) |
|
|
328
|
+
| **Worker** | \`@oktis-works/worker\` | Background queues/jobs (bullmq): publishing, media, webhooks, cache |
|
|
329
|
+
| **CLI** | \`@oktis-works/cms\` | \`okcms\` — init, start, database, extensions, update |
|
|
330
|
+
|
|
331
|
+
- **Database:** PostgreSQL (Row-Level Security, multi-tenant)
|
|
332
|
+
- **Cache and queues:** Redis
|
|
333
|
+
- **Extensions:** [plugins](./PLUGIN.md) (hooks/filters at runtime) and [themes](./THEME.md) (templates + isolated styles)
|
|
334
|
+
|
|
335
|
+
## Project structure
|
|
336
|
+
|
|
337
|
+
| Path | What it is |
|
|
338
|
+
|---|---|
|
|
339
|
+
| \`okcms.config.json\` | Structure: name, ports, storage, dirs, active theme. **No database credentials.** |
|
|
340
|
+
| \`.env\` | **Single source of connection**: database (\`DB_*\` or \`DATABASE_URL\`), Redis, JWT, ports |
|
|
341
|
+
| \`package.json\` | CMS apps (\`api\`, \`admin\`, \`web\`, \`worker\`) + CLI in devDependencies + shortcut scripts (start, migrate, doctor…) |
|
|
342
|
+
| \`plugins/\`, \`themes/\` | Project extensions |
|
|
343
|
+
| \`migrations/\` | SQL migrations (\`okcms db:migrate\`) |
|
|
344
|
+
| \`docker-compose.yml\` | Local infrastructure: PostgreSQL + Redis (healthcheck + volume) |
|
|
345
|
+
| \`docker/Dockerfile\`, \`.dockerignore\` | Single \`okcms/app\` image — 4 entrypoints: api, admin, web, worker |
|
|
346
|
+
| \`docker-compose.infra.yml\` | \`okcms\` project: network, postgres (127.0.0.1 only), redis (internal only) and proxy |
|
|
347
|
+
| \`docker-compose.deploy.yml\` | The 8 blue/green services: api, web, admin, worker × blue, green |
|
|
348
|
+
| \`deploy/nginx/\` | Proxy template + \`conf.d/00-upstreams.conf\` (rewritten on swap) |
|
|
349
|
+
| \`.deploy/\` | Deploy state: active lane, previous lane and history (not versioned) |
|
|
350
|
+
|
|
351
|
+
## Getting started (local development)
|
|
352
|
+
|
|
353
|
+
Prerequisites: **Node 20+** or **Bun 1.3+** · **PostgreSQL 16+** (required) ·
|
|
354
|
+
**Redis** (optional — only for the worker queues).
|
|
355
|
+
|
|
356
|
+
> **Project CLI:** the commands below run with \`npx okcms\` (with Bun,
|
|
357
|
+
> \`bunx okcms\`) — the CLI is installed in devDependencies, **not** on PATH.
|
|
358
|
+
> Shortcuts already in \`package.json\`: \`bun run start\` · \`bun run migrate\`
|
|
359
|
+
> · \`bun run doctor\`. To use bare \`okcms\` without a prefix anywhere,
|
|
360
|
+
> install the CLI globally: \`bun add -g @oktis-works/cms\`.
|
|
361
|
+
|
|
362
|
+
\`\`\`bash
|
|
363
|
+
# 1. Database in .env — pick ONE format:
|
|
364
|
+
# (a) separate variables (default)
|
|
365
|
+
DB_HOST=localhost
|
|
366
|
+
DB_PORT=5432
|
|
367
|
+
DB_NAME=okcms
|
|
368
|
+
DB_USER=postgres
|
|
369
|
+
# (b) single URL — takes precedence over the DB_* above
|
|
370
|
+
# DATABASE_URL=postgresql://postgres:password@localhost:5432/okcms
|
|
371
|
+
|
|
372
|
+
# 2. Start the infrastructure (Postgres + Redis) — with Docker:
|
|
373
|
+
docker compose up -d
|
|
374
|
+
# Without Docker: point DB_* to your own Postgres. Without Redis, use:
|
|
375
|
+
# REDIS_HOST=disabled (in-memory cache; the worker queues require Redis)
|
|
376
|
+
|
|
377
|
+
# 3. Migrations
|
|
378
|
+
npx okcms db:migrate
|
|
379
|
+
|
|
380
|
+
# 4. Start everything: api + admin + web + worker
|
|
381
|
+
npx okcms start
|
|
382
|
+
|
|
383
|
+
# 5. If something fails
|
|
384
|
+
npx okcms doctor
|
|
385
|
+
\`\`\`
|
|
386
|
+
|
|
387
|
+
Default ports (adjustable in \`.env\`): **API 3000** (\`PORT\`) · **Web 3001**
|
|
388
|
+
(\`WEB_PORT\`) · **Admin 3011** (\`ADMIN_PORT\`).
|
|
389
|
+
|
|
390
|
+
## Getting started (Docker)
|
|
391
|
+
|
|
392
|
+
\`\`\`bash
|
|
393
|
+
docker compose up -d # infrastructure only: postgres:16 + redis:7 (healthcheck + volumes)
|
|
394
|
+
npx okcms db:migrate
|
|
395
|
+
npx okcms start # apps run as normal processes, outside the compose
|
|
396
|
+
\`\`\`
|
|
397
|
+
|
|
398
|
+
The generated \`.env\` already points to \`localhost\`, where the compose publishes
|
|
399
|
+
the Postgres (5432) and Redis (6379) ports. The apps themselves run via
|
|
400
|
+
\`okcms start\` — the compose is only the infrastructure.
|
|
401
|
+
|
|
402
|
+
To run the **whole application in Docker** (api, admin, web and worker in
|
|
403
|
+
containers behind an nginx), use the blue/green deploy:
|
|
404
|
+
|
|
405
|
+
\`\`\`bash
|
|
406
|
+
npx okcms update --mode deploy
|
|
407
|
+
\`\`\`
|
|
408
|
+
|
|
409
|
+
That is the production path — see the complete guide at
|
|
410
|
+
[docs/docker-deploy.md](https://github.com/oktis-works/cms/blob/main/docs/docker-deploy.md).
|
|
411
|
+
|
|
412
|
+
## Production
|
|
413
|
+
|
|
414
|
+
In production **do not use \`okcms start\` as a supervisor** — it is a dev
|
|
415
|
+
convenience: it does not restart children that die and mixes every app's logs
|
|
416
|
+
into a single stream. Pick one of the paths below.
|
|
417
|
+
|
|
418
|
+
### Path 1: pm2 (host processes)
|
|
419
|
+
|
|
420
|
+
One pm2 **process per app** — restart on crash, log per process, \`pm2
|
|
421
|
+
startup\` on server boot and individual \`pm2 reload\`
|
|
422
|
+
(zero-downtime). Requires **Bun installed on the server** (apps start via
|
|
423
|
+
\`bunx\`).
|
|
424
|
+
|
|
425
|
+
\`\`\`js
|
|
426
|
+
// ecosystem.config.js
|
|
427
|
+
module.exports = {
|
|
428
|
+
apps: [
|
|
429
|
+
{ name: 'okcms-api', script: 'bunx', args: '@oktis-works/api', env: { NODE_ENV: 'production', PORT: 3000 } },
|
|
430
|
+
{ name: 'okcms-admin', script: 'bunx', args: '@oktis-works/admin', env: { NODE_ENV: 'production', PORT: 3011 } },
|
|
431
|
+
{ name: 'okcms-web', script: 'bunx', args: '@oktis-works/web', env: { NODE_ENV: 'production', WEB_PORT: 3001 } },
|
|
432
|
+
{ name: 'okcms-worker', script: 'bunx', args: '@oktis-works/worker', env: { NODE_ENV: 'production', WORKER_MODE: 'pm2' } },
|
|
433
|
+
],
|
|
434
|
+
};
|
|
435
|
+
\`\`\`
|
|
436
|
+
|
|
437
|
+
\`\`\`bash
|
|
438
|
+
pm2 start ecosystem.config.js
|
|
439
|
+
pm2 save && pm2 startup # start on boot
|
|
440
|
+
pm2 reload okcms-api # update with no downtime (per app)
|
|
441
|
+
pm2 logs okcms-api # log per process
|
|
442
|
+
pm2 unmonitor okcms-api && pm2 delete okcms-api # remove
|
|
443
|
+
\`\`\`
|
|
444
|
+
|
|
445
|
+
- The worker has a **native pm2 mode**: \`WORKER_MODE=pm2\` (cluster) combined with
|
|
446
|
+
\`WORKER_COUNT\` and \`WORKER_CONCURRENCY\`.
|
|
447
|
+
- Since each app is an independent executable, \`okcms start\` is not
|
|
448
|
+
needed in production — pm2 supervises each one directly.
|
|
449
|
+
|
|
450
|
+
### Path 2: Docker blue/green (recommended)
|
|
451
|
+
|
|
452
|
+
The project ships with everything a deploy needs ( \`okcms init\` writes
|
|
453
|
+
\`docker/\`, both compose files and the proxy's \`deploy/\`). A deploy is a single
|
|
454
|
+
command from the host:
|
|
455
|
+
|
|
456
|
+
\`\`\`bash
|
|
457
|
+
npx okcms update --mode deploy # no TTY; with a TTY it opens the wizard
|
|
458
|
+
\`\`\`
|
|
459
|
+
|
|
460
|
+
The application runs in **two lanes** (\`okcms-blue\` and \`okcms-green\`) behind a
|
|
461
|
+
public nginx. Each deploy:
|
|
462
|
+
|
|
463
|
+
1. builds the new image in a lane that **receives no traffic**;
|
|
464
|
+
2. runs \`okcms db:migrate\` **on the host** (if it fails, nothing changed);
|
|
465
|
+
3. starts the new lane's edge and waits for every container's healthcheck;
|
|
466
|
+
4. swaps the proxy by rewriting \`00-upstreams.conf\` + \`nginx -s reload\`
|
|
467
|
+
(existing connections stay alive);
|
|
468
|
+
5. **drains** the old worker (SIGTERM + \`stop_grace_period\`) and starts the new one;
|
|
469
|
+
6. tears down the old lane — **without \`-v\`**: the media volume is shared.
|
|
470
|
+
|
|
471
|
+
**Rollback** = run the same command again, or point the upstream back to the
|
|
472
|
+
other lane. Details, ports and security in
|
|
473
|
+
[docs/docker-deploy.md](https://github.com/oktis-works/cms/blob/main/docs/docker-deploy.md).
|
|
474
|
+
|
|
475
|
+
Manual alternative (without the CLI): \`docker build -f docker/Dockerfile\` with the
|
|
476
|
+
monorepo context and \`docker run --env-file .env\` — functional, but it hands you
|
|
477
|
+
the 6 steps above to do by hand. Prefer the CLI command.
|
|
478
|
+
|
|
479
|
+
- Production Postgres/Redis: managed services or your own containers with a
|
|
480
|
+
volume and backups — do not use the dev \`docker-compose.yml\`. The project's
|
|
481
|
+
\`docker-compose.infra.yml\` is the acceptable minimum (postgres only on
|
|
482
|
+
\`127.0.0.1\`, redis with no published port).
|
|
483
|
+
- **Migration as a deploy step**: already handled by \`--mode deploy\`, between
|
|
484
|
+
the build and the first traffic.
|
|
485
|
+
|
|
486
|
+
### Checklist (both paths)
|
|
487
|
+
|
|
488
|
+
- [ ] \`NODE_ENV=production\` and a strong, unique \`JWT_SECRET\`
|
|
489
|
+
- [ ] \`.env\` out of version control; credentials never in \`okcms.config.json\`
|
|
490
|
+
- [ ] TLS reverse proxy (nginx/caddy) in front of api/admin/web
|
|
491
|
+
- [ ] Pinned versions in the project \`package.json\` (no \`@latest\` in a deploy)
|
|
492
|
+
- [ ] \`okcms db:migrate\` in the deploy pipeline and scheduled \`okcms db:backup\`
|
|
493
|
+
- [ ] Real Redis in production (the worker queues do not work without Redis)
|
|
494
|
+
- [ ] \`okcms doctor\` green on the target environment
|
|
495
|
+
- [ ] Logs with a destination (pm2 logrotate, or container stdout collected)
|
|
496
|
+
|
|
497
|
+
## CLI commands
|
|
498
|
+
|
|
499
|
+
> The names below are the command itself: in the project, prefix them with
|
|
500
|
+
> \`npx\` (e.g. \`npx okcms doctor\`) or use a \`package.json\` script (\`bun run
|
|
501
|
+
> doctor\`); without a prefix, \`okcms\` only works with the CLI installed
|
|
502
|
+
> globally (\`bun add -g @oktis-works/cms\`).
|
|
503
|
+
|
|
504
|
+
| Command | What it does |
|
|
505
|
+
|---|---|
|
|
506
|
+
| \`okcms init <dir>\` | Creates the project (files + docs in \`--lang en\\|pt\`) and installs dependencies |
|
|
507
|
+
| \`okcms start [--api\\|--admin\\|--web\\|--worker\\|--all]\` | Starts the apps (default: all) |
|
|
508
|
+
| \`okcms stop\` / \`okcms status\` | Stops / shows the processes (pidfiles) |
|
|
509
|
+
| \`okcms doctor\` | Diagnostics: node, \`.env\`, database (\`DB_*\` or \`DATABASE_URL\`), config, docker, compose, lane and proxy |
|
|
510
|
+
| \`okcms config\` | \`.env\` configuration wizard (Enter keeps, Ctrl+C discards) · \`--list\` · \`--set K=V\` · \`--section <s>\` |
|
|
511
|
+
| \`okcms db:migrate\` · \`db:rollback\` · \`db:status\` | Migrations from the \`migrations/\` folder (\`--tenant\` optional) |
|
|
512
|
+
| \`okcms db:backup\` · \`db:restore -f <file>\` | Postgres backup/restore |
|
|
513
|
+
| \`okcms plugin:create -n <name>\` | Plugin scaffold — guide in [PLUGIN.md](./PLUGIN.md) |
|
|
514
|
+
| \`okcms plugin:install -n <path>\` | Installs a plugin from a local path + registers it |
|
|
515
|
+
| \`okcms plugin:list\` · \`plugin:search\` · \`plugin:manage\` | Lists, searches (npm) and enables/disables plugins |
|
|
516
|
+
| \`okcms theme:create -n <name> --style css\\|scss\\|tailwind\` | Theme scaffold — guide in [THEME.md](./THEME.md) |
|
|
517
|
+
| \`okcms theme:install\` · \`theme:list\` · \`theme:search\` · \`theme:manage\` | Theme management (\`--set-active\` sets the active one) |
|
|
518
|
+
| \`okcms theme:build -n <name>\` | Compiles SCSS/Tailwind → isolated \`dist/theme.css\` |
|
|
519
|
+
| \`okcms update\` | Wizard: **download packages only** or **Docker blue/green deploy** (\`--mode download\\|deploy\`) |
|
|
520
|
+
| \`okcms update -i\` | Only downloads/applies the \`@oktis-works/*\` packages (classic non-TTY behaviour) |
|
|
521
|
+
| \`okcms update --mode deploy\` | Full blue/green deploy: build → migrations → healthcheck → swap → worker |
|
|
522
|
+
| \`okcms redeploy\` | After installing a plugin/theme: plugin SQL → \`migrations/\`, theme \`dist/theme.css\` and blue/green deploy (\`--dry-run\` only shows the plan) |
|
|
523
|
+
| \`okcms seed\` | Seeds initial data (roles + settings) — idempotent |
|
|
524
|
+
| \`okcms user:create\` | Creates a user and assigns a role inside the tenant |
|
|
525
|
+
| \`okcms system:status\` | System status (environment + database health) |
|
|
526
|
+
| \`okcms media:migrate\` | Migrates media files between drivers (\`local\` ↔ \`s3\`/\`r2\`/\`minio\`) |
|
|
527
|
+
| \`okcms prerender\` | Generates static HTML for published pages (best-effort) |
|
|
528
|
+
| \`okcms build\` | Builds the monorepo apps (\`--apps api,admin,web\`) |
|
|
529
|
+
|
|
530
|
+
## Database
|
|
531
|
+
|
|
532
|
+
- **Connection** (in \`.env\`, pick one format): \`DB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASSWORD\`
|
|
533
|
+
**or** \`DATABASE_URL\` (takes precedence). \`okcms doctor\` validates both.
|
|
534
|
+
- **Migrations**: SQL files in \`migrations/\`; \`okcms db:migrate\` applies,
|
|
535
|
+
\`db:rollback\` reverts, \`db:status\` shows the state. \`--tenant\` is selective
|
|
536
|
+
(default \`default\`) — the database is multi-tenant via Row-Level Security.
|
|
537
|
+
- **Backup**: \`okcms db:backup\` writes a timestamped dump; \`db:restore -f <file>\` restores it.
|
|
538
|
+
|
|
539
|
+
## Updating
|
|
540
|
+
|
|
541
|
+
\`\`\`bash
|
|
542
|
+
npx okcms update # with TTY: choose between downloading packages or deploying
|
|
543
|
+
npx okcms update -i # only downloads/applies the packages (as always)
|
|
544
|
+
npx okcms update --mode deploy # full blue/green deploy
|
|
545
|
+
npx okcms update --mode deploy --yes # no prompts (CI/CD)
|
|
546
|
+
\`\`\`
|
|
547
|
+
|
|
548
|
+
In **non-TTY** (script/CI) the default is still \`download\` — an \`-i\` in a
|
|
549
|
+
cron job never starts deploying by accident. Only \`--mode deploy\` engages
|
|
550
|
+
the Docker.
|
|
551
|
+
|
|
552
|
+
Deploy flags: \`--no-cache\` (clean rebuild) · \`--remove-orphans\`
|
|
553
|
+
(default) · \`--keep-orphans\` · \`--yes\` (no prompts).
|
|
554
|
+
|
|
555
|
+
### Applying a new plugin or theme
|
|
556
|
+
|
|
557
|
+
Installing an extension does not change what is running: \`plugins/\` and \`themes/\`
|
|
558
|
+
go into the image at build time, and \`themes/<n>/dist/theme.css\` is compiled
|
|
559
|
+
**on the host**. After \`plugin:install\` / \`theme:install\`, run:
|
|
560
|
+
|
|
561
|
+
\`\`\`bash
|
|
562
|
+
npx okcms redeploy
|
|
563
|
+
\`\`\`
|
|
564
|
+
|
|
565
|
+
It copies \`plugins/<n>/migrations/*.sql\` into \`migrations/\` (idempotent),
|
|
566
|
+
compiles the style of every theme with an entry and redoes the blue/green
|
|
567
|
+
deploy — without \`bun add\`. Use \`--dry-run\` to see the plan,
|
|
568
|
+
\`--plugin <name>\` / \`--theme <name>\` to narrow the preparation, and
|
|
569
|
+
\`--skip-migrations\` / \`--skip-theme-build\` to skip steps.
|
|
570
|
+
|
|
571
|
+
\`\`\`bash
|
|
572
|
+
npx okcms doctor # checks docker, compose v2, lane and proxy before/after
|
|
573
|
+
\`\`\`
|
|
574
|
+
|
|
575
|
+
## Next steps
|
|
576
|
+
|
|
577
|
+
- Extend the CMS with plugins → [PLUGIN.md](./PLUGIN.md)
|
|
578
|
+
- Create/activate a theme → [THEME.md](./THEME.md)
|
|
579
|
+
`;
|
|
580
|
+
}
|
|
581
|
+
/** PLUGIN.md — guia de desenvolvimento de plugins (português). */
|
|
582
|
+
const PLUGIN_DOC_PT = `# Desenvolvendo um Plugin
|
|
206
583
|
|
|
207
584
|
Plugin é a extensão que se registra no runtime do CMS e participa do sistema
|
|
208
585
|
de **hooks e filters** (transformar dados, reagir a eventos de conteúdo etc.).
|
|
@@ -237,7 +614,7 @@ plugins/meu-plugin/
|
|
|
237
614
|
"main": "index.js",
|
|
238
615
|
"scope": "tenant",
|
|
239
616
|
"permissions": [],
|
|
240
|
-
"compatibility": { "okcms": "
|
|
617
|
+
"compatibility": { "okcms": "^${CMS_VERSION}" }
|
|
241
618
|
}
|
|
242
619
|
\`\`\`
|
|
243
620
|
|
|
@@ -263,6 +640,36 @@ O \`register(registry)\` é chamado quando o plugin é carregado. Use o registro
|
|
|
263
640
|
para expor filters (transformações) — veja o que existe em
|
|
264
641
|
\`GET /api/v1/hooks/catalog\` para os nomes e contratos disponíveis.
|
|
265
642
|
|
|
643
|
+
## Migrations do banco
|
|
644
|
+
|
|
645
|
+
Se o plugin cria ou altera tabelas, o SQL mora **dentro do plugin**:
|
|
646
|
+
|
|
647
|
+
\`\`\`bash
|
|
648
|
+
plugins/meu-plugin/
|
|
649
|
+
└── migrations/
|
|
650
|
+
├── V001__meu_plugin__tabelas.sql
|
|
651
|
+
└── V002__meu_plugin__colunas.sql
|
|
652
|
+
\`\`\`
|
|
653
|
+
|
|
654
|
+
O nome segue o padrão do runner — \`V<numero>__<owner>__<nome>.sql\` — e o
|
|
655
|
+
\`owner\` (aqui \`meu_plugin\`) é o que marca a migration como do plugin: o
|
|
656
|
+
rastreamento é por \`owner:version\`, então cada plugin tem a sua própria
|
|
657
|
+
linha de versão.
|
|
658
|
+
|
|
659
|
+
O SQL **não** é aplicado direto do diretório do plugin. O \`okcms redeploy\`
|
|
660
|
+
copia \`plugins/<n>/migrations/*.sql\` para \`migrations/\` (o único diretório
|
|
661
|
+
que o runner lê) e o \`db:migrate\` do deploy aplica — assim o schema do plugin
|
|
662
|
+
fica versionado e revisável no repositório do projeto.
|
|
663
|
+
|
|
664
|
+
Duas regras que o redeploy impõe:
|
|
665
|
+
|
|
666
|
+
- arquivo fora do padrão \`V###__owner__nome.sql\` **nunca** é copiado (e um
|
|
667
|
+
já existente em \`migrations/\` quebraria todo \`db:migrate\` — o comando
|
|
668
|
+
falha antes de tocar no Docker e diz qual arquivo renomear);
|
|
669
|
+
- uma migration já aplicada é imutável: se o plugin novo trouxer outro
|
|
670
|
+
conteúdo com o mesmo nome, o redeploy **não** sobrescreve o arquivo que já
|
|
671
|
+
está em \`migrations/\`, só avisa. Publique uma \`V00n+1\`.
|
|
672
|
+
|
|
266
673
|
## Fluxo de desenvolvimento
|
|
267
674
|
|
|
268
675
|
\`\`\`bash
|
|
@@ -283,6 +690,10 @@ npx okcms plugin:manage -n meu-plugin --uninstall # remove arquivos + registr
|
|
|
283
690
|
|
|
284
691
|
# 5. Busca no npm (pacotes com a keyword okcms-plugin)
|
|
285
692
|
npx okcms plugin:search -q galeria
|
|
693
|
+
|
|
694
|
+
# 6. Publicou/atualizou? Stage do SQL + build dos temas + deploy blue/green
|
|
695
|
+
npx okcms redeploy --dry-run # só mostra o plano
|
|
696
|
+
npx okcms redeploy
|
|
286
697
|
\`\`\`
|
|
287
698
|
|
|
288
699
|
## Publicando
|
|
@@ -291,8 +702,8 @@ Empacote o diretório do plugin como pacote npm com a keyword
|
|
|
291
702
|
\`okcms-plugin\` (é o que o \`okcms plugin:search\` consulta) e mantenha
|
|
292
703
|
\`compatibility.okcms\` atualizado para a linha do CMS que você suporta.
|
|
293
704
|
`;
|
|
294
|
-
/** THEME.md — guia de desenvolvimento de temas. */
|
|
295
|
-
|
|
705
|
+
/** THEME.md — guia de desenvolvimento de temas (português). */
|
|
706
|
+
const THEME_DOC_PT = `# Desenvolvendo um Tema
|
|
296
707
|
|
|
297
708
|
Tema é o visual do site público: **templates** (hierarquia de páginas) +
|
|
298
709
|
**estilos**, com isolamento por \`[data-theme]\` para que um tema nunca vaze
|
|
@@ -326,7 +737,7 @@ themes/meu-tema/
|
|
|
326
737
|
"version": "0.1.0",
|
|
327
738
|
"description": "Tema meu-tema para OkCMS",
|
|
328
739
|
"type": "theme",
|
|
329
|
-
"compatibility": { "okcms": "
|
|
740
|
+
"compatibility": { "okcms": "^${CMS_VERSION}" }
|
|
330
741
|
}
|
|
331
742
|
\`\`\`
|
|
332
743
|
|
|
@@ -365,6 +776,11 @@ O build compila para \`dist/theme.css\` **com isolamento
|
|
|
365
776
|
\`[data-theme="meu-tema"]\`** (sem vazar estilos entre temas; o Tailwind já
|
|
366
777
|
sai com \`preflight: false\`).
|
|
367
778
|
|
|
779
|
+
> \`dist/theme.css\` é lido **pronto** pelo container — nada compila SCSS ou
|
|
780
|
+
> Tailwind dentro da imagem. O arquivo existe no host e só chega em
|
|
781
|
+
> produção quando a imagem é reconstruída: \`okcms theme:build\` seguido de
|
|
782
|
+
> \`okcms redeploy\`.
|
|
783
|
+
|
|
368
784
|
## Fluxo de desenvolvimento
|
|
369
785
|
|
|
370
786
|
\`\`\`bash
|
|
@@ -389,6 +805,10 @@ npx okcms theme:search -q blog # busca no npm (keyword okcms
|
|
|
389
805
|
|
|
390
806
|
# Se criou FORA do projeto:
|
|
391
807
|
npx okcms theme:install --name ../meu-tema-fonte
|
|
808
|
+
|
|
809
|
+
# 6. Depois de mudar templates/estilos: recompila e refaz o deploy
|
|
810
|
+
npx okcms theme:build --name meu-tema # (o redeploy já compila sozinho)
|
|
811
|
+
npx okcms redeploy
|
|
392
812
|
\`\`\`
|
|
393
813
|
|
|
394
814
|
## Publicando
|
|
@@ -398,4 +818,262 @@ Publique como pacote npm com a keyword \`okcms-theme\` (alvo do
|
|
|
398
818
|
do CMS. O \`theme:build\` deve ser executado no seu processo de release para
|
|
399
819
|
que \`dist/theme.css\` vá junto no pacote.
|
|
400
820
|
`;
|
|
821
|
+
/** PLUGIN.md — plugin development guide (English). */
|
|
822
|
+
const PLUGIN_DOC_EN = `# Developing a Plugin
|
|
823
|
+
|
|
824
|
+
A plugin is the extension that registers with the CMS runtime and takes part
|
|
825
|
+
in the **hooks and filters** system (transform data, react to content events,
|
|
826
|
+
etc.). The catalogue of available hooks is served by the API at
|
|
827
|
+
\`GET /api/v1/hooks/catalog\`.
|
|
828
|
+
|
|
829
|
+
> The commands use \`npx\` with the project's local CLI (no global
|
|
830
|
+
> install). With the global CLI (\`bun add -g @oktis-works/cms\`), run
|
|
831
|
+
> \`okcms ...\` directly.
|
|
832
|
+
|
|
833
|
+
## Generated structure
|
|
834
|
+
|
|
835
|
+
\`\`\`bash
|
|
836
|
+
npx okcms plugin:create --name my-plugin
|
|
837
|
+
\`\`\`
|
|
838
|
+
|
|
839
|
+
\`\`\`
|
|
840
|
+
plugins/my-plugin/
|
|
841
|
+
├── manifest.json # identity + permissions + compatibility
|
|
842
|
+
├── index.js # entrypoint: module.exports.register(registry)
|
|
843
|
+
└── README.md
|
|
844
|
+
\`\`\`
|
|
845
|
+
|
|
846
|
+
### manifest.json
|
|
847
|
+
|
|
848
|
+
\`\`\`json
|
|
849
|
+
{
|
|
850
|
+
"name": "my-plugin",
|
|
851
|
+
"version": "0.1.0",
|
|
852
|
+
"description": "my-plugin plugin for OkCMS",
|
|
853
|
+
"type": "plugin",
|
|
854
|
+
"main": "index.js",
|
|
855
|
+
"scope": "tenant",
|
|
856
|
+
"permissions": [],
|
|
857
|
+
"compatibility": { "okcms": "^${CMS_VERSION}" }
|
|
858
|
+
}
|
|
859
|
+
\`\`\`
|
|
860
|
+
|
|
861
|
+
| Field | Meaning |
|
|
862
|
+
|---|---|
|
|
863
|
+
| \`type\` | \`"plugin"\` (fixed — themes use \`"theme"\`) |
|
|
864
|
+
| \`main\` | Entry file with the registration |
|
|
865
|
+
| \`scope\` | Scope of action in the multi-tenant setup (e.g. \`tenant\`) |
|
|
866
|
+
| \`permissions\` | Permissions the plugin requests (empty = none) |
|
|
867
|
+
| \`compatibility.okcms\` | Required semver range of the CMS. **The scaffold fills it in with the current version automatically** and the value is validated at scaffold time and on every install — an incompatible manifest is rejected. |
|
|
868
|
+
|
|
869
|
+
### index.js
|
|
870
|
+
|
|
871
|
+
\`\`\`js
|
|
872
|
+
'use strict';
|
|
873
|
+
|
|
874
|
+
module.exports.register = function register(registry) {
|
|
875
|
+
registry.addFilter('theme:data:posts', (value) => value);
|
|
876
|
+
};
|
|
877
|
+
\`\`\`
|
|
878
|
+
|
|
879
|
+
\`register(registry)\` is called when the plugin is loaded. Use the registry
|
|
880
|
+
to expose filters (transformations) — see what exists at
|
|
881
|
+
\`GET /api/v1/hooks/catalog\` for the available names and contracts.
|
|
882
|
+
|
|
883
|
+
## Database migrations
|
|
884
|
+
|
|
885
|
+
If the plugin creates or changes tables, the SQL lives **inside the plugin**:
|
|
886
|
+
|
|
887
|
+
\`\`\`bash
|
|
888
|
+
plugins/my-plugin/
|
|
889
|
+
└── migrations/
|
|
890
|
+
├── V001__my_plugin__tables.sql
|
|
891
|
+
└── V002__my_plugin__columns.sql
|
|
892
|
+
\`\`\`
|
|
893
|
+
|
|
894
|
+
The name follows the runner's pattern — \`V<number>__<owner>__<name>.sql\` — and
|
|
895
|
+
the \`owner\` (here \`my_plugin\`) is what marks the migration as the plugin's:
|
|
896
|
+
tracking is per \`owner:version\`, so each plugin has its own
|
|
897
|
+
version row.
|
|
898
|
+
|
|
899
|
+
The SQL is **not** applied straight from the plugin directory. \`okcms redeploy\`
|
|
900
|
+
copies \`plugins/<n>/migrations/*.sql\` into \`migrations/\` (the only directory
|
|
901
|
+
the runner reads) and the deploy's \`db:migrate\` applies it — so the plugin's
|
|
902
|
+
schema stays versioned and reviewable in the project repository.
|
|
903
|
+
|
|
904
|
+
Two rules the redeploy enforces:
|
|
905
|
+
|
|
906
|
+
- a file outside the \`V###__owner__name.sql\` pattern is **never** copied (and one
|
|
907
|
+
already in \`migrations/\` would break every \`db:migrate\` — the command
|
|
908
|
+
fails before touching Docker and tells you which file to rename);
|
|
909
|
+
- an applied migration is immutable: if a new plugin ships different content
|
|
910
|
+
under the same name, the redeploy does **not** overwrite the file already
|
|
911
|
+
in \`migrations/\`, it only warns. Ship a \`V00n+1\`.
|
|
912
|
+
|
|
913
|
+
## Development workflow
|
|
914
|
+
|
|
915
|
+
\`\`\`bash
|
|
916
|
+
# 1. Create it (in the project's ./plugins, or an external workspace with --dir)
|
|
917
|
+
npx okcms plugin:create --name my-plugin
|
|
918
|
+
|
|
919
|
+
# 2. Implement plugins/my-plugin/index.js
|
|
920
|
+
|
|
921
|
+
# 3. If you created it OUTSIDE the project, install it (validates compatibility and copies into plugins/)
|
|
922
|
+
npx okcms plugin:install --name ../my-plugin-source
|
|
923
|
+
|
|
924
|
+
# 4. Management
|
|
925
|
+
npx okcms plugin:list # installed + status
|
|
926
|
+
npx okcms plugin:manage -n my-plugin --info # manifest information
|
|
927
|
+
npx okcms plugin:manage -n my-plugin --disable # disables (keeps the files)
|
|
928
|
+
npx okcms plugin:manage -n my-plugin --enable # enables it again
|
|
929
|
+
npx okcms plugin:manage -n my-plugin --uninstall # removes files + registration
|
|
930
|
+
|
|
931
|
+
# 5. Search npm (packages with the okcms-plugin keyword)
|
|
932
|
+
npx okcms plugin:search -q gallery
|
|
933
|
+
|
|
934
|
+
# 6. Published/updated? Stage the SQL + build the themes + blue/green deploy
|
|
935
|
+
npx okcms redeploy --dry-run # only shows the plan
|
|
936
|
+
npx okcms redeploy
|
|
937
|
+
\`\`\`
|
|
938
|
+
|
|
939
|
+
## Publishing
|
|
940
|
+
|
|
941
|
+
Package the plugin directory as an npm package with the keyword
|
|
942
|
+
\`okcms-plugin\` (that is what \`okcms plugin:search\` queries) and keep
|
|
943
|
+
\`compatibility.okcms\` up to date for the CMS line you support.
|
|
944
|
+
`;
|
|
945
|
+
/** THEME.md — theme development guide (English). */
|
|
946
|
+
const THEME_DOC_EN = `# Developing a Theme
|
|
947
|
+
|
|
948
|
+
A theme is the look of the public site: **templates** (a page hierarchy) +
|
|
949
|
+
**styles**, isolated by \`[data-theme]\` so a theme never leaks CSS into
|
|
950
|
+
another one.
|
|
951
|
+
|
|
952
|
+
> The commands use \`npx\` with the project's local CLI (no global
|
|
953
|
+
> install). With the global CLI (\`bun add -g @oktis-works/cms\`), run
|
|
954
|
+
> \`okcms ...\` directly.
|
|
955
|
+
|
|
956
|
+
## Generated structure
|
|
957
|
+
|
|
958
|
+
\`\`\`bash
|
|
959
|
+
npx okcms theme:create --name my-theme --style css # css | scss | tailwind
|
|
960
|
+
\`\`\`
|
|
961
|
+
|
|
962
|
+
\`\`\`
|
|
963
|
+
themes/my-theme/
|
|
964
|
+
├── theme.json # manifest (type: theme + compatibility)
|
|
965
|
+
├── templates/
|
|
966
|
+
│ ├── index.html # listing (home)
|
|
967
|
+
│ └── single.html # single page (post/content)
|
|
968
|
+
├── style.css # css engine — or styles/main.scss — or src/input.css
|
|
969
|
+
└── README.md
|
|
970
|
+
\`\`\`
|
|
971
|
+
|
|
972
|
+
### theme.json
|
|
973
|
+
|
|
974
|
+
\`\`\`json
|
|
975
|
+
{
|
|
976
|
+
"name": "my-theme",
|
|
977
|
+
"version": "0.1.0",
|
|
978
|
+
"description": "my-theme theme for OkCMS",
|
|
979
|
+
"type": "theme",
|
|
980
|
+
"compatibility": { "okcms": "^${CMS_VERSION}" }
|
|
981
|
+
}
|
|
982
|
+
\`\`\`
|
|
983
|
+
|
|
984
|
+
With \`--style scss\` or \`--style tailwind\`, the manifest also gets
|
|
985
|
+
\`stylesConfig\` (\`engine\`, \`entry\`, \`output\`, \`isolation\`) pointing at the
|
|
986
|
+
style entry. \`compatibility.okcms\` is filled in and validated
|
|
987
|
+
automatically, just like with plugins.
|
|
988
|
+
|
|
989
|
+
### Templates
|
|
990
|
+
|
|
991
|
+
Template syntax with variables and loops:
|
|
992
|
+
|
|
993
|
+
\`\`\`html
|
|
994
|
+
<main class="site">
|
|
995
|
+
{{#each posts}}
|
|
996
|
+
<article>
|
|
997
|
+
<h2>{{this.title}}</h2>
|
|
998
|
+
<p>{{this.excerpt}}</p>
|
|
999
|
+
</article>
|
|
1000
|
+
{{/each}}
|
|
1001
|
+
</main>
|
|
1002
|
+
\`\`\`
|
|
1003
|
+
|
|
1004
|
+
- \`templates/index.html\` — listing (e.g. \`{{#each posts}}\`)
|
|
1005
|
+
- \`templates/single.html\` — single item (e.g. \`{{title}}\`, \`{{content}}\`)
|
|
1006
|
+
|
|
1007
|
+
## Styles per engine
|
|
1008
|
+
|
|
1009
|
+
| \`--style\` | Generated file | Build |
|
|
1010
|
+
|---|---|---|
|
|
1011
|
+
| \`css\` (default) | \`style.css\` | none — served as is |
|
|
1012
|
+
| \`scss\` | \`styles/main.scss\` (+ \`components.scss\`) | \`okcms theme:build -n my-theme\` |
|
|
1013
|
+
| \`tailwind\` | \`src/input.css\` + \`tailwind.config.js\` | \`okcms theme:build -n my-theme\` |
|
|
1014
|
+
|
|
1015
|
+
The build compiles into \`dist/theme.css\` **with \`[data-theme="my-theme"]\`
|
|
1016
|
+
isolation** (styles never leak between themes; Tailwind already ships with
|
|
1017
|
+
\`preflight: false\`).
|
|
1018
|
+
|
|
1019
|
+
> \`dist/theme.css\` is read **ready-made** by the container — nothing compiles
|
|
1020
|
+
> SCSS or Tailwind inside the image. The file exists on the host and only
|
|
1021
|
+
> reaches production when the image is rebuilt: \`okcms theme:build\` followed by
|
|
1022
|
+
> \`okcms redeploy\`.
|
|
1023
|
+
|
|
1024
|
+
## Development workflow
|
|
1025
|
+
|
|
1026
|
+
\`\`\`bash
|
|
1027
|
+
# 1. Create it
|
|
1028
|
+
npx okcms theme:create --name my-theme --style scss
|
|
1029
|
+
|
|
1030
|
+
# 2. Edit templates/ and styles
|
|
1031
|
+
|
|
1032
|
+
# 3. Compile the styles (scss/tailwind)
|
|
1033
|
+
npx okcms theme:build --name my-theme
|
|
1034
|
+
|
|
1035
|
+
# 4. Activate it (writes activeTheme into okcms.config.json)
|
|
1036
|
+
npx okcms theme:manage --name my-theme --set-active
|
|
1037
|
+
# (equivalent: ACTIVE_THEME=my-theme in .env)
|
|
1038
|
+
|
|
1039
|
+
# 5. Management
|
|
1040
|
+
npx okcms theme:list # installed + status
|
|
1041
|
+
npx okcms theme:manage -n my-theme --info # theme.json information
|
|
1042
|
+
npx okcms theme:manage -n my-theme --disable|enable
|
|
1043
|
+
npx okcms theme:manage -n my-theme --uninstall
|
|
1044
|
+
npx okcms theme:search -q blog # npm search (keyword okcms-theme)
|
|
1045
|
+
|
|
1046
|
+
# If you created it OUTSIDE the project:
|
|
1047
|
+
npx okcms theme:install --name ../my-theme-source
|
|
1048
|
+
|
|
1049
|
+
# 6. After changing templates/styles: recompile and redo the deploy
|
|
1050
|
+
npx okcms theme:build --name my-theme # (the redeploy compiles it anyway)
|
|
1051
|
+
npx okcms redeploy
|
|
1052
|
+
\`\`\`
|
|
1053
|
+
|
|
1054
|
+
## Publishing
|
|
1055
|
+
|
|
1056
|
+
Publish as an npm package with the keyword \`okcms-theme\` (the target of
|
|
1057
|
+
\`okcms theme:search\`) and keep \`compatibility.okcms\` on the supported CMS
|
|
1058
|
+
line. Run \`theme:build\` in your release process so \`dist/theme.css\` ships
|
|
1059
|
+
inside the package.
|
|
1060
|
+
`;
|
|
1061
|
+
// ---------------------------------------------------------------------------
|
|
1062
|
+
// Superfície pública — uma entrada por documento, com a língua pedida
|
|
1063
|
+
// ---------------------------------------------------------------------------
|
|
1064
|
+
/**
|
|
1065
|
+
* README.md do projeto scaffoldado, na língua escolhida no \`okcms init\`.
|
|
1066
|
+
* Default \`en\` (Enter do prompt e único valor em modo não-interativo).
|
|
1067
|
+
*/
|
|
1068
|
+
export function projectReadme(projectName, lang = DEFAULT_DOCS_LANG) {
|
|
1069
|
+
return lang === 'pt' ? projectReadmePt(projectName) : projectReadmeEn(projectName);
|
|
1070
|
+
}
|
|
1071
|
+
/** PLUGIN.md na língua pedida. */
|
|
1072
|
+
export function pluginDoc(lang = DEFAULT_DOCS_LANG) {
|
|
1073
|
+
return lang === 'pt' ? PLUGIN_DOC_PT : PLUGIN_DOC_EN;
|
|
1074
|
+
}
|
|
1075
|
+
/** THEME.md na língua pedida. */
|
|
1076
|
+
export function themeDoc(lang = DEFAULT_DOCS_LANG) {
|
|
1077
|
+
return lang === 'pt' ? THEME_DOC_PT : THEME_DOC_EN;
|
|
1078
|
+
}
|
|
401
1079
|
//# sourceMappingURL=scaffold-docs.js.map
|