@neetru/cli 1.0.1 → 2.0.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +136 -0
  2. package/README.md +109 -152
  3. package/dist/commands/add.d.ts +8 -3
  4. package/dist/commands/add.js +70 -143
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/commands/ai.d.ts +4 -0
  7. package/dist/commands/ai.js +88 -0
  8. package/dist/commands/ai.js.map +1 -0
  9. package/dist/commands/autocomplete.d.ts +7 -0
  10. package/dist/commands/autocomplete.js +107 -0
  11. package/dist/commands/autocomplete.js.map +1 -0
  12. package/dist/commands/build.d.ts +18 -0
  13. package/dist/commands/build.js +288 -0
  14. package/dist/commands/build.js.map +1 -0
  15. package/dist/commands/config.d.ts +3 -0
  16. package/dist/commands/config.js +70 -0
  17. package/dist/commands/config.js.map +1 -0
  18. package/dist/commands/db.d.ts +14 -0
  19. package/dist/commands/db.js +187 -0
  20. package/dist/commands/db.js.map +1 -0
  21. package/dist/commands/deploy.d.ts +16 -3
  22. package/dist/commands/deploy.js +400 -180
  23. package/dist/commands/deploy.js.map +1 -1
  24. package/dist/commands/doctor.d.ts +27 -0
  25. package/dist/commands/doctor.js +211 -0
  26. package/dist/commands/doctor.js.map +1 -0
  27. package/dist/commands/env.d.ts +15 -0
  28. package/dist/commands/env.js +56 -0
  29. package/dist/commands/env.js.map +1 -0
  30. package/dist/commands/fn.d.ts +6 -0
  31. package/dist/commands/fn.js +87 -0
  32. package/dist/commands/fn.js.map +1 -0
  33. package/dist/commands/init.d.ts +10 -3
  34. package/dist/commands/init.js +212 -143
  35. package/dist/commands/init.js.map +1 -1
  36. package/dist/commands/login.d.ts +6 -3
  37. package/dist/commands/login.js +222 -92
  38. package/dist/commands/login.js.map +1 -1
  39. package/dist/commands/logout.d.ts +1 -0
  40. package/dist/commands/logout.js +28 -0
  41. package/dist/commands/logout.js.map +1 -0
  42. package/dist/commands/logs.d.ts +14 -3
  43. package/dist/commands/logs.js +132 -106
  44. package/dist/commands/logs.js.map +1 -1
  45. package/dist/commands/mocks.d.ts +5 -0
  46. package/dist/commands/mocks.js +23 -0
  47. package/dist/commands/mocks.js.map +1 -0
  48. package/dist/commands/open.d.ts +4 -3
  49. package/dist/commands/open.js +53 -85
  50. package/dist/commands/open.js.map +1 -1
  51. package/dist/commands/promote.d.ts +9 -0
  52. package/dist/commands/promote.js +114 -0
  53. package/dist/commands/promote.js.map +1 -0
  54. package/dist/commands/publish.d.ts +14 -0
  55. package/dist/commands/publish.js +180 -0
  56. package/dist/commands/publish.js.map +1 -0
  57. package/dist/commands/status.d.ts +5 -3
  58. package/dist/commands/status.js +91 -93
  59. package/dist/commands/status.js.map +1 -1
  60. package/dist/commands/upgrade.d.ts +12 -0
  61. package/dist/commands/upgrade.js +77 -0
  62. package/dist/commands/upgrade.js.map +1 -0
  63. package/dist/commands/validate.d.ts +1 -3
  64. package/dist/commands/validate.js +83 -91
  65. package/dist/commands/validate.js.map +1 -1
  66. package/dist/commands/whoami.d.ts +5 -3
  67. package/dist/commands/whoami.js +76 -28
  68. package/dist/commands/whoami.js.map +1 -1
  69. package/dist/index.d.ts +0 -1
  70. package/dist/index.js +337 -36
  71. package/dist/index.js.map +1 -1
  72. package/dist/lib/ai/context.d.ts +11 -0
  73. package/dist/lib/ai/context.js +112 -0
  74. package/dist/lib/ai/context.js.map +1 -0
  75. package/dist/lib/ai/orchestrator.d.ts +10 -0
  76. package/dist/lib/ai/orchestrator.js +92 -0
  77. package/dist/lib/ai/orchestrator.js.map +1 -0
  78. package/dist/lib/api-client.d.ts +21 -0
  79. package/dist/lib/api-client.js +65 -0
  80. package/dist/lib/api-client.js.map +1 -0
  81. package/dist/lib/auth.d.ts +15 -0
  82. package/dist/lib/auth.js +98 -0
  83. package/dist/lib/auth.js.map +1 -0
  84. package/dist/lib/config-schema.d.ts +165 -0
  85. package/dist/lib/config-schema.js +57 -0
  86. package/dist/lib/config-schema.js.map +1 -0
  87. package/dist/lib/config.d.ts +15 -0
  88. package/dist/lib/config.js +33 -0
  89. package/dist/lib/config.js.map +1 -0
  90. package/dist/utils/logger.d.ts +13 -0
  91. package/dist/utils/logger.js +27 -0
  92. package/dist/utils/logger.js.map +1 -0
  93. package/package.json +35 -33
  94. package/templates/auth/callback.ts +22 -0
  95. package/templates/auth/sign-in.tsx +41 -0
  96. package/templates/billing/checkout.ts +22 -0
  97. package/templates/billing/page.tsx +43 -0
  98. package/templates/support/ticket-form.tsx +68 -0
  99. package/templates/usage/track.ts +30 -0
  100. package/templates/users/profile.tsx +43 -0
  101. package/LICENSE +0 -21
  102. package/dist/commands/add.d.ts.map +0 -1
  103. package/dist/commands/deploy.d.ts.map +0 -1
  104. package/dist/commands/generate-types.d.ts +0 -3
  105. package/dist/commands/generate-types.d.ts.map +0 -1
  106. package/dist/commands/generate-types.js +0 -150
  107. package/dist/commands/generate-types.js.map +0 -1
  108. package/dist/commands/init.d.ts.map +0 -1
  109. package/dist/commands/login.d.ts.map +0 -1
  110. package/dist/commands/logs.d.ts.map +0 -1
  111. package/dist/commands/open.d.ts.map +0 -1
  112. package/dist/commands/status.d.ts.map +0 -1
  113. package/dist/commands/validate.d.ts.map +0 -1
  114. package/dist/commands/whoami.d.ts.map +0 -1
  115. package/dist/config.d.ts +0 -14
  116. package/dist/config.d.ts.map +0 -1
  117. package/dist/config.js +0 -83
  118. package/dist/config.js.map +0 -1
  119. package/dist/index.d.ts.map +0 -1
  120. package/dist/scaffold/auth.d.ts +0 -3
  121. package/dist/scaffold/auth.d.ts.map +0 -1
  122. package/dist/scaffold/auth.js +0 -228
  123. package/dist/scaffold/auth.js.map +0 -1
  124. package/dist/scaffold/billing.d.ts +0 -3
  125. package/dist/scaffold/billing.d.ts.map +0 -1
  126. package/dist/scaffold/billing.js +0 -184
  127. package/dist/scaffold/billing.js.map +0 -1
  128. package/dist/scaffold/usage.d.ts +0 -3
  129. package/dist/scaffold/usage.d.ts.map +0 -1
  130. package/dist/scaffold/usage.js +0 -173
  131. package/dist/scaffold/usage.js.map +0 -1
  132. package/dist/scaffold/users.d.ts +0 -3
  133. package/dist/scaffold/users.d.ts.map +0 -1
  134. package/dist/scaffold/users.js +0 -135
  135. package/dist/scaffold/users.js.map +0 -1
