@oktis-works/cms 0.2.1 → 0.3.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 +23 -6
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +262 -87
- package/dist/assets.js.map +1 -1
- package/dist/bluegreen.d.ts.map +1 -1
- package/dist/bluegreen.js +75 -52
- package/dist/bluegreen.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +238 -142
- package/dist/commands.js.map +1 -1
- package/dist/config-wizard.js +34 -36
- package/dist/config-wizard.js.map +1 -1
- package/dist/deploy-target.d.ts +20 -0
- package/dist/deploy-target.d.ts.map +1 -0
- package/dist/deploy-target.js +90 -0
- package/dist/deploy-target.js.map +1 -0
- package/dist/deploy.d.ts +7 -7
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +123 -273
- package/dist/deploy.js.map +1 -1
- package/dist/docker.d.ts +16 -0
- package/dist/docker.d.ts.map +1 -1
- package/dist/docker.js +25 -0
- package/dist/docker.js.map +1 -1
- package/dist/doctor.js +12 -12
- package/dist/doctor.js.map +1 -1
- package/dist/env-file.js +1 -1
- package/dist/env-file.js.map +1 -1
- package/dist/env-schema.d.ts.map +1 -1
- package/dist/env-schema.js +64 -64
- package/dist/env-schema.js.map +1 -1
- package/dist/extension-scaffold.js +5 -5
- package/dist/extension-scaffold.js.map +1 -1
- package/dist/guards.js +8 -8
- package/dist/guards.js.map +1 -1
- package/dist/history.js +1 -1
- package/dist/installer.js +9 -9
- package/dist/installer.js.map +1 -1
- package/dist/npm-registry.js +1 -1
- package/dist/npm-registry.js.map +1 -1
- package/dist/pm2.d.ts +18 -0
- package/dist/pm2.d.ts.map +1 -0
- package/dist/pm2.js +179 -0
- package/dist/pm2.js.map +1 -0
- package/dist/project-config.js +1 -1
- package/dist/project-config.js.map +1 -1
- package/dist/prompt.d.ts +27 -4
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +254 -29
- package/dist/prompt.js.map +1 -1
- package/dist/redeploy.d.ts +6 -1
- package/dist/redeploy.d.ts.map +1 -1
- package/dist/redeploy.js +137 -74
- package/dist/redeploy.js.map +1 -1
- package/dist/rollback.js +21 -21
- package/dist/rollback.js.map +1 -1
- package/dist/scaffold-docs.d.ts.map +1 -1
- package/dist/scaffold-docs.js +44 -19
- package/dist/scaffold-docs.js.map +1 -1
- package/dist/scaffold.d.ts +3 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +25 -16
- package/dist/scaffold.js.map +1 -1
- package/dist/simple.d.ts +31 -0
- package/dist/simple.d.ts.map +1 -0
- package/dist/simple.js +200 -0
- package/dist/simple.js.map +1 -0
- package/dist/start.js +1 -1
- package/dist/theme-build.js +3 -3
- package/dist/theme-build.js.map +1 -1
- package/dist/update.d.ts +22 -15
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +163 -81
- package/dist/update.js.map +1 -1
- package/package.json +7 -7
package/dist/commands.js
CHANGED
|
@@ -20,18 +20,18 @@ async function prepareDb(options) {
|
|
|
20
20
|
const { ensureCoreSchema, resolveTenantId, seedCoreData } = await import('@oktis-works/database');
|
|
21
21
|
const applied = await ensureCoreSchema();
|
|
22
22
|
if (applied) {
|
|
23
|
-
console.log('✓ schema
|
|
23
|
+
console.log('✓ core schema applied (database initialized)');
|
|
24
24
|
}
|
|
25
25
|
// Seed idempotente (roles da política + settings gerais): roda em qualquer
|
|
26
26
|
// banco — sem ele, o primeiro usuário registra e cai em 403 em tudo.
|
|
27
27
|
try {
|
|
28
28
|
const seeded = await seedCoreData();
|
|
29
29
|
if (seeded.roles > 0 || seeded.settings > 0) {
|
|
30
|
-
console.log(`✓ seed: ${seeded.roles} roles, ${seeded.settings} settings
|
|
30
|
+
console.log(`✓ seed: ${seeded.roles} roles, ${seeded.settings} settings created`);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
34
|
-
console.warn('⚠
|
|
34
|
+
console.warn('⚠ default data seed failed:', error instanceof Error ? error.message : error);
|
|
35
35
|
}
|
|
36
36
|
return resolveTenantId(getTenantId(options));
|
|
37
37
|
}
|
|
@@ -51,9 +51,11 @@ export const commands = [
|
|
|
51
51
|
handler: async (args, options) => {
|
|
52
52
|
const { scaffoldProject, installProjectDeps } = await import('./scaffold.js');
|
|
53
53
|
const { DEFAULT_DOCS_LANG, parseDocsLang } = await import('./scaffold-docs.js');
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
//
|
|
54
|
+
const { Prompt } = await import('./prompt.js');
|
|
55
|
+
const prompt = new Prompt();
|
|
56
|
+
// Language of the generated docs (.md only — the code never changes
|
|
57
|
+
// language). `--lang en|pt` decides without a TTY (CI/script); with a TTY
|
|
58
|
+
// and no flag, an arrow menu asks; without either, English is the default.
|
|
57
59
|
const rawLang = options['lang'];
|
|
58
60
|
let lang;
|
|
59
61
|
if (rawLang !== undefined && rawLang !== 'true') {
|
|
@@ -66,31 +68,43 @@ export const commands = [
|
|
|
66
68
|
else if (rawLang === 'true') {
|
|
67
69
|
throw new Error('--lang requires a value: en or pt');
|
|
68
70
|
}
|
|
69
|
-
else {
|
|
70
|
-
|
|
71
|
-
lang = await select('Idioma da documentação (README.md, PLUGIN.md, THEME.md)', [
|
|
71
|
+
else if (prompt.interactive) {
|
|
72
|
+
lang = await prompt.select('Docs language (README.md, PLUGIN.md, THEME.md)', [
|
|
72
73
|
{ value: 'en', label: 'English', hint: 'default' },
|
|
73
74
|
{ value: 'pt', label: 'Português (Brasil)' },
|
|
74
75
|
], { defaultValue: DEFAULT_DOCS_LANG });
|
|
75
76
|
}
|
|
76
|
-
// O arg posicional tem prioridade sobre -d: `init cms-teste` deve criar
|
|
77
|
-
// o diretório cms-teste (o default '.' injetado pelo parser engolia args[0]).
|
|
78
|
-
const target = args[0] ?? options['dir'] ?? '.';
|
|
79
|
-
const name = args[1] ?? basename(resolve(target));
|
|
80
|
-
const root = await scaffoldProject(target, name, lang);
|
|
81
|
-
// Zero config: instala as dependências já no init (bun, ou npm sem bun).
|
|
82
|
-
console.log('Instalando dependências do projeto...');
|
|
83
|
-
const install = installProjectDeps(root);
|
|
84
|
-
if (install.ok) {
|
|
85
|
-
console.log(`✓ dependências instaladas via ${install.tool}`);
|
|
86
|
-
}
|
|
87
77
|
else {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
lang = DEFAULT_DOCS_LANG;
|
|
79
|
+
}
|
|
80
|
+
// The positional arg wins over -d: `init my-site` must create my-site
|
|
81
|
+
// (the parser's default '.' would swallow args[0]). Without either, an
|
|
82
|
+
// interactive run asks where to put the project.
|
|
83
|
+
let target = args[0] ?? options['dir'];
|
|
84
|
+
if (target === undefined && prompt.interactive) {
|
|
85
|
+
target = await prompt.ask('Project directory', { default: '.' });
|
|
93
86
|
}
|
|
87
|
+
target ??= '.';
|
|
88
|
+
const name = args[1] ?? basename(resolve(target));
|
|
89
|
+
const root = resolve(target);
|
|
90
|
+
// Zero config: dependencies are installed right in `init` (bun, or npm
|
|
91
|
+
// when bun is missing) — and BEFORE the summary, so the next steps are
|
|
92
|
+
// the last thing on screen.
|
|
93
|
+
await scaffoldProject(target, name, lang, async () => {
|
|
94
|
+
console.log('Installing project dependencies...');
|
|
95
|
+
const install = installProjectDeps(root);
|
|
96
|
+
if (install.ok) {
|
|
97
|
+
console.log(`✓ dependencies installed with ${install.tool}`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
console.warn(`⚠ automatic install failed with ${install.tool}. Run it manually in ${root}:`);
|
|
101
|
+
console.warn(' bun install (or: npm install)');
|
|
102
|
+
if (install.output) {
|
|
103
|
+
console.warn(install.output.split('\n').slice(-5).join('\n'));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
prompt.close();
|
|
94
108
|
},
|
|
95
109
|
},
|
|
96
110
|
{
|
|
@@ -110,7 +124,7 @@ export const commands = [
|
|
|
110
124
|
},
|
|
111
125
|
{
|
|
112
126
|
name: 'stop',
|
|
113
|
-
description: 'Stop apps started by `start` (via pidfile
|
|
127
|
+
description: 'Stop apps started by `start` (via pidfile or process detection)',
|
|
114
128
|
options: [],
|
|
115
129
|
handler: async () => {
|
|
116
130
|
const { stopAll, findRunningApps, clearPids } = await import('./runtime-state.js');
|
|
@@ -120,24 +134,24 @@ export const commands = [
|
|
|
120
134
|
for (const proc of fallback) {
|
|
121
135
|
try {
|
|
122
136
|
process.kill(proc.pid, 'SIGTERM');
|
|
123
|
-
console.log(`[stop] ${proc.label} (pid ${proc.pid})
|
|
137
|
+
console.log(`[stop] ${proc.label} (pid ${proc.pid}) finished`);
|
|
124
138
|
}
|
|
125
139
|
catch {
|
|
126
|
-
console.error(`[stop]
|
|
140
|
+
console.error(`[stop] failed to stop ${proc.label} (pid ${proc.pid})`);
|
|
127
141
|
}
|
|
128
142
|
}
|
|
129
143
|
if (fallback.length === 0) {
|
|
130
|
-
console.log('
|
|
144
|
+
console.log('No apps running.');
|
|
131
145
|
}
|
|
132
146
|
clearPids();
|
|
133
147
|
return;
|
|
134
148
|
}
|
|
135
149
|
for (const result of results) {
|
|
136
150
|
if (result.stopped) {
|
|
137
|
-
console.log(`[stop] ${result.label} (pid ${result.pid})
|
|
151
|
+
console.log(`[stop] ${result.label} (pid ${result.pid}) finished`);
|
|
138
152
|
}
|
|
139
153
|
else {
|
|
140
|
-
console.log(`[stop] ${result.label} (pid ${result.pid})
|
|
154
|
+
console.log(`[stop] ${result.label} (pid ${result.pid}) was no longer running`);
|
|
141
155
|
}
|
|
142
156
|
}
|
|
143
157
|
clearPids();
|
|
@@ -145,27 +159,27 @@ export const commands = [
|
|
|
145
159
|
},
|
|
146
160
|
{
|
|
147
161
|
name: 'status',
|
|
148
|
-
description: 'Show status of apps started by `start` +
|
|
162
|
+
description: 'Show status of apps started by `start` + project summary',
|
|
149
163
|
options: [],
|
|
150
164
|
handler: async () => {
|
|
151
165
|
const { statusAll } = await import('./runtime-state.js');
|
|
152
166
|
const { loadProjectConfig } = await import('./project-config.js');
|
|
153
167
|
const config = loadProjectConfig();
|
|
154
168
|
const processes = statusAll();
|
|
155
|
-
console.log(`
|
|
156
|
-
console.log(`
|
|
169
|
+
console.log(`Project "${config.name}" — ports api:${config.ports.api} admin:${config.ports.admin} web:${config.ports.web}`);
|
|
170
|
+
console.log(`Active theme: ${config.activeTheme || '(not set)'}`);
|
|
157
171
|
if (processes.length === 0) {
|
|
158
|
-
console.log('
|
|
172
|
+
console.log('No pidfile found (use `okcms start`).');
|
|
159
173
|
return;
|
|
160
174
|
}
|
|
161
175
|
for (const proc of processes) {
|
|
162
|
-
console.log(` ${proc.alive ? '●' : '○'} ${proc.label.padEnd(6)} pid=${proc.pid}
|
|
176
|
+
console.log(` ${proc.alive ? '●' : '○'} ${proc.label.padEnd(6)} pid=${proc.pid} started=${proc.startedAt}`);
|
|
163
177
|
}
|
|
164
178
|
},
|
|
165
179
|
},
|
|
166
180
|
{
|
|
167
181
|
name: 'doctor',
|
|
168
|
-
description: '
|
|
182
|
+
description: 'Environment diagnostics: node, .env, database, config, docker/compose/lane/proxy',
|
|
169
183
|
options: [],
|
|
170
184
|
handler: async () => {
|
|
171
185
|
const { runDoctorChecks } = await import('./doctor.js');
|
|
@@ -178,32 +192,32 @@ export const commands = [
|
|
|
178
192
|
failed++;
|
|
179
193
|
}
|
|
180
194
|
if (failed > 0) {
|
|
181
|
-
console.error(`doctor: ${failed}
|
|
195
|
+
console.error(`doctor: ${failed} required problem(s) found`);
|
|
182
196
|
process.exitCode = 1;
|
|
183
197
|
}
|
|
184
198
|
else {
|
|
185
|
-
console.log('
|
|
199
|
+
console.log('Environment OK.');
|
|
186
200
|
}
|
|
187
201
|
},
|
|
188
202
|
},
|
|
189
203
|
{
|
|
190
204
|
name: 'plugin:create',
|
|
191
|
-
description: 'Scaffold
|
|
205
|
+
description: 'Scaffold a minimal compatible plugin (--name)',
|
|
192
206
|
options: [
|
|
193
|
-
{ name: 'name', alias: 'n', description: '
|
|
194
|
-
{ name: 'dir', alias: 'd', description: '
|
|
207
|
+
{ name: 'name', alias: 'n', description: 'Plugin name', required: true },
|
|
208
|
+
{ name: 'dir', alias: 'd', description: 'Base directory (default: ./plugins)', required: false },
|
|
195
209
|
],
|
|
196
210
|
handler: async (_args, options) => {
|
|
197
211
|
const { scaffoldPlugin } = await import('./extension-scaffold.js');
|
|
198
212
|
const name = options['name'];
|
|
199
213
|
if (!name) {
|
|
200
|
-
console.error('
|
|
214
|
+
console.error('Plugin name is required (--name)');
|
|
201
215
|
process.exit(1);
|
|
202
216
|
}
|
|
203
217
|
try {
|
|
204
218
|
const result = scaffoldPlugin(name, options['dir']);
|
|
205
|
-
console.log(`Plugin
|
|
206
|
-
console.log(`
|
|
219
|
+
console.log(`Plugin created at ${result.dir}`);
|
|
220
|
+
console.log(`Compatibility validated against CMS ${result.manifest['compatibility'] ? '' : ''}(manifest.json)`);
|
|
207
221
|
}
|
|
208
222
|
catch (error) {
|
|
209
223
|
console.error(error instanceof Error ? error.message : String(error));
|
|
@@ -213,27 +227,27 @@ export const commands = [
|
|
|
213
227
|
},
|
|
214
228
|
{
|
|
215
229
|
name: 'theme:create',
|
|
216
|
-
description: 'Scaffold
|
|
230
|
+
description: 'Scaffold a minimal compatible theme (--name --style css|scss|tailwind)',
|
|
217
231
|
options: [
|
|
218
|
-
{ name: 'name', alias: 'n', description: '
|
|
219
|
-
{ name: 'dir', alias: 'd', description: '
|
|
220
|
-
{ name: 'style', alias: 's', description: '
|
|
232
|
+
{ name: 'name', alias: 'n', description: 'Theme name', required: true },
|
|
233
|
+
{ name: 'dir', alias: 'd', description: 'Base directory (default: ./themes)', required: false },
|
|
234
|
+
{ name: 'style', alias: 's', description: 'Style engine: css|scss|tailwind', required: false },
|
|
221
235
|
],
|
|
222
236
|
handler: async (_args, options) => {
|
|
223
237
|
const { scaffoldTheme } = await import('./extension-scaffold.js');
|
|
224
238
|
const name = options['name'];
|
|
225
239
|
const style = (options['style'] ?? 'css');
|
|
226
240
|
if (!name) {
|
|
227
|
-
console.error('
|
|
241
|
+
console.error('Theme name is required (--name)');
|
|
228
242
|
process.exit(1);
|
|
229
243
|
}
|
|
230
244
|
if (!['css', 'scss', 'tailwind'].includes(style)) {
|
|
231
|
-
console.error('--style
|
|
245
|
+
console.error('--style must be css|scss|tailwind');
|
|
232
246
|
process.exit(1);
|
|
233
247
|
}
|
|
234
248
|
try {
|
|
235
249
|
const result = scaffoldTheme(name, options['dir'], style);
|
|
236
|
-
console.log(`
|
|
250
|
+
console.log(`Theme created at ${result.dir} (engine: ${style})`);
|
|
237
251
|
}
|
|
238
252
|
catch (error) {
|
|
239
253
|
console.error(error instanceof Error ? error.message : String(error));
|
|
@@ -243,16 +257,16 @@ export const commands = [
|
|
|
243
257
|
},
|
|
244
258
|
{
|
|
245
259
|
name: 'theme:build',
|
|
246
|
-
description: '
|
|
260
|
+
description: 'Compile theme styles (SCSS/Tailwind -> dist/theme.css with [data-theme] isolation)',
|
|
247
261
|
options: [
|
|
248
|
-
{ name: 'name', alias: 'n', description: '
|
|
249
|
-
{ name: 'themes-dir', alias: 'd', description: '
|
|
262
|
+
{ name: 'name', alias: 'n', description: 'Theme name', required: true },
|
|
263
|
+
{ name: 'themes-dir', alias: 'd', description: 'Themes directory (default: ./themes)', required: false },
|
|
250
264
|
],
|
|
251
265
|
handler: async (_args, options) => {
|
|
252
266
|
const { join } = await import('node:path');
|
|
253
267
|
const name = options['name'];
|
|
254
268
|
if (!name) {
|
|
255
|
-
console.error('--name
|
|
269
|
+
console.error('--name required');
|
|
256
270
|
process.exit(1);
|
|
257
271
|
}
|
|
258
272
|
const themesDir = options['themes-dir'] ?? join(process.cwd(), 'themes');
|
|
@@ -260,7 +274,7 @@ export const commands = [
|
|
|
260
274
|
const { buildThemeStylesOnDisk } = await import('./theme-build.js');
|
|
261
275
|
const outcome = await buildThemeStylesOnDisk(themesDir, name);
|
|
262
276
|
if (!outcome.entry)
|
|
263
|
-
console.log(`[${name}]
|
|
277
|
+
console.log(`[${name}] no style entry (${outcome.engine})`);
|
|
264
278
|
for (const warning of outcome.warnings)
|
|
265
279
|
console.warn(`warn: ${warning}`);
|
|
266
280
|
console.log(`[${name}] ${outcome.engine} -> ${outcome.output} (${outcome.bytes} bytes) isolated=${outcome.isolated}`);
|
|
@@ -273,9 +287,9 @@ export const commands = [
|
|
|
273
287
|
},
|
|
274
288
|
{
|
|
275
289
|
name: 'build',
|
|
276
|
-
description: 'Build
|
|
290
|
+
description: 'Build project apps via bun filters (--apps api,admin,web)',
|
|
277
291
|
options: [
|
|
278
|
-
{ name: 'apps', alias: 'a', description: 'Apps
|
|
292
|
+
{ name: 'apps', alias: 'a', description: 'Apps to build (default: api,admin,web)', required: false },
|
|
279
293
|
],
|
|
280
294
|
handler: async (_args, options) => {
|
|
281
295
|
const { runProjectBuild, isWorkspaceProject } = await import('./build.js');
|
|
@@ -283,8 +297,8 @@ export const commands = [
|
|
|
283
297
|
// OkCMS vêm pré-compilados do npm — o `bun run --filter` falharia com
|
|
284
298
|
// "No packages matched the filter".
|
|
285
299
|
if (!isWorkspaceProject(process.cwd())) {
|
|
286
|
-
console.log('
|
|
287
|
-
console.log('
|
|
300
|
+
console.log('OkCMS apps come pre-built from npm — nothing to build in this project.');
|
|
301
|
+
console.log('To compile theme styles use: okcms theme:build --name <theme>');
|
|
288
302
|
return;
|
|
289
303
|
}
|
|
290
304
|
const appsArg = options['apps'];
|
|
@@ -300,20 +314,20 @@ export const commands = [
|
|
|
300
314
|
console.error(step.output.split('\n').slice(-10).join('\n'));
|
|
301
315
|
}
|
|
302
316
|
}
|
|
303
|
-
console.log(ok ? `Build
|
|
317
|
+
console.log(ok ? `Build completed in ${Date.now() - started}ms.` : 'Build failed.');
|
|
304
318
|
process.exitCode = ok ? 0 : 1;
|
|
305
319
|
},
|
|
306
320
|
},
|
|
307
321
|
{
|
|
308
322
|
name: 'prerender',
|
|
309
|
-
description: '
|
|
323
|
+
description: 'Statically prerender published pages for the active theme (best-effort)',
|
|
310
324
|
options: [
|
|
311
|
-
{ name: 'out', alias: 'o', description: '
|
|
325
|
+
{ name: 'out', alias: 'o', description: 'Output directory (default: ./.prerender)', required: false },
|
|
312
326
|
],
|
|
313
327
|
handler: async (_args, options) => {
|
|
314
328
|
const { join } = await import('node:path');
|
|
315
329
|
if (!process.env['DATABASE_URL']) {
|
|
316
|
-
console.log('[prerender] DATABASE_URL
|
|
330
|
+
console.log('[prerender] DATABASE_URL not set — skipping (best-effort).');
|
|
317
331
|
return;
|
|
318
332
|
}
|
|
319
333
|
const outDir = options['out'] ?? join(process.cwd(), '.prerender');
|
|
@@ -326,27 +340,27 @@ export const commands = [
|
|
|
326
340
|
path: `/${content.slug}`,
|
|
327
341
|
render: async () => `<main data-type="${content.type}" data-slug="${content.slug}"></main>`,
|
|
328
342
|
})), outDir);
|
|
329
|
-
console.log(`[prerender] ${result.pages}
|
|
343
|
+
console.log(`[prerender] ${result.pages} page(s) generated at ${outDir}`);
|
|
330
344
|
if (result.failed.length > 0) {
|
|
331
345
|
const failedPaths = result.failed.map((failed) => failed.path).join(', ');
|
|
332
|
-
console.warn(`[prerender] ${result.failed.length}
|
|
346
|
+
console.warn(`[prerender] ${result.failed.length} failure(s): ${failedPaths}`);
|
|
333
347
|
}
|
|
334
348
|
}
|
|
335
349
|
catch (error) {
|
|
336
|
-
console.warn(`[prerender]
|
|
350
|
+
console.warn(`[prerender] unavailable (${error instanceof Error ? error.message : String(error)}) — skipping.`);
|
|
337
351
|
}
|
|
338
352
|
},
|
|
339
353
|
},
|
|
340
354
|
{
|
|
341
355
|
name: 'config',
|
|
342
|
-
description: '
|
|
356
|
+
description: 'Environment variables wizard (.env) — interactive, or --list / --set KEY=value',
|
|
343
357
|
options: [
|
|
344
|
-
{ name: 'set', alias: 's', description: '
|
|
345
|
-
{ name: 'list', alias: 'l', description: '
|
|
346
|
-
{ name: 'show-secrets', alias: 'S', description: '
|
|
347
|
-
{ name: 'non-interactive', alias: 'n', description: '
|
|
348
|
-
{ name: 'section', alias: 'x', description: '
|
|
349
|
-
{ name: 'force', alias: 'F', description: '
|
|
358
|
+
{ name: 'set', alias: 's', description: 'Set a key (repeat for more): --set PORT=3000', required: false, repeatable: true },
|
|
359
|
+
{ name: 'list', alias: 'l', description: 'List .env keys (secrets masked)', required: false },
|
|
360
|
+
{ name: 'show-secrets', alias: 'S', description: 'With --list, show secrets unmasked', required: false },
|
|
361
|
+
{ name: 'non-interactive', alias: 'n', description: 'No TTY wait (CI) — output of --list', required: false },
|
|
362
|
+
{ name: 'section', alias: 'x', description: 'Open directly on a section (app|database|redis|auth|storage|worker|cache|ports|theme|deploy)', required: false },
|
|
363
|
+
{ name: 'force', alias: 'F', description: 'Allow running inside a container (not recommended)', required: false },
|
|
350
364
|
],
|
|
351
365
|
handler: async (_args, options) => {
|
|
352
366
|
const { runConfigWizard } = await import('./config-wizard.js');
|
|
@@ -364,21 +378,58 @@ export const commands = [
|
|
|
364
378
|
},
|
|
365
379
|
{
|
|
366
380
|
name: 'update',
|
|
367
|
-
description: '
|
|
381
|
+
description: 'Update packages, then optionally deploy (blue/green, simple or PM2)',
|
|
368
382
|
options: [
|
|
369
|
-
{
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
{
|
|
383
|
+
{
|
|
384
|
+
name: 'install',
|
|
385
|
+
alias: 'i',
|
|
386
|
+
description: 'Download mode: apply the updates to node_modules',
|
|
387
|
+
required: false,
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
name: 'mode',
|
|
391
|
+
alias: 'm',
|
|
392
|
+
description: 'Skip the menu: download (packages only) or deploy',
|
|
393
|
+
required: false,
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
name: 'target',
|
|
397
|
+
alias: 't',
|
|
398
|
+
description: 'Skip the target menu: blue-green | simple | pm2',
|
|
399
|
+
required: false,
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
name: 'no-cache',
|
|
403
|
+
alias: 'c',
|
|
404
|
+
description: 'Deploy: build --no-cache (clean rebuild, slower)',
|
|
405
|
+
required: false,
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
name: 'remove-orphans',
|
|
409
|
+
alias: 'r',
|
|
410
|
+
description: 'Deploy (blue/green): down --remove-orphans on the old lane (default)',
|
|
411
|
+
required: false,
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
name: 'keep-orphans',
|
|
415
|
+
alias: 'k',
|
|
416
|
+
description: 'Deploy (blue/green): keep the orphan containers of the old lane',
|
|
417
|
+
required: false,
|
|
418
|
+
},
|
|
419
|
+
{ name: 'yes', alias: 'y', description: 'No prompts: take every default', required: false },
|
|
420
|
+
{
|
|
421
|
+
name: 'force',
|
|
422
|
+
alias: 'F',
|
|
423
|
+
description: 'Allow running inside a container (not recommended)',
|
|
424
|
+
required: false,
|
|
425
|
+
},
|
|
376
426
|
],
|
|
377
427
|
handler: async (_args, options) => {
|
|
378
428
|
const { runUpdate } = await import('./update.js');
|
|
379
429
|
const code = await runUpdate({
|
|
380
430
|
install: options['install'] !== undefined,
|
|
381
431
|
mode: options['mode'],
|
|
432
|
+
target: options['target'],
|
|
382
433
|
noCache: options['no-cache'] !== undefined,
|
|
383
434
|
removeOrphans: options['remove-orphans'] !== undefined,
|
|
384
435
|
keepOrphans: options['keep-orphans'] !== undefined,
|
|
@@ -391,18 +442,54 @@ export const commands = [
|
|
|
391
442
|
},
|
|
392
443
|
{
|
|
393
444
|
name: 'redeploy',
|
|
394
|
-
description: '
|
|
445
|
+
description: 'Apply a freshly installed plugin/theme: migrations + theme build + deploy',
|
|
395
446
|
options: [
|
|
396
|
-
{ name: 'plugin', alias: 'p', description: '
|
|
397
|
-
{ name: 'theme', alias: 't', description: '
|
|
398
|
-
{
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
{
|
|
405
|
-
|
|
447
|
+
{ name: 'plugin', alias: 'p', description: 'Only prepare the migrations of this plugin', required: false },
|
|
448
|
+
{ name: 'theme', alias: 't', description: 'Only build this theme', required: false },
|
|
449
|
+
{
|
|
450
|
+
name: 'skip-migrations',
|
|
451
|
+
alias: 'M',
|
|
452
|
+
description: 'Do not copy plugin SQL into migrations/',
|
|
453
|
+
required: false,
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
name: 'skip-theme-build',
|
|
457
|
+
alias: 'B',
|
|
458
|
+
description: 'Do not compile theme styles',
|
|
459
|
+
required: false,
|
|
460
|
+
},
|
|
461
|
+
{ name: 'dry-run', alias: 'n', description: 'Show the plan and exit without running', required: false },
|
|
462
|
+
{
|
|
463
|
+
name: 'target',
|
|
464
|
+
alias: 'T',
|
|
465
|
+
description: 'Skip the target menu: blue-green | simple | pm2',
|
|
466
|
+
required: false,
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
name: 'no-cache',
|
|
470
|
+
alias: 'c',
|
|
471
|
+
description: 'Deploy: build --no-cache (clean rebuild, slower)',
|
|
472
|
+
required: false,
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
name: 'remove-orphans',
|
|
476
|
+
alias: 'r',
|
|
477
|
+
description: 'Deploy (blue/green): down --remove-orphans on the old lane (default)',
|
|
478
|
+
required: false,
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: 'keep-orphans',
|
|
482
|
+
alias: 'k',
|
|
483
|
+
description: 'Deploy (blue/green): keep the orphan containers of the old lane',
|
|
484
|
+
required: false,
|
|
485
|
+
},
|
|
486
|
+
{ name: 'yes', alias: 'y', description: 'No prompts: take every default', required: false },
|
|
487
|
+
{
|
|
488
|
+
name: 'force',
|
|
489
|
+
alias: 'F',
|
|
490
|
+
description: 'Allow running inside a container (not recommended)',
|
|
491
|
+
required: false,
|
|
492
|
+
},
|
|
406
493
|
],
|
|
407
494
|
handler: async (_args, options) => {
|
|
408
495
|
const { runRedeploy } = await import('./redeploy.js');
|
|
@@ -412,6 +499,7 @@ export const commands = [
|
|
|
412
499
|
skipMigrations: options['skip-migrations'] !== undefined,
|
|
413
500
|
skipThemeBuild: options['skip-theme-build'] !== undefined,
|
|
414
501
|
dryRun: options['dry-run'] !== undefined,
|
|
502
|
+
target: options['target'],
|
|
415
503
|
noCache: options['no-cache'] !== undefined,
|
|
416
504
|
removeOrphans: options['remove-orphans'] !== undefined,
|
|
417
505
|
keepOrphans: options['keep-orphans'] !== undefined,
|
|
@@ -531,7 +619,7 @@ export const commands = [
|
|
|
531
619
|
handler: async (_args, options) => {
|
|
532
620
|
const name = options['name'];
|
|
533
621
|
if (!name) {
|
|
534
|
-
console.error('
|
|
622
|
+
console.error('Plugin name or path is required (--name)');
|
|
535
623
|
process.exit(1);
|
|
536
624
|
}
|
|
537
625
|
const { installExtension } = await import('./installer.js');
|
|
@@ -564,7 +652,7 @@ export const commands = [
|
|
|
564
652
|
try {
|
|
565
653
|
const results = await searchExtensions('plugin', options['query'] ?? '');
|
|
566
654
|
if (results.length === 0) {
|
|
567
|
-
console.log('
|
|
655
|
+
console.log('No plugins found.');
|
|
568
656
|
return;
|
|
569
657
|
}
|
|
570
658
|
for (const result of results) {
|
|
@@ -585,7 +673,7 @@ export const commands = [
|
|
|
585
673
|
{ name: 'info', alias: 'i', description: 'Show manifest info', required: false },
|
|
586
674
|
{ name: 'enable', alias: 'e', description: 'Enable the plugin', required: false },
|
|
587
675
|
{ name: 'disable', alias: 'd', description: 'Disable the plugin', required: false },
|
|
588
|
-
{ name: 'uninstall', alias: 'u', description: 'Uninstall (remove files +
|
|
676
|
+
{ name: 'uninstall', alias: 'u', description: 'Uninstall (remove files + registry)', required: false },
|
|
589
677
|
],
|
|
590
678
|
handler: async (_args, options) => {
|
|
591
679
|
const { readFileSync } = await import('node:fs');
|
|
@@ -594,23 +682,23 @@ export const commands = [
|
|
|
594
682
|
const { setEnabled, loadExtensionsState, uninstallExtension } = await import('./extensions-state.js');
|
|
595
683
|
const name = options['name'];
|
|
596
684
|
if (!name) {
|
|
597
|
-
console.error('
|
|
685
|
+
console.error('Plugin name is required (--name)');
|
|
598
686
|
process.exit(1);
|
|
599
687
|
}
|
|
600
688
|
if (options['uninstall'] !== undefined) {
|
|
601
689
|
const result = uninstallExtension('plugin', name);
|
|
602
690
|
if (!result.removed) {
|
|
603
|
-
console.log(`Plugin "${name}"
|
|
691
|
+
console.log(`Plugin "${name}" was not installed.`);
|
|
604
692
|
process.exitCode = 1;
|
|
605
693
|
return;
|
|
606
694
|
}
|
|
607
|
-
console.log(`Plugin "${name}"
|
|
695
|
+
console.log(`Plugin "${name}" uninstalled (${result.targetDir}).`);
|
|
608
696
|
return;
|
|
609
697
|
}
|
|
610
698
|
if (options['enable'] !== undefined || options['disable'] !== undefined) {
|
|
611
699
|
const enabled = options['enable'] !== undefined;
|
|
612
700
|
const ok = setEnabled('plugin', name, enabled);
|
|
613
|
-
console.log(ok ? `Plugin "${name}" ${enabled ? '
|
|
701
|
+
console.log(ok ? `Plugin "${name}" ${enabled ? 'enabled' : 'disabled'}.` : `Plugin "${name}" is not registered.`);
|
|
614
702
|
process.exitCode = ok ? 0 : 1;
|
|
615
703
|
return;
|
|
616
704
|
}
|
|
@@ -620,15 +708,15 @@ export const commands = [
|
|
|
620
708
|
try {
|
|
621
709
|
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
622
710
|
const state = loadExtensionsState().plugins[name];
|
|
623
|
-
console.log(`
|
|
624
|
-
console.log(`
|
|
625
|
-
console.log(`
|
|
626
|
-
console.log(`Entry:
|
|
627
|
-
console.log(`
|
|
628
|
-
console.log(`
|
|
711
|
+
console.log(`Name: ${manifest['name'] ?? name}`);
|
|
712
|
+
console.log(`Version: ${manifest['version'] ?? '?'}`);
|
|
713
|
+
console.log(`Description: ${manifest['description'] ?? '-'}`);
|
|
714
|
+
console.log(`Entry: ${manifest['main'] ?? '?'}`);
|
|
715
|
+
console.log(`Permissions: ${manifest['permissions']?.join(', ') ?? '-'}`);
|
|
716
|
+
console.log(`State: ${state?.enabled === false ? 'disabled' : 'enabled'}`);
|
|
629
717
|
}
|
|
630
718
|
catch {
|
|
631
|
-
console.error(`
|
|
719
|
+
console.error(`Manifest not found at ${manifestPath}`);
|
|
632
720
|
process.exit(1);
|
|
633
721
|
}
|
|
634
722
|
},
|
|
@@ -642,7 +730,7 @@ export const commands = [
|
|
|
642
730
|
handler: async (_args, options) => {
|
|
643
731
|
const name = options['name'];
|
|
644
732
|
if (!name) {
|
|
645
|
-
console.error('
|
|
733
|
+
console.error('Theme name or path is required (--name)');
|
|
646
734
|
process.exit(1);
|
|
647
735
|
}
|
|
648
736
|
const { installExtension } = await import('./installer.js');
|
|
@@ -675,7 +763,7 @@ export const commands = [
|
|
|
675
763
|
try {
|
|
676
764
|
const results = await searchExtensions('theme', options['query'] ?? '');
|
|
677
765
|
if (results.length === 0) {
|
|
678
|
-
console.log('
|
|
766
|
+
console.log('No themes found.');
|
|
679
767
|
return;
|
|
680
768
|
}
|
|
681
769
|
for (const result of results) {
|
|
@@ -696,7 +784,7 @@ export const commands = [
|
|
|
696
784
|
{ name: 'info', alias: 'i', description: 'Show theme.json info', required: false },
|
|
697
785
|
{ name: 'enable', alias: 'e', description: 'Enable the theme', required: false },
|
|
698
786
|
{ name: 'disable', alias: 'd', description: 'Disable the theme', required: false },
|
|
699
|
-
{ name: 'uninstall', alias: 'u', description: 'Uninstall (remove files +
|
|
787
|
+
{ name: 'uninstall', alias: 'u', description: 'Uninstall (remove files + registry)', required: false },
|
|
700
788
|
{ name: 'set-active', alias: 's', description: 'Set as active theme', required: false },
|
|
701
789
|
],
|
|
702
790
|
handler: async (_args, options) => {
|
|
@@ -706,36 +794,36 @@ export const commands = [
|
|
|
706
794
|
const { setEnabled, loadExtensionsState } = await import('./extensions-state.js');
|
|
707
795
|
const name = options['name'];
|
|
708
796
|
if (!name) {
|
|
709
|
-
console.error('
|
|
797
|
+
console.error('Theme name is required (--name)');
|
|
710
798
|
process.exit(1);
|
|
711
799
|
}
|
|
712
800
|
if (options['uninstall'] !== undefined) {
|
|
713
801
|
const { uninstallExtension } = await import('./extensions-state.js');
|
|
714
802
|
const result = uninstallExtension('theme', name);
|
|
715
803
|
if (!result.removed) {
|
|
716
|
-
console.log(`Theme "${name}"
|
|
804
|
+
console.log(`Theme "${name}" was not installed.`);
|
|
717
805
|
process.exitCode = 1;
|
|
718
806
|
return;
|
|
719
807
|
}
|
|
720
|
-
console.log(`Theme "${name}"
|
|
808
|
+
console.log(`Theme "${name}" uninstalled (${result.targetDir}).`);
|
|
721
809
|
return;
|
|
722
810
|
}
|
|
723
811
|
if (options['set-active'] !== undefined) {
|
|
724
812
|
const configPath = join(process.cwd(), DEFAULT_CONFIG_FILENAME);
|
|
725
813
|
if (!existsSync(configPath)) {
|
|
726
|
-
console.error(`${DEFAULT_CONFIG_FILENAME}
|
|
814
|
+
console.error(`${DEFAULT_CONFIG_FILENAME} not found; run \`okcms init\` first.`);
|
|
727
815
|
process.exit(1);
|
|
728
816
|
}
|
|
729
817
|
const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
730
818
|
raw['activeTheme'] = name;
|
|
731
819
|
writeFileSync(configPath, JSON.stringify(raw, null, 2));
|
|
732
|
-
console.log(`
|
|
820
|
+
console.log(`Active theme set to "${name}".`);
|
|
733
821
|
return;
|
|
734
822
|
}
|
|
735
823
|
if (options['enable'] !== undefined || options['disable'] !== undefined) {
|
|
736
824
|
const enabled = options['enable'] !== undefined;
|
|
737
825
|
const ok = setEnabled('theme', name, enabled);
|
|
738
|
-
console.log(ok ? `
|
|
826
|
+
console.log(ok ? `Theme "${name}" ${enabled ? 'enabled' : 'disabled'}.` : `Theme "${name}" is not registered.`);
|
|
739
827
|
process.exitCode = ok ? 0 : 1;
|
|
740
828
|
return;
|
|
741
829
|
}
|
|
@@ -745,16 +833,16 @@ export const commands = [
|
|
|
745
833
|
const manifest = JSON.parse(readFileSync(themeJsonPath, 'utf-8'));
|
|
746
834
|
const provides = (manifest['provides'] ?? {});
|
|
747
835
|
const state = loadExtensionsState().themes[name];
|
|
748
|
-
console.log(`
|
|
749
|
-
console.log(`
|
|
750
|
-
console.log(`
|
|
836
|
+
console.log(`Name: ${manifest['name'] ?? name}`);
|
|
837
|
+
console.log(`Version: ${manifest['version'] ?? '?'}`);
|
|
838
|
+
console.log(`Author: ${manifest['author'] ?? '-'}`);
|
|
751
839
|
console.log(`Parent: ${manifest['parent'] ?? '-'}`);
|
|
752
840
|
console.log(`Layouts: ${provides['layouts']?.join(', ') ?? '-'}`);
|
|
753
|
-
console.log(`
|
|
754
|
-
console.log(`
|
|
841
|
+
console.log(`Active: ${config.activeTheme === name ? 'yes' : 'no'} (${config.activeTheme || 'none'})`);
|
|
842
|
+
console.log(`State: ${state?.enabled === false ? 'disabled' : 'enabled'}`);
|
|
755
843
|
}
|
|
756
844
|
catch {
|
|
757
|
-
console.error(`theme.json
|
|
845
|
+
console.error(`theme.json not found at ${themeJsonPath}`);
|
|
758
846
|
process.exit(1);
|
|
759
847
|
}
|
|
760
848
|
},
|
|
@@ -769,13 +857,13 @@ export const commands = [
|
|
|
769
857
|
handler: async (_args, options) => {
|
|
770
858
|
const from = options['from'] ?? 'local';
|
|
771
859
|
const to = options['to'] ?? 's3';
|
|
772
|
-
console.log(`
|
|
860
|
+
console.log(`Migrating media from "${from}" to "${to}"...`);
|
|
773
861
|
const { initDb } = await import('./db-init.js');
|
|
774
862
|
await initDb();
|
|
775
863
|
const { createMigrator } = await import('@oktis-works/core');
|
|
776
864
|
const migrator = createMigrator(from, to);
|
|
777
865
|
const result = await migrator.migrateAll();
|
|
778
|
-
console.log(`
|
|
866
|
+
console.log(`Migrated: ${result.migrated}, Failed: ${result.failed}`);
|
|
779
867
|
for (const err of result.errors) {
|
|
780
868
|
console.error(` ! ${err.filename}: ${err.error}`);
|
|
781
869
|
}
|
|
@@ -795,7 +883,7 @@ export const commands = [
|
|
|
795
883
|
// A política RBAC usa slugs em maiúsculas: `--role editor` → EDITOR.
|
|
796
884
|
const roleSlug = String(options['role'] ?? 'EDITOR').toUpperCase();
|
|
797
885
|
if (!VALID_ROLES.includes(roleSlug)) {
|
|
798
|
-
console.error(`
|
|
886
|
+
console.error(`Invalid role: ${options['role']} — use one of: ${VALID_ROLES.join(', ')}`);
|
|
799
887
|
process.exitCode = 1;
|
|
800
888
|
return;
|
|
801
889
|
}
|
|
@@ -809,7 +897,7 @@ export const commands = [
|
|
|
809
897
|
const email = String(options['email']);
|
|
810
898
|
const existing = await sql.unsafe('SELECT id FROM users WHERE email = $1', [email]);
|
|
811
899
|
if (existing.length > 0) {
|
|
812
|
-
console.error(`
|
|
900
|
+
console.error(`User already exists: ${email}`);
|
|
813
901
|
process.exitCode = 1;
|
|
814
902
|
return;
|
|
815
903
|
}
|
|
@@ -823,7 +911,7 @@ export const commands = [
|
|
|
823
911
|
ORDER BY tenant_id NULLS LAST
|
|
824
912
|
LIMIT 1`, [roleSlug, tenantId]);
|
|
825
913
|
if (roles.length === 0) {
|
|
826
|
-
console.error(`Role "${roleSlug}"
|
|
914
|
+
console.error(`Role "${roleSlug}" not found after seeding.`);
|
|
827
915
|
process.exitCode = 1;
|
|
828
916
|
return;
|
|
829
917
|
}
|
|
@@ -831,7 +919,7 @@ export const commands = [
|
|
|
831
919
|
VALUES ($1, $2, $3, 'ACTIVE')
|
|
832
920
|
ON CONFLICT (tenant_id, user_id)
|
|
833
921
|
DO UPDATE SET role_id = EXCLUDED.role_id, status = 'ACTIVE'`, [tenantId, userId, roles[0]['id']]);
|
|
834
|
-
console.log(`✓
|
|
922
|
+
console.log(`✓ user created: ${email} (role ${roleSlug})`);
|
|
835
923
|
},
|
|
836
924
|
},
|
|
837
925
|
{
|
|
@@ -843,10 +931,10 @@ export const commands = [
|
|
|
843
931
|
const { ensureCoreSchema, seedCoreData } = await import('@oktis-works/database');
|
|
844
932
|
const applied = await ensureCoreSchema();
|
|
845
933
|
if (applied) {
|
|
846
|
-
console.log('✓ schema
|
|
934
|
+
console.log('✓ core schema applied (database initialized)');
|
|
847
935
|
}
|
|
848
936
|
const { roles, settings } = await seedCoreData();
|
|
849
|
-
console.log(`✓ seed
|
|
937
|
+
console.log(`✓ seed completed: ${roles} roles, ${settings} settings created`);
|
|
850
938
|
},
|
|
851
939
|
},
|
|
852
940
|
{
|
|
@@ -866,11 +954,11 @@ export const commands = [
|
|
|
866
954
|
},
|
|
867
955
|
{
|
|
868
956
|
name: 'rollback',
|
|
869
|
-
description: 'Rollback
|
|
957
|
+
description: 'Rollback to a previous state (lists history and lets you choose)',
|
|
870
958
|
options: [
|
|
871
|
-
{ name: 'id', alias: 'i', description: 'ID
|
|
872
|
-
{ name: 'yes', alias: 'y', description: '
|
|
873
|
-
{ name: 'force', alias: 'F', description: '
|
|
959
|
+
{ name: 'id', alias: 'i', description: 'History ID for direct rollback (no menu)', required: false },
|
|
960
|
+
{ name: 'yes', alias: 'y', description: 'Confirm without prompt', required: false },
|
|
961
|
+
{ name: 'force', alias: 'F', description: 'Allow running inside a container (not recommended)', required: false },
|
|
874
962
|
],
|
|
875
963
|
handler: async (_args, options) => {
|
|
876
964
|
const { runRollback } = await import('./rollback.js');
|
|
@@ -885,13 +973,22 @@ export const commands = [
|
|
|
885
973
|
},
|
|
886
974
|
{
|
|
887
975
|
name: 'deploy',
|
|
888
|
-
description: '
|
|
976
|
+
description: 'First deploy — pick a target: blue/green lanes, simple containers or PM2',
|
|
889
977
|
options: [
|
|
890
|
-
{
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
978
|
+
{
|
|
979
|
+
name: 'target',
|
|
980
|
+
alias: 't',
|
|
981
|
+
description: 'Skip the menu: blue-green | simple | pm2',
|
|
982
|
+
required: false,
|
|
983
|
+
},
|
|
984
|
+
{ name: 'yes', alias: 'y', description: 'No prompts: take every default', required: false },
|
|
985
|
+
{
|
|
986
|
+
name: 'force',
|
|
987
|
+
alias: 'F',
|
|
988
|
+
description: 'Allow running inside a container (not recommended)',
|
|
989
|
+
required: false,
|
|
990
|
+
},
|
|
991
|
+
{ name: 'install', alias: 'i', description: 'PM2: update packages before deploying', required: false },
|
|
895
992
|
],
|
|
896
993
|
handler: async (_args, options) => {
|
|
897
994
|
const { runDeploy } = await import('./deploy.js');
|
|
@@ -899,7 +996,6 @@ export const commands = [
|
|
|
899
996
|
target: options['target'],
|
|
900
997
|
yes: options['yes'] !== undefined,
|
|
901
998
|
force: options['force'] !== undefined,
|
|
902
|
-
noCache: options['no-cache'] !== undefined,
|
|
903
999
|
install: options['install'] !== undefined,
|
|
904
1000
|
});
|
|
905
1001
|
if (code !== 0)
|