@oktis-works/cms 0.1.14 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +158 -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/deploy.d.ts +20 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +304 -0
- package/dist/deploy.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/docs-updater.d.ts +10 -0
- package/dist/docs-updater.d.ts.map +1 -0
- package/dist/docs-updater.js +45 -0
- package/dist/docs-updater.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/history.d.ts +48 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +104 -0
- package/dist/history.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/rollback.d.ts +15 -0
- package/dist/rollback.d.ts.map +1 -0
- package/dist/rollback.js +170 -0
- package/dist/rollback.js.map +1 -0
- package/dist/scaffold-docs.d.ts +30 -6
- package/dist/scaffold-docs.d.ts.map +1 -1
- package/dist/scaffold-docs.js +728 -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 +52 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +273 -0
- package/dist/update.js.map +1 -0
- package/package.json +7 -7
package/dist/guards.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// @oktis-works/cms - Guardas de segurança da CLI
|
|
2
|
+
//
|
|
3
|
+
// A CLI não abre porta nenhuma: a superfície de rede dela é ZERO. O risco
|
|
4
|
+
// real é ela rodar DENTRO de um container comprometido — aí `okcms update`
|
|
5
|
+
// vira um executor de `bun add` (scripts de pós-install de terceiros) dentro
|
|
6
|
+
// da rede do banco, com o `.env` na mão. Estas funções transformam essa
|
|
7
|
+
// análise em checagens executáveis.
|
|
8
|
+
//
|
|
9
|
+
// Regras:
|
|
10
|
+
// 1. comandos destrutivos/deploy recusam rodar em container (--force escapa);
|
|
11
|
+
// 2. o tráfego de rede da CLI é limitado ao registry npm oficial;
|
|
12
|
+
// 3. nenhum compose de produção monta /var/run/docker.sock;
|
|
13
|
+
// 4. segredos nunca aparecem em log/stdout.
|
|
14
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
15
|
+
/** Marca `OKCMS_IN_CONTAINER=1` também detecta o caso de CLI montada à mão. */
|
|
16
|
+
const CONTAINER_ENV = 'OKCMS_IN_CONTAINER';
|
|
17
|
+
function readCgroup(exists) {
|
|
18
|
+
const path = '/proc/1/cgroup';
|
|
19
|
+
if (!exists(path))
|
|
20
|
+
return null;
|
|
21
|
+
try {
|
|
22
|
+
return readFileSync(path, 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function isInContainer(probe = {}) {
|
|
29
|
+
const exists = probe.exists ?? existsSync;
|
|
30
|
+
const env = probe.env ?? process.env;
|
|
31
|
+
if (env[CONTAINER_ENV] === '1' || env[CONTAINER_ENV] === 'true')
|
|
32
|
+
return true;
|
|
33
|
+
// Marcadores canônicos de runtime
|
|
34
|
+
if (exists('/.dockerenv'))
|
|
35
|
+
return true;
|
|
36
|
+
if (exists('/run/.containerenv'))
|
|
37
|
+
return true; // podman
|
|
38
|
+
const cgroup = probe.cgroup !== undefined ? probe.cgroup : readCgroup(exists);
|
|
39
|
+
if (cgroup && /docker|lxc|kubepods|containerd|podman|cri-o|nomad/i.test(cgroup)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
// /proc/self/cgroup do processo (quando /proc/1/cgroup não é legível)
|
|
43
|
+
if (!cgroup) {
|
|
44
|
+
const own = probe.cgroup === undefined ? readCgroupWeird(exists) : null;
|
|
45
|
+
if (own && /docker|lxc|kubepods|containerd|podman/i.test(own))
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
function readCgroupWeird(exists) {
|
|
51
|
+
const path = '/proc/self/cgroup';
|
|
52
|
+
if (!exists(path))
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
return readFileSync(path, 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Bloqueia comandos que alteram estado fora do host quando a CLI roda dentro
|
|
63
|
+
* de um container. `force` (=`--force`) é o escape consciente — registrado em
|
|
64
|
+
* log para auditoria.
|
|
65
|
+
*/
|
|
66
|
+
export function assertHostOnly(command, opts = {}) {
|
|
67
|
+
if (opts.force)
|
|
68
|
+
return { ok: true, message: '' };
|
|
69
|
+
if (!isInContainer(opts.probe ?? {}))
|
|
70
|
+
return { ok: true, message: '' };
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
message: `${command} recusou rodar dentro de um container.\n` +
|
|
74
|
+
` A CLI de deploy/config só executa no HOST — dentro do container ela viraria\n` +
|
|
75
|
+
` um executor de \`bun add\` na rede do banco com o .env exposto.\n` +
|
|
76
|
+
` Rode no host: \`docker exec -it <container-do-host> ${command}\` ou use --force.`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// 2. Allowlist de rede
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
/** Único destino que a CLI fala sem configuração explícita. */
|
|
83
|
+
export const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
|
|
84
|
+
export function registryAllowlist(env = process.env) {
|
|
85
|
+
const extra = env['OKCMS_NPM_REGISTRY'];
|
|
86
|
+
return extra ? [DEFAULT_REGISTRY, extra] : [DEFAULT_REGISTRY];
|
|
87
|
+
}
|
|
88
|
+
export function isUrlAllowed(url, allowlist = registryAllowlist()) {
|
|
89
|
+
return allowlist.some((base) => url === base || url.startsWith(`${base}/`));
|
|
90
|
+
}
|
|
91
|
+
export function assertUrlAllowed(url, allowlist = registryAllowlist()) {
|
|
92
|
+
if (isUrlAllowed(url, allowlist))
|
|
93
|
+
return { ok: true, message: '' };
|
|
94
|
+
return {
|
|
95
|
+
ok: false,
|
|
96
|
+
message: `URL fora da allowlist da CLI: ${redact(url)}\n Permitido: ${allowlist.join(', ')}`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// 3. Compose: socket do Docker é escalação de privilégio
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
const SOCKET_MOUNT = /docker\.sock/i;
|
|
103
|
+
/** true se algum serviço monta o socket do Docker (via short ou long syntax). */
|
|
104
|
+
export function hasDockerSocketMount(composeText) {
|
|
105
|
+
return SOCKET_MOUNT.test(composeText);
|
|
106
|
+
}
|
|
107
|
+
export function assertNoDockerSocket(composeText) {
|
|
108
|
+
if (!hasDockerSocketMount(composeText))
|
|
109
|
+
return { ok: true, message: '' };
|
|
110
|
+
return {
|
|
111
|
+
ok: false,
|
|
112
|
+
message: 'O compose monta /var/run/docker.sock num container de aplicação.\n' +
|
|
113
|
+
' Isso é escalação direta para root do host: qualquer RCE na app vira root.\n' +
|
|
114
|
+
' Remova o bind mount; se um serviço precisa do daemon, use um proxy dedicado.',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// 4. Redação de segredos em log
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
const SENSITIVE_KEY = /(PASS|PASSWORD|SECRET|TOKEN|API_?KEY|PRIVATE_?KEY|CREDENTIAL|DSN|DATABASE_URL|JWT)/i;
|
|
121
|
+
/** URIs com credencial: `postgres://user:senha@host` → `postgres://user:***@host`. */
|
|
122
|
+
function redactUrls(text) {
|
|
123
|
+
return text.replace(/\b([a-z][a-z0-9+.-]*:\/\/)([^:/\s@]+):([^/\s@]+)@/gi, (_all, scheme, user) => `${scheme}${user}:***@`);
|
|
124
|
+
}
|
|
125
|
+
/** `KEY=valor` sensível → `KEY=***`. */
|
|
126
|
+
function redactAssignments(text) {
|
|
127
|
+
return text.replace(/^[ \t]*([A-Za-z_][A-Za-z0-9_]*)([ \t]*=[ \t]*)(.*)$/gm, (line, key, sep, value) => {
|
|
128
|
+
if (!SENSITIVE_KEY.test(key))
|
|
129
|
+
return line;
|
|
130
|
+
if (!value || value === '***')
|
|
131
|
+
return `${key}${sep}***`;
|
|
132
|
+
return `${key}${sep}***`;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Aplica redação a QUALQUER texto de log da CLI. Chamado pelas mensagens de
|
|
137
|
+
* erro de `update`/`config` para nunca vazar senha em CI ou em issue de suporte.
|
|
138
|
+
*/
|
|
139
|
+
export function redact(text) {
|
|
140
|
+
return redactAssignments(redactUrls(text));
|
|
141
|
+
}
|
|
142
|
+
/** true se o valor parece um segredo de verdade (não vazio, não placeholder). */
|
|
143
|
+
export function looksLikeSecret(value) {
|
|
144
|
+
const trimmed = value.trim();
|
|
145
|
+
if (trimmed.length < 8)
|
|
146
|
+
return false;
|
|
147
|
+
return !/^(change-?me|dev-?secret|placeholder|example|changeme)/i.test(trimmed);
|
|
148
|
+
}
|
|
149
|
+
/** Gera um segredo forte (JWT_SECRET / cookie key) sem dependência externa. */
|
|
150
|
+
export function generateSecret(length = 48) {
|
|
151
|
+
// import dinâmico barato: só roda quando realmente precisamos gerar
|
|
152
|
+
const bytes = new Uint8Array(length);
|
|
153
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
154
|
+
let out = '';
|
|
155
|
+
for (const byte of bytes)
|
|
156
|
+
out += byte.toString(16).padStart(2, '0');
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type HistoryMode = 'download' | 'deploy' | 'pm2';
|
|
2
|
+
export interface HistoryEntry {
|
|
3
|
+
id: number;
|
|
4
|
+
/** Modo da operação. */
|
|
5
|
+
mode: HistoryMode;
|
|
6
|
+
/** Timestamp ISO da operação. */
|
|
7
|
+
at: string;
|
|
8
|
+
/** Versão da CLI que executou. */
|
|
9
|
+
cliVersion: string;
|
|
10
|
+
/** Pacotes atualizados (apenas modo download/deploy). */
|
|
11
|
+
packages?: Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
from: string;
|
|
14
|
+
to: string;
|
|
15
|
+
}>;
|
|
16
|
+
/** Lane ativa após deploy (apenas modo deploy). */
|
|
17
|
+
lane?: 'blue' | 'green';
|
|
18
|
+
/** Lane anterior (para rollback de lane). */
|
|
19
|
+
previousLane?: 'blue' | 'green' | null;
|
|
20
|
+
/** Mensagem descritiva. */
|
|
21
|
+
message: string;
|
|
22
|
+
/** Snapshot do package.json (apenas modo download). */
|
|
23
|
+
packageJsonSnapshot?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface HistoryState {
|
|
26
|
+
entries: HistoryEntry[];
|
|
27
|
+
/** Próximo ID incremental. */
|
|
28
|
+
nextId: number;
|
|
29
|
+
}
|
|
30
|
+
/** Caminho absoluto do arquivo de histórico. */
|
|
31
|
+
export declare function historyPath(cwd: string): string;
|
|
32
|
+
/** Lê o estado do histórico. */
|
|
33
|
+
export declare function readHistory(cwd: string): HistoryState;
|
|
34
|
+
/** Grava o estado do histórico (atômico via writeFileSync). */
|
|
35
|
+
export declare function writeHistory(cwd: string, state: HistoryState): void;
|
|
36
|
+
/** Adiciona uma entrada ao histórico e retorna a entrada criada. */
|
|
37
|
+
export declare function addHistoryEntry(cwd: string, entry: Omit<HistoryEntry, 'id'>, cliVersion: string): HistoryEntry;
|
|
38
|
+
/** Lista entradas (mais recentes primeiro). */
|
|
39
|
+
export declare function listHistory(cwd: string): HistoryEntry[];
|
|
40
|
+
/** Busca entrada por ID. */
|
|
41
|
+
export declare function getHistoryEntry(cwd: string, id: number): HistoryEntry | null;
|
|
42
|
+
/** Remove entrada por ID (útil para limpar). */
|
|
43
|
+
export declare function removeHistoryEntry(cwd: string, id: number): boolean;
|
|
44
|
+
/** Limpa todo o histórico. */
|
|
45
|
+
export declare function clearHistory(cwd: string): void;
|
|
46
|
+
/** Formata uma entrada para exibição no terminal. */
|
|
47
|
+
export declare function formatHistoryEntry(entry: HistoryEntry): string;
|
|
48
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,wBAAwB;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACvC,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,gCAAgC;AAChC,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAYrD;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAInE;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAC/B,UAAU,EAAE,MAAM,GACjB,YAAY,CAYd;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,EAAE,CAGvD;AAED,4BAA4B;AAC5B,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAG5E;AAED,gDAAgD;AAChD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAOnE;AAED,8BAA8B;AAC9B,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED,qDAAqD;AACrD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAuB9D"}
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// @oktis-works/cms - Sistema de histórico e rollback unificado
|
|
2
|
+
//
|
|
3
|
+
// O estado persiste em `.deploy/update-history.json` (para updates de pacotes)
|
|
4
|
+
// e em `.deploy/state.json` (para deploys blue/green).
|
|
5
|
+
// Ambos expõem a mesma API: lista, detalhe, rollback para índice.
|
|
6
|
+
//
|
|
7
|
+
// Entradas de histórico cobrem:
|
|
8
|
+
// - update:download (pacotes @oktis-works/*)
|
|
9
|
+
// - update:deploy (blue/green + pacotes)
|
|
10
|
+
// - deploy:pm2 (ecosystem pm2)
|
|
11
|
+
// - deploy:docker (alias para update:deploy)
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { join, dirname } from 'node:path';
|
|
14
|
+
const HISTORY_DIR = '.deploy';
|
|
15
|
+
const HISTORY_FILE = 'update-history.json';
|
|
16
|
+
/** Caminho absoluto do arquivo de histórico. */
|
|
17
|
+
export function historyPath(cwd) {
|
|
18
|
+
return join(cwd, HISTORY_DIR, HISTORY_FILE);
|
|
19
|
+
}
|
|
20
|
+
/** Lê o estado do histórico. */
|
|
21
|
+
export function readHistory(cwd) {
|
|
22
|
+
const path = historyPath(cwd);
|
|
23
|
+
if (!existsSync(path))
|
|
24
|
+
return { entries: [], nextId: 1 };
|
|
25
|
+
try {
|
|
26
|
+
const raw = readFileSync(path, 'utf-8');
|
|
27
|
+
const parsed = JSON.parse(raw);
|
|
28
|
+
if (!Array.isArray(parsed.entries))
|
|
29
|
+
return { entries: [], nextId: 1 };
|
|
30
|
+
if (typeof parsed.nextId !== 'number')
|
|
31
|
+
parsed.nextId = parsed.entries.length + 1;
|
|
32
|
+
return parsed;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return { entries: [], nextId: 1 };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Grava o estado do histórico (atômico via writeFileSync). */
|
|
39
|
+
export function writeHistory(cwd, state) {
|
|
40
|
+
const path = historyPath(cwd);
|
|
41
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
42
|
+
writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`, 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
/** Adiciona uma entrada ao histórico e retorna a entrada criada. */
|
|
45
|
+
export function addHistoryEntry(cwd, entry, cliVersion) {
|
|
46
|
+
const state = readHistory(cwd);
|
|
47
|
+
const newEntry = {
|
|
48
|
+
...entry,
|
|
49
|
+
id: state.nextId++,
|
|
50
|
+
cliVersion,
|
|
51
|
+
};
|
|
52
|
+
state.entries.push(newEntry);
|
|
53
|
+
// Mantém apenas os últimos 50 (diagnóstico, não log infinito)
|
|
54
|
+
if (state.entries.length > 50)
|
|
55
|
+
state.entries = state.entries.slice(-50);
|
|
56
|
+
writeHistory(cwd, state);
|
|
57
|
+
return newEntry;
|
|
58
|
+
}
|
|
59
|
+
/** Lista entradas (mais recentes primeiro). */
|
|
60
|
+
export function listHistory(cwd) {
|
|
61
|
+
const state = readHistory(cwd);
|
|
62
|
+
return [...state.entries].reverse();
|
|
63
|
+
}
|
|
64
|
+
/** Busca entrada por ID. */
|
|
65
|
+
export function getHistoryEntry(cwd, id) {
|
|
66
|
+
const state = readHistory(cwd);
|
|
67
|
+
return state.entries.find((e) => e.id === id) ?? null;
|
|
68
|
+
}
|
|
69
|
+
/** Remove entrada por ID (útil para limpar). */
|
|
70
|
+
export function removeHistoryEntry(cwd, id) {
|
|
71
|
+
const state = readHistory(cwd);
|
|
72
|
+
const idx = state.entries.findIndex((e) => e.id === id);
|
|
73
|
+
if (idx === -1)
|
|
74
|
+
return false;
|
|
75
|
+
state.entries.splice(idx, 1);
|
|
76
|
+
writeHistory(cwd, state);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/** Limpa todo o histórico. */
|
|
80
|
+
export function clearHistory(cwd) {
|
|
81
|
+
writeHistory(cwd, { entries: [], nextId: 1 });
|
|
82
|
+
}
|
|
83
|
+
/** Formata uma entrada para exibição no terminal. */
|
|
84
|
+
export function formatHistoryEntry(entry) {
|
|
85
|
+
const modeLabel = {
|
|
86
|
+
download: 'download',
|
|
87
|
+
deploy: 'deploy (blue/green)',
|
|
88
|
+
pm2: 'deploy (pm2)',
|
|
89
|
+
}[entry.mode];
|
|
90
|
+
const lines = [
|
|
91
|
+
` ${entry.id}. [${modeLabel}] ${entry.at}`,
|
|
92
|
+
` CLI: ${entry.cliVersion} · ${entry.message}`,
|
|
93
|
+
];
|
|
94
|
+
if (entry.packages && entry.packages.length > 0) {
|
|
95
|
+
for (const p of entry.packages) {
|
|
96
|
+
lines.push(` @oktis-works/${p.name}: ${p.from} → ${p.to}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (entry.lane) {
|
|
100
|
+
lines.push(` lane: ${entry.lane}${entry.previousLane ? ` (era ${entry.previousLane})` : ''}`);
|
|
101
|
+
}
|
|
102
|
+
return lines.join('\n');
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
|
package/dist/parser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAkDpD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAgBrC"}
|
package/dist/parser.js
CHANGED
|
@@ -9,11 +9,17 @@ export function parseArgs(argv) {
|
|
|
9
9
|
let i = isFlag ? 0 : 1;
|
|
10
10
|
while (i < sliced.length) {
|
|
11
11
|
const arg = sliced[i];
|
|
12
|
+
const cmd = commands.find((c) => c.name === command);
|
|
12
13
|
if (arg.startsWith('--')) {
|
|
13
14
|
const key = arg.slice(2);
|
|
15
|
+
const repeatable = cmd?.options.find((o) => o.name === key)?.repeatable === true;
|
|
14
16
|
const next = sliced[i + 1];
|
|
15
17
|
if (next && !next.startsWith('--')) {
|
|
16
|
-
|
|
18
|
+
// repetível acumula em linhas; senão a 2ª ocorrência engolia a 1ª
|
|
19
|
+
options[key] =
|
|
20
|
+
repeatable && options[key] !== undefined && options[key] !== 'true'
|
|
21
|
+
? `${options[key]}\n${next}`
|
|
22
|
+
: next;
|
|
17
23
|
i += 2;
|
|
18
24
|
}
|
|
19
25
|
else {
|
|
@@ -23,12 +29,15 @@ export function parseArgs(argv) {
|
|
|
23
29
|
}
|
|
24
30
|
else if (arg.startsWith('-')) {
|
|
25
31
|
const alias = arg.slice(1);
|
|
26
|
-
const cmd = commands.find((c) => c.name === command);
|
|
27
32
|
const opt = cmd?.options.find((o) => o.alias === alias);
|
|
28
33
|
const key = opt?.name ?? alias;
|
|
34
|
+
const repeatable = opt?.repeatable === true;
|
|
29
35
|
const next = sliced[i + 1];
|
|
30
36
|
if (next && !next.startsWith('-')) {
|
|
31
|
-
options[key] =
|
|
37
|
+
options[key] =
|
|
38
|
+
repeatable && options[key] !== undefined && options[key] !== 'true'
|
|
39
|
+
? `${options[key]}\n${next}`
|
|
40
|
+
: next;
|
|
32
41
|
i += 2;
|
|
33
42
|
}
|
|
34
43
|
else {
|
package/dist/parser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQzC,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAkB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,OAAO,GAA2B,EAAE,CAAC;IAE3C,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3B,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
|
package/dist/project-config.js
CHANGED
|
@@ -14,8 +14,8 @@ export function defaultProjectConfig(name = 'my-okcms-site') {
|
|
|
14
14
|
activeTheme: process.env['ACTIVE_THEME'] ?? '',
|
|
15
15
|
ports: {
|
|
16
16
|
api: Number(process.env['PORT'] ?? 3000),
|
|
17
|
-
admin: Number(process.env['ADMIN_PORT'] ??
|
|
18
|
-
web: Number(process.env['WEB_PORT'] ??
|
|
17
|
+
admin: Number(process.env['ADMIN_PORT'] ?? 3011),
|
|
18
|
+
web: Number(process.env['WEB_PORT'] ?? 3001),
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
21
|
}
|
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
export interface PromptIO {
|
|
3
|
+
input: Readable;
|
|
4
|
+
output: Writable;
|
|
5
|
+
/** true somente quando há terminal nos DOIS lados (TTY de verdade). */
|
|
6
|
+
isTTY: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function defaultIO(): PromptIO;
|
|
9
|
+
export declare const style: {
|
|
10
|
+
bold: (text: string) => string;
|
|
11
|
+
dim: (text: string) => string;
|
|
12
|
+
red: (text: string) => string;
|
|
13
|
+
green: (text: string) => string;
|
|
14
|
+
yellow: (text: string) => string;
|
|
15
|
+
blue: (text: string) => string;
|
|
16
|
+
cyan: (text: string) => string;
|
|
17
|
+
gray: (text: string) => string;
|
|
18
|
+
};
|
|
19
|
+
/** Símbolos canônicos — mesmos glifos já usados pelos comandos da CLI. */
|
|
20
|
+
export declare const symbol: {
|
|
21
|
+
readonly ask: "?";
|
|
22
|
+
readonly ok: "✓";
|
|
23
|
+
readonly fail: "✗";
|
|
24
|
+
readonly arrow: "→";
|
|
25
|
+
readonly bullet: "•";
|
|
26
|
+
readonly warn: "⚠";
|
|
27
|
+
};
|
|
28
|
+
export interface SelectChoice<T> {
|
|
29
|
+
value: T;
|
|
30
|
+
label: string;
|
|
31
|
+
/** Contexto curto alinhado à direita da opção. */
|
|
32
|
+
hint?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface SelectOptions<T> {
|
|
35
|
+
/** Default no Enter E valor devolvido em modo não-interativo. */
|
|
36
|
+
defaultValue?: T;
|
|
37
|
+
/** Mensagem quando não há TTY nem default. */
|
|
38
|
+
nonInteractiveError?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface InputOptions {
|
|
41
|
+
default?: string;
|
|
42
|
+
/** Mensagem de erro para re-perguntar; null/undefined aceita. */
|
|
43
|
+
validate?: (value: string) => string | null | undefined;
|
|
44
|
+
/** Preview do valor atual (ex.: máscara `••••` para segredos). */
|
|
45
|
+
placeholder?: string;
|
|
46
|
+
}
|
|
47
|
+
export declare class Prompt {
|
|
48
|
+
private readonly io;
|
|
49
|
+
private readonly input;
|
|
50
|
+
private closed;
|
|
51
|
+
constructor(io?: Partial<PromptIO>);
|
|
52
|
+
get interactive(): boolean;
|
|
53
|
+
write(text: string): void;
|
|
54
|
+
/** Título de seção do wizard. */
|
|
55
|
+
heading(text: string): void;
|
|
56
|
+
info(text: string): void;
|
|
57
|
+
success(text: string): void;
|
|
58
|
+
warn(text: string): void;
|
|
59
|
+
error(text: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Menu numerado. Em modo não-interativo devolve `defaultValue`; sem default
|
|
62
|
+
* lança erro — assim um CI nunca aciona um deploy por acidente.
|
|
63
|
+
*/
|
|
64
|
+
select<T>(title: string, choices: Array<SelectChoice<T>>, opts?: SelectOptions<T>): Promise<T>;
|
|
65
|
+
/** Confirmação Y/n. Não-interativo → `defaultValue`. */
|
|
66
|
+
confirm(title: string, opts?: {
|
|
67
|
+
defaultValue?: boolean;
|
|
68
|
+
}): Promise<boolean>;
|
|
69
|
+
/** Texto livre com validação, repetindo até aceitar. */
|
|
70
|
+
ask(title: string, opts?: InputOptions): Promise<string>;
|
|
71
|
+
/** Segredo: sem eco no TTY (mostra `*`), default via Enter. */
|
|
72
|
+
secret(title: string, opts?: InputOptions): Promise<string>;
|
|
73
|
+
/** Lê uma linha cruta (também usada pelos testes). */
|
|
74
|
+
askLine(question: string): Promise<string | null>;
|
|
75
|
+
close(): void;
|
|
76
|
+
}
|
|
77
|
+
export declare function select<T>(title: string, choices: Array<SelectChoice<T>>, opts?: SelectOptions<T>, io?: Partial<PromptIO>): Promise<T>;
|
|
78
|
+
export declare function confirm(title: string, opts?: {
|
|
79
|
+
defaultValue?: boolean;
|
|
80
|
+
}, io?: Partial<PromptIO>): Promise<boolean>;
|
|
81
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
|