@@ -1,114 +1,140 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.logsCommand = logsCommand;
7
- const commander_1 = require("commander");
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const ora_1 = __importDefault(require("ora"));
10
- const config_1 = require("../config");
11
- function logsCommand() {
12
- const cmd = new commander_1.Command('logs');
13
- cmd
14
- .description('Visualiza logs do workspace em tempo real')
15
- .option('-f, --follow', 'Tail contínuo (poll a cada 5s)')
16
- .option('-n, --lines <count>', 'Número de linhas a buscar', '50')
17
- .option('--since <duration>', 'Logs desde N minutos atrás (ex: 30m, 2h)', '15m')
18
- .option('--level <level>', 'Filtrar por nível: info | warn | error | debug')
19
- .action(async (options) => {
20
- let config;
21
- try {
22
- config = (0, config_1.requireConfig)();
23
- }
24
- catch (e) {
25
- console.error(chalk_1.default.red(e.message));
26
- process.exit(1);
1
+ /**
2
+ * `neetru logs` visualiza logs do workspace.
3
+ *
4
+ * Endpoint: `GET /api/v1/cli/logs?clientId=<id>&limit=N&since=<ms>&level=<lvl>`.
5
+ * Suporta tail contínuo (`-f`) com poll a cada 5s usando `after=<lastTs>`.
6
+ */
7
+ import chalk from 'chalk';
8
+ import { apiRequest, CliApiError, CliNetworkError } from '../lib/api-client.js';
9
+ import { config } from '../lib/config.js';
10
+ import { log } from '../utils/logger.js';
11
+ function parseDuration(input) {
12
+ const m = input.match(/^(\d+)([smhd])$/i);
13
+ if (!m)
14
+ return 15 * 60 * 1000;
15
+ const n = Number.parseInt(m[1], 10);
16
+ const unit = m[2].toLowerCase();
17
+ switch (unit) {
18
+ case 's': return n * 1000;
19
+ case 'm': return n * 60 * 1000;
20
+ case 'h': return n * 60 * 60 * 1000;
21
+ case 'd': return n * 24 * 60 * 60 * 1000;
22
+ default: return 15 * 60 * 1000;
23
+ }
24
+ }
25
+ function colorLevel(level) {
26
+ switch ((level ?? 'info').toLowerCase()) {
27
+ case 'error':
28
+ case 'fatal': return chalk.red;
29
+ case 'warn':
30
+ case 'warning': return chalk.yellow;
31
+ case 'debug': return chalk.gray;
32
+ default: return chalk.blue;
33
+ }
34
+ }
35
+ function printLog(entry) {
36
+ const ts = new Date(entry.timestamp).toLocaleTimeString('pt-BR');
37
+ const lvl = (entry.level ?? 'info').toUpperCase().padEnd(5);
38
+ const color = colorLevel(entry.level);
39
+ const src = entry.source ? chalk.dim(`[${entry.source}]`) : '';
40
+ console.log(`${chalk.dim(ts)} ${color(lvl)} ${src} ${entry.message}`);
41
+ }
42
+ async function fetchLogs(clientId, params) {
43
+ const qs = new URLSearchParams({
44
+ clientId,
45
+ limit: String(params.limit),
46
+ });
47
+ if (params.after)
48
+ qs.set('after', params.after);
49
+ else if (params.since !== undefined)
50
+ qs.set('since', String(params.since));
51
+ if (params.level)
52
+ qs.set('level', params.level);
53
+ if (params.product)
54
+ qs.set('product', params.product);
55
+ if (params.channel)
56
+ qs.set('channel', params.channel);
57
+ if (params.correlationId)
58
+ qs.set('correlationId', params.correlationId);
59
+ const res = await apiRequest(`/api/v1/cli/logs?${qs.toString()}`);
60
+ return res.logs ?? [];
61
+ }
62
+ export async function runLogs(opts) {
63
+ if (!opts.clientId) {
64
+ log.error('--client-id <oauthClientId> obrigatório.');
65
+ process.exit(1);
66
+ }
67
+ if (!config.get('neetruApiKey')) {
68
+ log.error('Não autenticado. Execute: neetru login');
69
+ process.exit(2);
70
+ }
71
+ const lines = Math.max(1, Math.min(1000, Number.parseInt(opts.lines ?? '50', 10) || 50));
72
+ const sinceMs = parseDuration(opts.since ?? '15m');
73
+ const since = Date.now() - sinceMs;
74
+ let entries;
75
+ try {
76
+ entries = await fetchLogs(opts.clientId, {
77
+ limit: lines,
78
+ since,
79
+ level: opts.level,
80
+ product: opts.product,
81
+ channel: opts.channel,
82
+ correlationId: opts.correlationId,
83
+ });
84
+ }
85
+ catch (error) {
86
+ if (error instanceof CliApiError) {
87
+ if (error.status === 401) {
88
+ log.error('Sessão expirada. Execute: neetru login');
89
+ process.exit(2);
90
+ }
91
+ if (error.status === 404) {
92
+ log.error('Workspace não encontrado.');
93
+ process.exit(1);
94
+ }
95
+ log.error(`Erro do servidor (${error.status}): ${error.message}`);
96
+ process.exit(4);
27
97
  }
28
- const global = (0, config_1.readGlobalConfig)();
29
- const apiKey = global.clientSecret ?? process.env.NEETRU_CLI_API_KEY;
30
- if (!apiKey) {
31
- console.error(chalk_1.default.red('Não autenticado. Execute neetru login primeiro.'));
32
- process.exit(1);
98
+ if (error instanceof CliNetworkError) {
99
+ log.error(error.message);
100
+ process.exit(4);
33
101
  }
34
- const lines = parseInt(options.lines, 10);
35
- const sinceMs = parseDuration(options.since);
36
- const fetchLogs = async (afterTs) => {
37
- const params = new URLSearchParams({
38
- clientId: config.clientId,
39
- limit: String(lines),
40
- });
41
- if (afterTs)
42
- params.set('after', afterTs);
43
- else
44
- params.set('since', String(Date.now() - sinceMs));
45
- if (options.level)
46
- params.set('level', options.level);
47
- const res = await fetch(`${config.coreUrl}/api/v1/cli/logs?${params.toString()}`, {
48
- headers: { Authorization: `Bearer ${apiKey}` },
49
- signal: AbortSignal.timeout(10000),
102
+ log.error(error.message);
103
+ process.exit(4);
104
+ }
105
+ if (entries.length === 0) {
106
+ log.dim(' Nenhum log encontrado no intervalo.');
107
+ }
108
+ else {
109
+ for (const e of entries)
110
+ printLog(e);
111
+ }
112
+ if (!opts.follow)
113
+ return;
114
+ let lastTs = entries.length > 0 ? entries[entries.length - 1].timestamp : new Date().toISOString();
115
+ log.dim(' Aguardando novos logs… (Ctrl+C para sair)');
116
+ while (true) {
117
+ await new Promise((r) => setTimeout(r, 5000));
118
+ try {
119
+ const next = await fetchLogs(opts.clientId, {
120
+ limit: lines,
121
+ after: lastTs,
122
+ level: opts.level,
123
+ product: opts.product,
124
+ channel: opts.channel,
125
+ correlationId: opts.correlationId,
50
126
  });
51
- if (!res.ok) {
52
- throw new Error(`HTTP ${res.status}`);
127
+ for (const e of next) {
128
+ printLog(e);
129
+ lastTs = e.timestamp;
53
130
  }
54
- const data = await res.json();
55
- return data.logs ?? [];
56
- };
57
- const printLog = (log) => {
58
- const ts = new Date(log.timestamp).toLocaleTimeString('pt-BR');
59
- const levelColor = {
60
- info: chalk_1.default.blue,
61
- warn: chalk_1.default.yellow,
62
- error: chalk_1.default.red,
63
- debug: chalk_1.default.dim,
64
- }[log.level] ?? chalk_1.default.white;
65
- console.log(`${chalk_1.default.dim(ts)} ${levelColor(log.level.toUpperCase().padEnd(5))} ${chalk_1.default.cyan(log.source.padEnd(20))} ${log.message}`);
66
- };
67
- // Initial fetch
68
- const spinner = (0, ora_1.default)('Buscando logs...').start();
69
- let initialLogs;
70
- try {
71
- initialLogs = await fetchLogs();
72
- }
73
- catch (e) {
74
- spinner.fail(`Erro: ${e.message}`);
75
- process.exit(1);
76
- }
77
- spinner.stop();
78
- if (initialLogs.length === 0) {
79
- console.log(chalk_1.default.dim('Nenhum log encontrado nos últimos ' + options.since));
80
131
  }
81
- else {
82
- initialLogs.forEach(printLog);
132
+ catch (error) {
133
+ // Transient errors no follow não derrubam o tail
134
+ if (error instanceof CliNetworkError)
135
+ continue;
136
+ throw error;
83
137
  }
84
- if (!options.follow)
85
- return;
86
- // Tail mode
87
- console.log(chalk_1.default.dim('\n--- Tail mode (Ctrl+C para sair) ---'));
88
- let lastTimestamp = initialLogs.at(-1)?.timestamp ?? new Date().toISOString();
89
- const poll = async () => {
90
- try {
91
- const newLogs = await fetchLogs(lastTimestamp);
92
- if (newLogs.length > 0) {
93
- newLogs.forEach(printLog);
94
- lastTimestamp = newLogs.at(-1).timestamp;
95
- }
96
- }
97
- catch (e) {
98
- console.error(chalk_1.default.dim(`[poll error: ${e.message}]`));
99
- }
100
- };
101
- setInterval(poll, 5000);
102
- });
103
- return cmd;
104
- }
105
- function parseDuration(s) {
106
- const match = s.match(/^(\d+)([smhd])$/);
107
- if (!match)
108
- return 15 * 60000;
109
- const n = parseInt(match[1], 10);
110
- const unit = match[2];
111
- const mult = unit === 's' ? 1000 : unit === 'm' ? 60000 : unit === 'h' ? 3600000 : 86400000;
112
- return n * mult;
138
+ }
113
139
  }
114
140
  //# sourceMappingURL=logs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface MocksOptions {
2
+ /** Override cwd (test injeta diferente). */
3
+ cwd?: string;
4
+ }
5
+ export declare function runMocksReset(opts?: MocksOptions): Promise<void>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `neetru mocks reset` — limpa fixtures dev (`.neetru/dev-fixtures.json`).
3
+ *
4
+ * Útil quando o produto consome SDK em modo `NEETRU_ENV=dev` e quer um
5
+ * estado limpo entre runs locais. Não toca produção.
6
+ */
7
+ import * as fs from 'node:fs/promises';
8
+ import * as fsSync from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import { log } from '../utils/logger.js';
11
+ const FIXTURE_FILE = '.neetru/dev-fixtures.json';
12
+ export async function runMocksReset(opts = {}) {
13
+ const cwd = opts.cwd ?? process.cwd();
14
+ const filePath = path.join(cwd, FIXTURE_FILE);
15
+ if (!fsSync.existsSync(filePath)) {
16
+ log.info(`Sem fixture pra resetar (${FIXTURE_FILE} não existe).`);
17
+ return;
18
+ }
19
+ // Mantém arquivo, sobrescreve com `{}` (mais auditável que delete).
20
+ await fs.writeFile(filePath, '{}\n', 'utf-8');
21
+ log.success(`Fixture resetada: ${FIXTURE_FILE}`);
22
+ }
23
+ //# sourceMappingURL=mocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mocks.js","sourceRoot":"","sources":["../../src/commands/mocks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,MAAM,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAOzC,MAAM,YAAY,GAAG,2BAA2B,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAqB,EAAE;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAE9C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,IAAI,CAAC,4BAA4B,YAAY,eAAe,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IAED,oEAAoE;IACpE,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,GAAG,CAAC,OAAO,CAAC,qBAAqB,YAAY,EAAE,CAAC,CAAC;AACnD,CAAC"}
@@ -1,3 +1,4 @@
1
- import { Command } from 'commander';
2
- export declare function openCommand(): Command;
3
- //# sourceMappingURL=open.d.ts.map
1
+ export interface OpenOptions {
2
+ clientId?: string;
3
+ }
4
+ export declare function runOpen(target: string | undefined, opts: OpenOptions): Promise<void>;
@@ -1,91 +1,59 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.openCommand = openCommand;
40
- const commander_1 = require("commander");
41
- const chalk_1 = __importDefault(require("chalk"));
42
- const config_1 = require("../config");
43
- const child_process_1 = require("child_process");
44
- const os = __importStar(require("os"));
1
+ /**
2
+ * `neetru open [target]` abre página do painel Neetru no browser.
3
+ *
4
+ * Targets: dashboard, builds, logs, settings, workspaces, products, servers.
5
+ * Default: dashboard.
6
+ */
7
+ import { spawn } from 'node:child_process';
8
+ import chalk from 'chalk';
9
+ import { config } from '../lib/config.js';
10
+ import { log } from '../utils/logger.js';
45
11
  const TARGETS = {
46
- dashboard: (url) => `${url}/`,
47
- workspace: (url, id) => `${url}/workspaces?clientId=${encodeURIComponent(id)}`,
48
- builds: (url) => `${url}/builds`,
49
- deployments: (url) => `${url}/deployments`,
50
- billing: (url) => `${url}/billing`,
51
- logs: (url) => `${url}/logs`,
52
- credentials: (url) => `${url}/admin/credentials`,
53
- status: (url) => `${url}/status`,
12
+ dashboard: '/',
13
+ builds: '/builds',
14
+ logs: '/observability',
15
+ settings: '/settings',
16
+ workspaces: '/workspaces',
17
+ products: '/products/public',
18
+ servers: '/servers',
19
+ incidents: '/incidents',
54
20
  };
55
- function openCommand() {
56
- const cmd = new commander_1.Command('open');
57
- cmd
58
- .description('Abre uma página do painel Neetru no navegador')
59
- .argument('[target]', `Página: ${Object.keys(TARGETS).join(' | ')}`, 'dashboard')
60
- .action((target) => {
61
- const config = (0, config_1.readLocalConfig)();
62
- if (!config) {
63
- console.error(chalk_1.default.red('neetru.json não encontrado. Execute neetru init primeiro.'));
64
- process.exit(1);
65
- }
66
- const buildUrl = TARGETS[target];
67
- if (!buildUrl) {
68
- console.error(chalk_1.default.red(`Target desconhecido: ${target}`));
69
- console.log(chalk_1.default.dim(`Disponíveis: ${Object.keys(TARGETS).join(', ')}`));
70
- process.exit(1);
21
+ function openUrl(url) {
22
+ try {
23
+ if (process.platform === 'win32') {
24
+ spawn('cmd', ['/c', 'start', '""', url], {
25
+ detached: true,
26
+ stdio: 'ignore',
27
+ windowsHide: true,
28
+ }).unref();
29
+ return;
71
30
  }
72
- const url = buildUrl(config.coreUrl, config.clientId);
73
- console.log(chalk_1.default.dim(`Abrindo ${url}`));
74
- const platform = os.platform();
75
- try {
76
- const cmdMap = {
77
- darwin: `open "${url}"`,
78
- win32: `start "" "${url}"`,
79
- linux: `xdg-open "${url}"`,
80
- };
81
- const command = cmdMap[platform] ?? cmdMap.linux;
82
- (0, child_process_1.execSync)(command, { stdio: 'ignore' });
31
+ if (process.platform === 'darwin') {
32
+ spawn('open', [url], { detached: true, stdio: 'ignore' }).unref();
33
+ return;
83
34
  }
84
- catch {
85
- console.log(chalk_1.default.yellow('Não foi possível abrir o navegador automaticamente.'));
86
- console.log(chalk_1.default.cyan(url));
87
- }
88
- });
89
- return cmd;
35
+ spawn('xdg-open', [url], { detached: true, stdio: 'ignore' }).unref();
36
+ }
37
+ catch (e) {
38
+ log.warn(`Não consegui abrir browser. Acesse manualmente: ${url}`);
39
+ }
40
+ }
41
+ export async function runOpen(target, opts) {
42
+ const key = (target ?? 'dashboard').toLowerCase();
43
+ if (!(key in TARGETS)) {
44
+ log.error(`Target desconhecido: ${target}`);
45
+ log.dim(` Disponíveis: ${Object.keys(TARGETS).join(', ')}`);
46
+ process.exit(1);
47
+ }
48
+ const corePath = TARGETS[key];
49
+ const baseUrl = String(config.get('neetruCoreUrl') ?? 'https://core.neetru.com').replace(/\/+$/, '');
50
+ let url = `${baseUrl}${corePath}`;
51
+ // Para targets workspace-scoped, anexa clientId se disponível
52
+ if (opts.clientId && ['logs', 'builds'].includes(key)) {
53
+ const sep = url.includes('?') ? '&' : '?';
54
+ url = `${url}${sep}clientId=${encodeURIComponent(opts.clientId)}`;
55
+ }
56
+ console.log(chalk.dim(`Abrindo ${url}…`));
57
+ openUrl(url);
90
58
  }
91
59
  //# sourceMappingURL=open.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface PromoteOptions {
2
+ from: string;
3
+ to: string;
4
+ product?: string;
5
+ reason?: string;
6
+ fromRevision?: string;
7
+ toRevision?: string;
8
+ }
9
+ export declare function runPromote(opts: PromoteOptions): Promise<void>;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * `neetru promote --from=workspace --to=beta|prod` — staff-gated.
3
+ *
4
+ * Sprint 10 (CLI 1.4). Wrapper sobre a server action `requestPromotion`
5
+ * (Core) — chama via API REST `/cli/v1/promotion/request`. Retorna o
6
+ * `promotionId` pra owner conferir em `/observability/promotions`.
7
+ *
8
+ * Por se tratar de operação privilegiada, o endpoint REST exige Bearer
9
+ * token nrt_<keyId>_<secret> com role `admin` ou `operator` em
10
+ * `cli_api_keys/{id}.staffRole`.
11
+ *
12
+ * O CLI não aprova/aplica diretamente — esse fluxo de approve passa por
13
+ * UI staff (`/observability/promotions`) ou comando dedicado futuro
14
+ * (out of scope no Sprint 10).
15
+ */
16
+ import * as fs from 'node:fs/promises';
17
+ import * as fsSync from 'node:fs';
18
+ import * as path from 'node:path';
19
+ import chalk from 'chalk';
20
+ import { log } from '../utils/logger.js';
21
+ import { apiRequest, CliApiError, CliNetworkError } from '../lib/api-client.js';
22
+ const CONFIG_FILENAMES = ['neetru.config.json', '.neetru.json'];
23
+ const VALID_ENVS = ['dev', 'workspace', 'beta', 'prod'];
24
+ async function loadProductConfig() {
25
+ for (const name of CONFIG_FILENAMES) {
26
+ const filePath = path.resolve(process.cwd(), name);
27
+ if (fsSync.existsSync(filePath)) {
28
+ try {
29
+ const raw = await fs.readFile(filePath, 'utf8');
30
+ return JSON.parse(raw);
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+ function isValidEnv(v) {
40
+ return VALID_ENVS.includes(v);
41
+ }
42
+ export async function runPromote(opts) {
43
+ log.banner();
44
+ log.heading('neetru promote');
45
+ if (!opts.from || !opts.to) {
46
+ log.error('--from e --to são obrigatórios. Ex: neetru promote --from=workspace --to=beta');
47
+ process.exit(1);
48
+ return;
49
+ }
50
+ if (!isValidEnv(opts.from)) {
51
+ log.error(`--from inválido. Use: ${VALID_ENVS.join(' | ')}`);
52
+ process.exit(2);
53
+ return;
54
+ }
55
+ if (!isValidEnv(opts.to)) {
56
+ log.error(`--to inválido. Use: ${VALID_ENVS.join(' | ')}`);
57
+ process.exit(2);
58
+ return;
59
+ }
60
+ let productSlug = opts.product;
61
+ if (!productSlug) {
62
+ const cfg = await loadProductConfig();
63
+ if (!cfg) {
64
+ log.error('neetru.config.json não encontrado e --product não informado.');
65
+ process.exit(3);
66
+ return;
67
+ }
68
+ productSlug = cfg.slug;
69
+ }
70
+ log.info(`Solicitando promotion ${chalk.bold(productSlug)}: ${chalk.bold(opts.from)} → ${chalk.bold(opts.to)}`);
71
+ try {
72
+ const r = await apiRequest('/cli/v1/promotion/request', {
73
+ method: 'POST',
74
+ body: {
75
+ productSlug,
76
+ fromEnv: opts.from,
77
+ toEnv: opts.to,
78
+ reason: opts.reason,
79
+ fromRevision: opts.fromRevision,
80
+ toRevision: opts.toRevision,
81
+ },
82
+ });
83
+ log.success(`Promotion criada: ${chalk.bold(r.promotionId)}`);
84
+ log.dim(` status: ${r.status}`);
85
+ log.dim(' Acompanhe em: https://core.neetru.com/observability/promotions');
86
+ }
87
+ catch (err) {
88
+ if (err instanceof CliApiError) {
89
+ if (err.status === 404 || err.status === 501) {
90
+ log.warn(`Endpoint ainda não disponível (${err.status}).`);
91
+ log.dim(' /cli/v1/promotion/request entra em build no Sprint 11.');
92
+ process.exit(0);
93
+ return;
94
+ }
95
+ if (err.status === 401 || err.status === 403) {
96
+ log.error('Não autorizado. Faça login com chave que tenha role admin/operator.');
97
+ log.dim(' neetru login');
98
+ process.exit(4);
99
+ return;
100
+ }
101
+ log.error(`API ${err.status}: ${err.message}`);
102
+ process.exit(5);
103
+ return;
104
+ }
105
+ if (err instanceof CliNetworkError) {
106
+ log.error(`Conexão falhou: ${err.message}`);
107
+ process.exit(6);
108
+ return;
109
+ }
110
+ log.error(err instanceof Error ? err.message : String(err));
111
+ process.exit(7);
112
+ }
113
+ }
114
+ //# sourceMappingURL=promote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promote.js","sourceRoot":"","sources":["../../src/commands/promote.ts"],"names":[],"mappings":"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"}