@neetru/cli 2.1.1 → 2.3.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/README.md +40 -2
- package/dist/commands/ai.js +82 -10
- package/dist/commands/ai.js.map +1 -1
- package/dist/commands/auth.d.ts +19 -0
- package/dist/commands/auth.js +203 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/new.d.ts +12 -0
- package/dist/commands/new.js +163 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/products.d.ts +31 -0
- package/dist/commands/products.js +190 -0
- package/dist/commands/products.js.map +1 -1
- package/dist/commands/upgrade.js +1 -1
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/workspaces.d.ts +22 -0
- package/dist/commands/workspaces.js +146 -2
- package/dist/commands/workspaces.js.map +1 -1
- package/dist/index.js +210 -101
- package/dist/index.js.map +1 -1
- package/dist/lib/ai/auth-discovery.d.ts +26 -0
- package/dist/lib/ai/auth-discovery.js +256 -0
- package/dist/lib/ai/auth-discovery.js.map +1 -0
- package/dist/lib/ai/orchestrator.d.ts +25 -0
- package/dist/lib/ai/orchestrator.js +167 -28
- package/dist/lib/ai/orchestrator.js.map +1 -1
- package/dist/lib/config-schema.d.ts +2 -2
- package/dist/version.d.ts +1 -0
- package/dist/version.js +24 -0
- package/dist/version.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `neetru new <name>` — macro end-to-end pra criar um produto + workspace +
|
|
3
|
+
* scaffold local + abrir o painel. Cinco linhas de output, zero prompt se
|
|
4
|
+
* todas as flags vierem.
|
|
5
|
+
*
|
|
6
|
+
* Orquestra:
|
|
7
|
+
* 1. runProductsCreate({ name, slug, ...defaults }) — registra no Core
|
|
8
|
+
* 2. runWorkspacesCreate({ product, customer, env, tier }) — provisiona
|
|
9
|
+
* 3. runInit({ name, type: 'nextjs', here: false, yes: true }) — scaffold
|
|
10
|
+
* 4. openBrowser(`/workspaces/{id}`) — UX win
|
|
11
|
+
* 5. resumo
|
|
12
|
+
*
|
|
13
|
+
* Erro em qualquer passo: mostra exatamente onde + sugere o comando manual
|
|
14
|
+
* pra continuar. Não tenta rollback (decisão: prefere idempotência humana
|
|
15
|
+
* sobre auto-undo silencioso).
|
|
16
|
+
*/
|
|
17
|
+
import chalk from 'chalk';
|
|
18
|
+
import { log } from '../utils/logger.js';
|
|
19
|
+
import { runProductsCreate, deriveSlug, } from './products.js';
|
|
20
|
+
import { runWorkspacesCreate, buildWorkspaceDashboardUrl, openBrowser, } from './workspaces.js';
|
|
21
|
+
import { runInit } from './init.js';
|
|
22
|
+
/**
|
|
23
|
+
* Captura erro de um passo do macro como mensagem human-readable + uma
|
|
24
|
+
* sugestão de comando pra continuar manualmente. O process.exit() interno
|
|
25
|
+
* do helper é convertido via try/catch — preferimos relatar e re-lançar
|
|
26
|
+
* (caller decide o exit).
|
|
27
|
+
*/
|
|
28
|
+
async function step(name, hint, fn) {
|
|
29
|
+
try {
|
|
30
|
+
const data = await fn();
|
|
31
|
+
return { ok: true, data };
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
35
|
+
return { ok: false, error, hint };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export async function runNewMacro(name, opts = {}) {
|
|
39
|
+
if (!name || !name.trim()) {
|
|
40
|
+
log.error('Uso: neetru new <name>');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
const slug = (opts.productSlug ?? deriveSlug(name)) || deriveSlug(name);
|
|
44
|
+
const env = opts.env ?? 'dev';
|
|
45
|
+
const tier = opts.tier ?? 'standard';
|
|
46
|
+
const customer = opts.customer ?? 'self';
|
|
47
|
+
if (!opts.json) {
|
|
48
|
+
log.banner();
|
|
49
|
+
log.heading(`neetru new ${name}`);
|
|
50
|
+
log.dim(` slug=${slug} · env=${env} · tier=${tier}`);
|
|
51
|
+
console.log();
|
|
52
|
+
}
|
|
53
|
+
const summary = [];
|
|
54
|
+
// ─── Step 1 — Criar produto ──────────────────────────────────────────────
|
|
55
|
+
const s1 = await step('products.create', `neetru products create --name "${name}" --slug ${slug} --yes`, () => runProductsCreate({
|
|
56
|
+
name,
|
|
57
|
+
slug,
|
|
58
|
+
yes: true,
|
|
59
|
+
json: true, // força non-interactive sem prints duplicados
|
|
60
|
+
}));
|
|
61
|
+
if (!s1.ok) {
|
|
62
|
+
log.error(`[1/4] products.create falhou: ${s1.error}`);
|
|
63
|
+
log.dim(` Tente manualmente: ${chalk.cyan(s1.hint)}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
const product = s1.data;
|
|
67
|
+
if (!opts.json)
|
|
68
|
+
log.success(`[1/4] Produto criado: ${product.productId} (${product.slug})`);
|
|
69
|
+
summary.push({ step: 'products.create', ok: true, data: product });
|
|
70
|
+
// ─── Step 2 — Criar workspace ────────────────────────────────────────────
|
|
71
|
+
const s2 = await step('workspaces.create', `neetru workspaces create --product ${product.productId} --customer ${customer} --env ${env} --tier ${tier}`, () => runWorkspacesCreate({
|
|
72
|
+
product: product.productId,
|
|
73
|
+
customer,
|
|
74
|
+
env,
|
|
75
|
+
tier,
|
|
76
|
+
json: true,
|
|
77
|
+
}));
|
|
78
|
+
if (!s2.ok) {
|
|
79
|
+
log.error(`[2/4] workspaces.create falhou: ${s2.error}`);
|
|
80
|
+
log.dim(` Produto ${chalk.cyan(product.productId)} já foi criado — recupere com:`);
|
|
81
|
+
log.dim(` ${chalk.cyan(s2.hint)}`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
// runWorkspacesCreate hoje escreve direto no stdout em modo json — pegar id
|
|
85
|
+
// do output é frágil. Pegamos o ID por re-fetch via list filtrado, mas pra
|
|
86
|
+
// não duplicar chamada aqui assumimos que o printJSON da própria função
|
|
87
|
+
// bastou. O macro segue mesmo sem ID em mãos, e usa o slug como fallback
|
|
88
|
+
// pra construção da URL final (servidor aceita ambos).
|
|
89
|
+
const workspaceId = s2.data?.id ?? product.productId;
|
|
90
|
+
if (!opts.json)
|
|
91
|
+
log.success(`[2/4] Workspace criado: ${workspaceId}`);
|
|
92
|
+
summary.push({ step: 'workspaces.create', ok: true, data: { workspaceId } });
|
|
93
|
+
// ─── Step 3 — Scaffold local ─────────────────────────────────────────────
|
|
94
|
+
if (!opts.skipInit) {
|
|
95
|
+
const s3 = await step('init.scaffold', `neetru init ${name} --yes`, () => runInit({
|
|
96
|
+
name,
|
|
97
|
+
type: 'nextjs',
|
|
98
|
+
here: false,
|
|
99
|
+
force: false,
|
|
100
|
+
yes: true,
|
|
101
|
+
}));
|
|
102
|
+
if (!s3.ok) {
|
|
103
|
+
log.error(`[3/4] init.scaffold falhou: ${s3.error}`);
|
|
104
|
+
log.dim(` Produto + workspace OK. Rode manualmente:`);
|
|
105
|
+
log.dim(` ${chalk.cyan(s3.hint)}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
if (!opts.json)
|
|
109
|
+
log.success(`[3/4] Scaffold local em ./${name}/`);
|
|
110
|
+
summary.push({ step: 'init.scaffold', ok: true });
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
if (!opts.json)
|
|
114
|
+
log.dim('[3/4] Scaffold local pulado (--skip-init).');
|
|
115
|
+
summary.push({ step: 'init.scaffold', ok: true, data: { skipped: true } });
|
|
116
|
+
}
|
|
117
|
+
// ─── Step 4 — Abrir browser ──────────────────────────────────────────────
|
|
118
|
+
const dashboardUrl = buildWorkspaceDashboardUrl(workspaceId);
|
|
119
|
+
if (!opts.skipOpen) {
|
|
120
|
+
try {
|
|
121
|
+
openBrowser(dashboardUrl);
|
|
122
|
+
if (!opts.json)
|
|
123
|
+
log.success(`[4/4] Browser aberto: ${dashboardUrl}`);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
127
|
+
if (!opts.json) {
|
|
128
|
+
log.warn(`[4/4] Abertura do browser falhou: ${error}`);
|
|
129
|
+
log.dim(` Acesse manualmente: ${chalk.blue(dashboardUrl)}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
summary.push({ step: 'browser.open', ok: true, data: { url: dashboardUrl } });
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
if (!opts.json)
|
|
136
|
+
log.dim(`[4/4] Browser pulado (--skip-open). URL: ${dashboardUrl}`);
|
|
137
|
+
summary.push({ step: 'browser.open', ok: true, data: { skipped: true, url: dashboardUrl } });
|
|
138
|
+
}
|
|
139
|
+
// ─── Resumo ──────────────────────────────────────────────────────────────
|
|
140
|
+
if (opts.json) {
|
|
141
|
+
console.log(JSON.stringify({
|
|
142
|
+
ok: true,
|
|
143
|
+
product,
|
|
144
|
+
workspaceId,
|
|
145
|
+
dashboardUrl,
|
|
146
|
+
steps: summary,
|
|
147
|
+
}));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
console.log();
|
|
151
|
+
log.heading('Tudo pronto!');
|
|
152
|
+
log.info(`Produto: ${chalk.cyan(product.slug)} (${product.productId})`);
|
|
153
|
+
log.info(`Workspace: ${chalk.cyan(workspaceId)} · env=${env} · tier=${tier}`);
|
|
154
|
+
if (!opts.skipInit)
|
|
155
|
+
log.info(`Local: ./${name}/`);
|
|
156
|
+
log.info(`Painel: ${chalk.blue(dashboardUrl)}`);
|
|
157
|
+
console.log();
|
|
158
|
+
log.dim('Próximos passos:');
|
|
159
|
+
if (!opts.skipInit)
|
|
160
|
+
log.dim(` cd ${name} && npm install && npm run dev`);
|
|
161
|
+
log.dim(` neetru workspaces get ${workspaceId}`);
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=new.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,3 +10,34 @@ export declare function runProductsPublish(slug: string, opts: {
|
|
|
10
10
|
export declare function runProductsUnpublish(slug: string, opts: {
|
|
11
11
|
json?: boolean;
|
|
12
12
|
}): Promise<void>;
|
|
13
|
+
export type ProductPlanTemplate = 'free' | 'starter' | 'pro';
|
|
14
|
+
export interface ProductsCreateOptions {
|
|
15
|
+
name?: string;
|
|
16
|
+
slug?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
ownerTeam?: string;
|
|
19
|
+
planTemplate?: string;
|
|
20
|
+
/** CSV de envs (ex: "dev,prod"). */
|
|
21
|
+
env?: string;
|
|
22
|
+
/** Pula prompts — exige pelo menos `name`. */
|
|
23
|
+
yes?: boolean;
|
|
24
|
+
json?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface ProductCreatedResult {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
productId: string;
|
|
29
|
+
slug: string;
|
|
30
|
+
name: string;
|
|
31
|
+
ownerTeam: string;
|
|
32
|
+
planTemplate: ProductPlanTemplate;
|
|
33
|
+
environments: string[];
|
|
34
|
+
createdAt: string | number | null;
|
|
35
|
+
dashboardUrl: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Deriva um slug `kebab-case` a partir do `name`. Mantém apenas [a-z0-9-]
|
|
39
|
+
* + colapsa hífens + corta hífens nas pontas. Não verifica unicidade — isso é
|
|
40
|
+
* responsabilidade do servidor.
|
|
41
|
+
*/
|
|
42
|
+
export declare function deriveSlug(name: string): string;
|
|
43
|
+
export declare function runProductsCreate(opts: ProductsCreateOptions): Promise<ProductCreatedResult | void>;
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
* Saída: tabela (default) ou `--json`.
|
|
10
10
|
*/
|
|
11
11
|
import chalk from 'chalk';
|
|
12
|
+
import inquirer from 'inquirer';
|
|
12
13
|
import ora from 'ora';
|
|
13
14
|
import { apiRequest } from '../lib/api-client.js';
|
|
15
|
+
import { config } from '../lib/config.js';
|
|
14
16
|
import { requireToken, handleApiError } from '../lib/cli-read.js';
|
|
15
17
|
import { printWriteResult } from '../lib/cli-write.js';
|
|
16
18
|
import { renderTable } from '../lib/render.js';
|
|
@@ -94,4 +96,192 @@ export async function runProductsPublish(slug, opts) {
|
|
|
94
96
|
export async function runProductsUnpublish(slug, opts) {
|
|
95
97
|
return runProductsPublishToggle(slug, false, opts);
|
|
96
98
|
}
|
|
99
|
+
const VALID_PLAN_TEMPLATES = ['free', 'starter', 'pro'];
|
|
100
|
+
/**
|
|
101
|
+
* Deriva um slug `kebab-case` a partir do `name`. Mantém apenas [a-z0-9-]
|
|
102
|
+
* + colapsa hífens + corta hífens nas pontas. Não verifica unicidade — isso é
|
|
103
|
+
* responsabilidade do servidor.
|
|
104
|
+
*/
|
|
105
|
+
export function deriveSlug(name) {
|
|
106
|
+
return name
|
|
107
|
+
.trim()
|
|
108
|
+
.toLowerCase()
|
|
109
|
+
.normalize('NFD')
|
|
110
|
+
.replace(/\p{Diacritic}/gu, '') // remove acentos (NFD + Unicode property)
|
|
111
|
+
.replace(/[^a-z0-9-]+/g, '-')
|
|
112
|
+
.replace(/-+/g, '-')
|
|
113
|
+
.replace(/^-|-$/g, '');
|
|
114
|
+
}
|
|
115
|
+
function parseEnvCsv(value, fallback) {
|
|
116
|
+
if (!value)
|
|
117
|
+
return fallback;
|
|
118
|
+
const parts = value
|
|
119
|
+
.split(',')
|
|
120
|
+
.map((s) => s.trim().toLowerCase())
|
|
121
|
+
.filter((s) => s.length > 0);
|
|
122
|
+
return parts.length > 0 ? parts : fallback;
|
|
123
|
+
}
|
|
124
|
+
function buildDashboardUrl(productId) {
|
|
125
|
+
const baseUrl = String(config.get('neetruCoreUrl') ?? 'https://core.neetru.com').replace(/\/+$/, '');
|
|
126
|
+
return `${baseUrl}/products/${encodeURIComponent(productId)}`;
|
|
127
|
+
}
|
|
128
|
+
export async function runProductsCreate(opts) {
|
|
129
|
+
const token = await requireToken(opts.json);
|
|
130
|
+
// Resolve campos — interativo ou non-interactive.
|
|
131
|
+
let name = opts.name?.trim() ?? '';
|
|
132
|
+
let slug = opts.slug?.trim() ?? '';
|
|
133
|
+
let description = opts.description ?? '';
|
|
134
|
+
let ownerTeam = opts.ownerTeam?.trim() || 'neetru-eng';
|
|
135
|
+
let planTemplate = (opts.planTemplate ?? 'free').toLowerCase();
|
|
136
|
+
let environments = parseEnvCsv(opts.env, ['dev', 'prod']);
|
|
137
|
+
const interactive = !opts.yes && !opts.json && process.stdin.isTTY;
|
|
138
|
+
if (interactive) {
|
|
139
|
+
const answers = await inquirer.prompt([
|
|
140
|
+
{
|
|
141
|
+
type: 'input',
|
|
142
|
+
name: 'name',
|
|
143
|
+
message: 'Nome do produto:',
|
|
144
|
+
when: () => !name,
|
|
145
|
+
validate: (v) => (v && v.trim().length > 0 ? true : 'Obrigatório.'),
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: 'input',
|
|
149
|
+
name: 'slug',
|
|
150
|
+
message: 'Slug (kebab-case):',
|
|
151
|
+
when: () => !slug,
|
|
152
|
+
default: () => deriveSlug(name || ''),
|
|
153
|
+
validate: (v) => /^[a-z0-9-]+$/.test(v) ? true : 'Apenas [a-z0-9-].',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'input',
|
|
157
|
+
name: 'description',
|
|
158
|
+
message: 'Descrição (opcional):',
|
|
159
|
+
when: () => !description,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
type: 'input',
|
|
163
|
+
name: 'ownerTeam',
|
|
164
|
+
message: 'Time dono:',
|
|
165
|
+
when: () => !opts.ownerTeam,
|
|
166
|
+
default: 'neetru-eng',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
type: 'list',
|
|
170
|
+
name: 'planTemplate',
|
|
171
|
+
message: 'Plano template:',
|
|
172
|
+
when: () => !opts.planTemplate,
|
|
173
|
+
choices: VALID_PLAN_TEMPLATES,
|
|
174
|
+
default: 'free',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
type: 'input',
|
|
178
|
+
name: 'env',
|
|
179
|
+
message: 'Ambientes (csv):',
|
|
180
|
+
when: () => !opts.env,
|
|
181
|
+
default: environments.join(','),
|
|
182
|
+
},
|
|
183
|
+
]);
|
|
184
|
+
if (answers.name)
|
|
185
|
+
name = answers.name.trim();
|
|
186
|
+
if (answers.slug)
|
|
187
|
+
slug = answers.slug.trim();
|
|
188
|
+
if (answers.description !== undefined)
|
|
189
|
+
description = answers.description;
|
|
190
|
+
if (answers.ownerTeam)
|
|
191
|
+
ownerTeam = answers.ownerTeam.trim();
|
|
192
|
+
if (answers.planTemplate)
|
|
193
|
+
planTemplate = answers.planTemplate;
|
|
194
|
+
if (answers.env)
|
|
195
|
+
environments = parseEnvCsv(answers.env, environments);
|
|
196
|
+
}
|
|
197
|
+
// Validação final
|
|
198
|
+
if (!name) {
|
|
199
|
+
const msg = '--name é obrigatório (ou execute em modo interativo).';
|
|
200
|
+
if (opts.json) {
|
|
201
|
+
console.log(JSON.stringify({ ok: false, error: 'invalid_input', message: msg }));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
log.error(msg);
|
|
205
|
+
}
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
if (!slug)
|
|
209
|
+
slug = deriveSlug(name);
|
|
210
|
+
if (!slug) {
|
|
211
|
+
const msg = `Slug derivado de "${name}" ficou vazio — informe --slug.`;
|
|
212
|
+
if (opts.json) {
|
|
213
|
+
console.log(JSON.stringify({ ok: false, error: 'invalid_input', message: msg }));
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
log.error(msg);
|
|
217
|
+
}
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
if (!VALID_PLAN_TEMPLATES.includes(planTemplate)) {
|
|
221
|
+
const msg = `--plan-template inválido: ${planTemplate} (use ${VALID_PLAN_TEMPLATES.join('|')}).`;
|
|
222
|
+
if (opts.json) {
|
|
223
|
+
console.log(JSON.stringify({ ok: false, error: 'invalid_input', message: msg }));
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
log.error(msg);
|
|
227
|
+
}
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
const spinner = opts.json
|
|
231
|
+
? null
|
|
232
|
+
: ora({ text: `Criando produto "${name}"…`, color: 'blue' }).start();
|
|
233
|
+
let res;
|
|
234
|
+
try {
|
|
235
|
+
res = await apiRequest('/api/cli/v1/products', {
|
|
236
|
+
method: 'POST',
|
|
237
|
+
token,
|
|
238
|
+
body: {
|
|
239
|
+
name,
|
|
240
|
+
slug,
|
|
241
|
+
description: description || undefined,
|
|
242
|
+
ownerTeam,
|
|
243
|
+
planTemplate,
|
|
244
|
+
environments,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
spinner?.stop();
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
spinner?.fail('Falha ao criar produto.');
|
|
251
|
+
handleApiError(error, opts.json);
|
|
252
|
+
}
|
|
253
|
+
const productId = res.productId ?? res.id ?? slug;
|
|
254
|
+
const result = {
|
|
255
|
+
ok: true,
|
|
256
|
+
productId,
|
|
257
|
+
slug: res.slug ?? slug,
|
|
258
|
+
name: res.name ?? name,
|
|
259
|
+
ownerTeam: res.ownerTeam ?? ownerTeam,
|
|
260
|
+
planTemplate: res.planTemplate ?? planTemplate,
|
|
261
|
+
environments: res.environments ?? environments,
|
|
262
|
+
createdAt: res.createdAt ?? null,
|
|
263
|
+
dashboardUrl: buildDashboardUrl(productId),
|
|
264
|
+
};
|
|
265
|
+
if (opts.json) {
|
|
266
|
+
console.log(JSON.stringify(result));
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
log.heading('Produto criado');
|
|
270
|
+
renderTable([
|
|
271
|
+
{ header: 'CAMPO', value: (r) => r.k, maxWidth: 18 },
|
|
272
|
+
{ header: 'VALOR', value: (r) => r.v, maxWidth: 60 },
|
|
273
|
+
], [
|
|
274
|
+
{ k: 'productId', v: result.productId },
|
|
275
|
+
{ k: 'slug', v: chalk.cyan(result.slug) },
|
|
276
|
+
{ k: 'name', v: result.name },
|
|
277
|
+
{ k: 'ownerTeam', v: result.ownerTeam },
|
|
278
|
+
{ k: 'planTemplate', v: chalk.yellow(result.planTemplate) },
|
|
279
|
+
{ k: 'environments', v: result.environments.join(', ') },
|
|
280
|
+
{ k: 'createdAt', v: result.createdAt ? String(result.createdAt) : '—' },
|
|
281
|
+
{ k: 'dashboardUrl', v: chalk.blue(result.dashboardUrl) },
|
|
282
|
+
]);
|
|
283
|
+
console.log();
|
|
284
|
+
log.dim(`Abra no painel: neetru workspaces open ${result.productId}`);
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
97
287
|
//# sourceMappingURL=products.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/commands/products.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/commands/products.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* confirme. Auto-install pode quebrar pipelines CI/CD que pinaram versão.
|
|
13
13
|
*/
|
|
14
14
|
import chalk from 'chalk';
|
|
15
|
-
|
|
15
|
+
import { CLI_VERSION } from '../version.js';
|
|
16
16
|
const NPM_REGISTRY = 'https://registry.npmjs.org/@neetru/cli';
|
|
17
17
|
export async function fetchLatest(fetchImpl = fetch) {
|
|
18
18
|
const ctrl = new AbortController();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,3 +13,25 @@ export interface WorkspacesAdvanceOptions {
|
|
|
13
13
|
json?: boolean;
|
|
14
14
|
}
|
|
15
15
|
export declare function runWorkspacesAdvance(id: string, opts: WorkspacesAdvanceOptions): Promise<void>;
|
|
16
|
+
export interface WorkspacesListOptions {
|
|
17
|
+
product?: string;
|
|
18
|
+
env?: string;
|
|
19
|
+
status?: string;
|
|
20
|
+
json?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function runWorkspacesList(opts: WorkspacesListOptions): Promise<void>;
|
|
23
|
+
export interface WorkspacesGetOptions {
|
|
24
|
+
json?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function runWorkspacesGet(id: string, opts: WorkspacesGetOptions): Promise<void>;
|
|
27
|
+
export interface WorkspacesOpenOptions {
|
|
28
|
+
/** Pula a abertura real do browser (útil pra testes/CI). */
|
|
29
|
+
printOnly?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function buildWorkspaceDashboardUrl(id: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Abre uma URL no browser default do OS. Não bloqueia o processo.
|
|
34
|
+
* Em caso de erro, só loga warn — o caller pode copiar a URL printada.
|
|
35
|
+
*/
|
|
36
|
+
export declare function openBrowser(url: string): void;
|
|
37
|
+
export declare function runWorkspacesOpen(id: string, opts?: WorkspacesOpenOptions): Promise<void>;
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `neetru workspaces create|advance` — control plane de
|
|
3
|
-
* shared `neetru-workspaces`).
|
|
2
|
+
* `neetru workspaces create|advance|list|get|open` — control plane de
|
|
3
|
+
* workspaces (runtime shared `neetru-workspaces`).
|
|
4
4
|
*
|
|
5
5
|
* Endpoints:
|
|
6
6
|
* POST /api/cli/v1/workspaces (create)
|
|
7
7
|
* POST /api/cli/v1/workspaces/{id}/advance (advance — promove bundle)
|
|
8
|
+
* GET /api/cli/v1/workspaces (list — filtros productId/env/status)
|
|
9
|
+
* GET /api/cli/v1/workspaces/{id} (get)
|
|
10
|
+
* (open) NÃO chama API — só monta a URL do painel e abre o browser.
|
|
8
11
|
*/
|
|
12
|
+
import { spawn } from 'node:child_process';
|
|
9
13
|
import chalk from 'chalk';
|
|
10
14
|
import ora from 'ora';
|
|
11
15
|
import { apiRequest } from '../lib/api-client.js';
|
|
16
|
+
import { config } from '../lib/config.js';
|
|
12
17
|
import { requireToken, handleApiError, printWriteResult } from '../lib/cli-write.js';
|
|
18
|
+
import { renderTable, fmtTimestamp } from '../lib/render.js';
|
|
13
19
|
import { log } from '../utils/logger.js';
|
|
14
20
|
export async function runWorkspacesCreate(opts) {
|
|
15
21
|
const token = await requireToken(opts.json);
|
|
@@ -69,4 +75,142 @@ export async function runWorkspacesAdvance(id, opts) {
|
|
|
69
75
|
}
|
|
70
76
|
printWriteResult({ tenantId: res.tenantId, version: res.version, runtimeStatus: res.runtimeStatus }, `Workspace ${res.tenantId} → ${res.version} (${res.runtimeStatus})`, opts.json);
|
|
71
77
|
}
|
|
78
|
+
function colorStatus(s) {
|
|
79
|
+
if (!s)
|
|
80
|
+
return chalk.dim('—');
|
|
81
|
+
if (s === 'active' || s === 'ativo' || s === 'running')
|
|
82
|
+
return chalk.green(s);
|
|
83
|
+
if (s === 'paused' || s === 'suspended')
|
|
84
|
+
return chalk.yellow(s);
|
|
85
|
+
if (s === 'provisioning' || s === 'pending')
|
|
86
|
+
return chalk.cyan(s);
|
|
87
|
+
if (s === 'failed' || s === 'error')
|
|
88
|
+
return chalk.red(s);
|
|
89
|
+
return s;
|
|
90
|
+
}
|
|
91
|
+
export async function runWorkspacesList(opts) {
|
|
92
|
+
const token = await requireToken(opts.json);
|
|
93
|
+
const params = new URLSearchParams();
|
|
94
|
+
if (opts.product)
|
|
95
|
+
params.set('productId', opts.product);
|
|
96
|
+
if (opts.env)
|
|
97
|
+
params.set('env', opts.env);
|
|
98
|
+
if (opts.status)
|
|
99
|
+
params.set('status', opts.status);
|
|
100
|
+
const qs = params.toString();
|
|
101
|
+
const spinner = opts.json
|
|
102
|
+
? null
|
|
103
|
+
: ora({ text: 'Buscando workspaces…', color: 'blue' }).start();
|
|
104
|
+
let res;
|
|
105
|
+
try {
|
|
106
|
+
res = await apiRequest(`/api/cli/v1/workspaces${qs ? `?${qs}` : ''}`, { token });
|
|
107
|
+
spinner?.stop();
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
spinner?.fail('Falha ao buscar workspaces.');
|
|
111
|
+
handleApiError(error, opts.json);
|
|
112
|
+
}
|
|
113
|
+
if (opts.json) {
|
|
114
|
+
console.log(JSON.stringify(res));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
log.heading(`Workspaces (${res.count})`);
|
|
118
|
+
renderTable([
|
|
119
|
+
{ header: 'ID', value: (r) => r.id ?? r.workspaceId ?? '—', maxWidth: 24 },
|
|
120
|
+
{ header: 'PRODUTO', value: (r) => r.productSlug ?? r.productId ?? '—', maxWidth: 22 },
|
|
121
|
+
{ header: 'ENV', value: (r) => r.env ?? r.environmentId ?? '—', maxWidth: 10 },
|
|
122
|
+
{ header: 'TIER', value: (r) => r.tier ?? r.resourceTier ?? '—', maxWidth: 12 },
|
|
123
|
+
{ header: 'STATUS', value: (r) => colorStatus(r.status), maxWidth: 16 },
|
|
124
|
+
{ header: 'CRIADO', value: (r) => fmtTimestamp(r.createdAt) },
|
|
125
|
+
], res.workspaces);
|
|
126
|
+
console.log();
|
|
127
|
+
}
|
|
128
|
+
export async function runWorkspacesGet(id, opts) {
|
|
129
|
+
if (!id) {
|
|
130
|
+
log.error('Uso: neetru workspaces get <workspaceId>');
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
const token = await requireToken(opts.json);
|
|
134
|
+
const spinner = opts.json
|
|
135
|
+
? null
|
|
136
|
+
: ora({ text: `Buscando workspace ${id}…`, color: 'blue' }).start();
|
|
137
|
+
let res;
|
|
138
|
+
try {
|
|
139
|
+
res = await apiRequest(`/api/cli/v1/workspaces/${encodeURIComponent(id)}`, { token });
|
|
140
|
+
spinner?.stop();
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
spinner?.fail('Falha ao buscar workspace.');
|
|
144
|
+
handleApiError(error, opts.json);
|
|
145
|
+
}
|
|
146
|
+
if (opts.json) {
|
|
147
|
+
console.log(JSON.stringify(res));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const w = res.workspace ?? {};
|
|
151
|
+
const endpoints = (w.endpoints ?? []).map((e) => e?.url ?? '—').filter(Boolean);
|
|
152
|
+
const domains = [w.primaryDomain, w.temporaryDomain].filter(Boolean);
|
|
153
|
+
log.heading(`Workspace ${w.id ?? w.workspaceId ?? id}`);
|
|
154
|
+
renderTable([
|
|
155
|
+
{ header: 'CAMPO', value: (r) => r.k, maxWidth: 20 },
|
|
156
|
+
{ header: 'VALOR', value: (r) => r.v, maxWidth: 70 },
|
|
157
|
+
], [
|
|
158
|
+
{ k: 'id', v: w.id ?? w.workspaceId ?? id },
|
|
159
|
+
{ k: 'produto', v: w.productSlug ?? w.productId ?? '—' },
|
|
160
|
+
{ k: 'env', v: w.env ?? w.environmentId ?? '—' },
|
|
161
|
+
{ k: 'tier', v: w.tier ?? w.resourceTier ?? '—' },
|
|
162
|
+
{ k: 'status', v: colorStatus(w.status) },
|
|
163
|
+
{ k: 'domínios', v: domains.length > 0 ? domains.join(', ') : '—' },
|
|
164
|
+
{ k: 'endpoints', v: endpoints.length > 0 ? endpoints.join(', ') : '—' },
|
|
165
|
+
{ k: 'lastDeployedAt', v: fmtTimestamp(w.lastDeployedAt) },
|
|
166
|
+
{ k: 'lastBundleId', v: w.lastBundleId ?? '—' },
|
|
167
|
+
{ k: 'oauthClientId', v: w.oauthClientId ?? '—' },
|
|
168
|
+
{
|
|
169
|
+
k: 'secrets',
|
|
170
|
+
v: w.secretsRefs && w.secretsRefs.length > 0
|
|
171
|
+
? `${w.secretsRefs.length} ref(s): ${w.secretsRefs.join(', ')} ${chalk.dim('(valores nunca expostos via CLI)')}`
|
|
172
|
+
: '—',
|
|
173
|
+
},
|
|
174
|
+
{ k: 'createdAt', v: fmtTimestamp(w.createdAt) },
|
|
175
|
+
]);
|
|
176
|
+
console.log();
|
|
177
|
+
}
|
|
178
|
+
export function buildWorkspaceDashboardUrl(id) {
|
|
179
|
+
const baseUrl = String(config.get('neetruCoreUrl') ?? 'https://core.neetru.com').replace(/\/+$/, '');
|
|
180
|
+
return `${baseUrl}/workspaces/${encodeURIComponent(id)}`;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Abre uma URL no browser default do OS. Não bloqueia o processo.
|
|
184
|
+
* Em caso de erro, só loga warn — o caller pode copiar a URL printada.
|
|
185
|
+
*/
|
|
186
|
+
export function openBrowser(url) {
|
|
187
|
+
try {
|
|
188
|
+
if (process.platform === 'win32') {
|
|
189
|
+
spawn('cmd', ['/c', 'start', '""', url], {
|
|
190
|
+
detached: true,
|
|
191
|
+
stdio: 'ignore',
|
|
192
|
+
windowsHide: true,
|
|
193
|
+
}).unref();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (process.platform === 'darwin') {
|
|
197
|
+
spawn('open', [url], { detached: true, stdio: 'ignore' }).unref();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
spawn('xdg-open', [url], { detached: true, stdio: 'ignore' }).unref();
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
log.warn(`Não consegui abrir browser. Acesse manualmente: ${url}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
export async function runWorkspacesOpen(id, opts = {}) {
|
|
207
|
+
if (!id) {
|
|
208
|
+
log.error('Uso: neetru workspaces open <workspaceId>');
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
const url = buildWorkspaceDashboardUrl(id);
|
|
212
|
+
console.log(chalk.dim(`Abrindo ${url}…`));
|
|
213
|
+
if (!opts.printOnly)
|
|
214
|
+
openBrowser(url);
|
|
215
|
+
}
|
|
72
216
|
//# sourceMappingURL=workspaces.js.map
|