@neetru/cli 2.13.1 → 2.15.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/CHANGELOG.md +27 -0
- package/dist/commands/ai.js +8 -8
- package/dist/commands/autocomplete.d.ts +1 -1
- package/dist/commands/autocomplete.js +1 -0
- package/dist/commands/autocomplete.js.map +1 -1
- package/dist/commands/code.d.ts +27 -0
- package/dist/commands/code.js +469 -0
- package/dist/commands/code.js.map +1 -0
- package/dist/commands/fn.d.ts +6 -0
- package/dist/commands/fn.js +88 -0
- package/dist/commands/fn.js.map +1 -0
- package/dist/commands/init.js +147 -147
- package/dist/commands/marketplace.d.ts +36 -0
- package/dist/commands/marketplace.js +585 -0
- package/dist/commands/marketplace.js.map +1 -0
- package/dist/commands/ui.d.ts +1 -1
- package/dist/commands/ui.js +9 -0
- package/dist/commands/ui.js.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/ai/context.js +91 -91
- package/dist/lib/ai/orchestrator.js +7 -43
- package/dist/lib/ai/orchestrator.js.map +1 -1
- package/dist/lib/api-client.d.ts +1 -0
- package/dist/lib/api-client.js +4 -3
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/code-agent-files.d.ts +47 -0
- package/dist/lib/code-agent-files.js +468 -0
- package/dist/lib/code-agent-files.js.map +1 -0
- package/dist/lib/code-agent-gateway.d.ts +27 -0
- package/dist/lib/code-agent-gateway.js +115 -0
- package/dist/lib/code-agent-gateway.js.map +1 -0
- package/dist/lib/code-agent-protocol.d.ts +24 -0
- package/dist/lib/code-agent-protocol.js +56 -0
- package/dist/lib/code-agent-protocol.js.map +1 -0
- package/dist/lib/code-agent-session.d.ts +54 -0
- package/dist/lib/code-agent-session.js +147 -0
- package/dist/lib/code-agent-session.js.map +1 -0
- package/dist/lib/code-agent-settings.d.ts +20 -0
- package/dist/lib/code-agent-settings.js +38 -0
- package/dist/lib/code-agent-settings.js.map +1 -0
- package/dist/lib/code-agent-tools.d.ts +17 -0
- package/dist/lib/code-agent-tools.js +52 -0
- package/dist/lib/code-agent-tools.js.map +1 -0
- package/dist/lib/code-agent-types.d.ts +34 -0
- package/dist/lib/code-agent-types.js +7 -0
- package/dist/lib/code-agent-types.js.map +1 -0
- package/dist/lib/code-agent-ui.d.ts +30 -0
- package/dist/lib/code-agent-ui.js +258 -0
- package/dist/lib/code-agent-ui.js.map +1 -0
- package/dist/lib/sse.d.ts +14 -0
- package/dist/lib/sse.js +43 -0
- package/dist/lib/sse.js.map +1 -0
- package/package.json +1 -1
- package/templates/auth/callback.ts +22 -22
- package/templates/auth/sign-in.tsx +41 -41
- package/templates/billing/checkout.ts +22 -22
- package/templates/billing/page.tsx +43 -43
- package/templates/support/ticket-form.tsx +68 -68
- package/templates/usage/track.ts +30 -30
- package/templates/users/profile.tsx +43 -43
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderização de terminal do `neetru code` — extraído de commands/code.ts
|
|
3
|
+
* (Fase 2, NEETRU_CODE_ARCHITECTURE.md: "separar núcleo de interface").
|
|
4
|
+
*
|
|
5
|
+
* Puramente apresentacional: recebe dados já resolvidos (settings, history,
|
|
6
|
+
* strings) e escreve no terminal. Não decide fluxo, não chama AI Gateway,
|
|
7
|
+
* não executa ferramentas — isso mora em code-agent-gateway.ts /
|
|
8
|
+
* code-agent-tools.ts / commands/code.ts (orquestração do REPL).
|
|
9
|
+
*/
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { spawnSync } from 'node:child_process';
|
|
13
|
+
import { summarizePatch } from './code-agent-protocol.js';
|
|
14
|
+
import { renderColoredDiff } from './code-agent-files.js';
|
|
15
|
+
const AI_GATEWAY_CHAT_PATH = '/api/cli/v1/ai/chat';
|
|
16
|
+
const UI_MIN_WIDTH = 72;
|
|
17
|
+
const UI_MAX_WIDTH = 110;
|
|
18
|
+
export function stripAnsi(text) {
|
|
19
|
+
return text.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '');
|
|
20
|
+
}
|
|
21
|
+
export function visibleLength(text) {
|
|
22
|
+
return Array.from(stripAnsi(text)).length;
|
|
23
|
+
}
|
|
24
|
+
export function padVisible(text, width) {
|
|
25
|
+
return `${text}${' '.repeat(Math.max(0, width - visibleLength(text)))}`;
|
|
26
|
+
}
|
|
27
|
+
export function terminalWidth() {
|
|
28
|
+
const raw = process.stdout.columns ?? 88;
|
|
29
|
+
return Math.max(UI_MIN_WIDTH, Math.min(UI_MAX_WIDTH, raw));
|
|
30
|
+
}
|
|
31
|
+
export function truncateMiddle(text, max) {
|
|
32
|
+
if (visibleLength(text) <= max)
|
|
33
|
+
return text;
|
|
34
|
+
if (max <= 5)
|
|
35
|
+
return text.slice(0, max);
|
|
36
|
+
const clean = stripAnsi(text);
|
|
37
|
+
const left = Math.ceil((max - 3) / 2);
|
|
38
|
+
const right = Math.floor((max - 3) / 2);
|
|
39
|
+
return `${clean.slice(0, left)}...${clean.slice(clean.length - right)}`;
|
|
40
|
+
}
|
|
41
|
+
export function wrapPlain(text, width) {
|
|
42
|
+
const clean = stripAnsi(text);
|
|
43
|
+
if (clean.length <= width)
|
|
44
|
+
return [clean];
|
|
45
|
+
const out = [];
|
|
46
|
+
let rest = clean;
|
|
47
|
+
while (rest.length > width) {
|
|
48
|
+
const slice = rest.slice(0, width + 1);
|
|
49
|
+
const breakAt = Math.max(slice.lastIndexOf(' '), slice.lastIndexOf('/'), slice.lastIndexOf('\\'));
|
|
50
|
+
const idx = breakAt > Math.floor(width * 0.45) ? breakAt : width;
|
|
51
|
+
out.push(rest.slice(0, idx).trimEnd());
|
|
52
|
+
rest = rest.slice(idx).trimStart();
|
|
53
|
+
}
|
|
54
|
+
if (rest)
|
|
55
|
+
out.push(rest);
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
export function printBox(title, rows = []) {
|
|
59
|
+
const width = terminalWidth();
|
|
60
|
+
const inner = width - 2;
|
|
61
|
+
const label = title ? ` ${title} ` : '';
|
|
62
|
+
const top = `+${label}${'-'.repeat(Math.max(0, inner - visibleLength(label)))}+`;
|
|
63
|
+
console.log(chalk.dim(top));
|
|
64
|
+
for (const row of rows) {
|
|
65
|
+
const wrapped = wrapPlain(row, inner - 2);
|
|
66
|
+
for (const line of wrapped) {
|
|
67
|
+
console.log(chalk.dim('| ') + padVisible(truncateMiddle(line, inner - 2), inner - 2) + chalk.dim(' |'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
console.log(chalk.dim(`+${'-'.repeat(inner)}+`));
|
|
71
|
+
}
|
|
72
|
+
export function printStatusBar(settings, mode) {
|
|
73
|
+
const width = terminalWidth();
|
|
74
|
+
const repo = path.basename(settings.cwd) || settings.cwd;
|
|
75
|
+
const patchMode = settings.apply ? (settings.yes ? 'auto-aplica' : 'confirma patch') : 'somente plano';
|
|
76
|
+
const raw = ` neetru code | ${mode} | ${repo} | ${settings.model} | ${patchMode} `;
|
|
77
|
+
console.log(chalk.inverse(padVisible(truncateMiddle(raw, width), width)));
|
|
78
|
+
}
|
|
79
|
+
export function printDivider(label) {
|
|
80
|
+
const width = terminalWidth();
|
|
81
|
+
if (!label) {
|
|
82
|
+
console.log(chalk.dim('-'.repeat(width)));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const title = ` ${label} `;
|
|
86
|
+
console.log(chalk.dim(`${title}${'-'.repeat(Math.max(0, width - visibleLength(title)))}`));
|
|
87
|
+
}
|
|
88
|
+
export function printEvent(kind, title, detail) {
|
|
89
|
+
const colors = {
|
|
90
|
+
wait: chalk.cyan,
|
|
91
|
+
tool: chalk.blue,
|
|
92
|
+
ok: chalk.green,
|
|
93
|
+
warn: chalk.yellow,
|
|
94
|
+
error: chalk.red,
|
|
95
|
+
};
|
|
96
|
+
const labels = {
|
|
97
|
+
wait: '...',
|
|
98
|
+
tool: 'tool',
|
|
99
|
+
ok: 'ok',
|
|
100
|
+
warn: 'aviso',
|
|
101
|
+
error: 'erro',
|
|
102
|
+
};
|
|
103
|
+
const time = new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' });
|
|
104
|
+
const tag = colors[kind](`[${labels[kind]}]`.padEnd(8));
|
|
105
|
+
const suffix = detail ? chalk.dim(` ${detail}`) : '';
|
|
106
|
+
console.log(`${chalk.dim(time)} ${tag} ${chalk.bold(title)}${suffix}`);
|
|
107
|
+
}
|
|
108
|
+
export function summarizeToolResult(result) {
|
|
109
|
+
const lines = result.split(/\r?\n/).filter(Boolean).length;
|
|
110
|
+
const chars = result.length;
|
|
111
|
+
return `${lines} linha(s), ${chars} char(s)`;
|
|
112
|
+
}
|
|
113
|
+
export function printAssistantText(content) {
|
|
114
|
+
const text = content.trim();
|
|
115
|
+
if (!text)
|
|
116
|
+
return;
|
|
117
|
+
printBox('resposta', text.split(/\r?\n/));
|
|
118
|
+
}
|
|
119
|
+
export function patchSummaryRows(patch) {
|
|
120
|
+
const summary = summarizePatch(patch);
|
|
121
|
+
if (summary.length === 0)
|
|
122
|
+
return ['arquivos: nao detectado'];
|
|
123
|
+
const added = summary.reduce((total, item) => total + item.added, 0);
|
|
124
|
+
const removed = summary.reduce((total, item) => total + item.removed, 0);
|
|
125
|
+
const rows = [`arquivos: ${summary.length} | +${added} -${removed}`];
|
|
126
|
+
for (const item of summary.slice(0, 8)) {
|
|
127
|
+
rows.push(`${item.file} +${item.added} -${item.removed}`);
|
|
128
|
+
}
|
|
129
|
+
if (summary.length > 8)
|
|
130
|
+
rows.push(`... mais ${summary.length - 8} arquivo(s)`);
|
|
131
|
+
return rows;
|
|
132
|
+
}
|
|
133
|
+
export function printPatchPreview(patch) {
|
|
134
|
+
printBox('patch proposto', [
|
|
135
|
+
...patchSummaryRows(patch),
|
|
136
|
+
'aplicacao: git apply depois de confirmacao',
|
|
137
|
+
]);
|
|
138
|
+
process.stdout.write(renderColoredDiff(patch));
|
|
139
|
+
}
|
|
140
|
+
export function renderHeader(settings, mode = 'oneshot') {
|
|
141
|
+
const gitBranch = spawnSync('git', ['branch', '--show-current'], { cwd: settings.cwd, encoding: 'utf8' });
|
|
142
|
+
const gitStatus = spawnSync('git', ['status', '--short'], { cwd: settings.cwd, encoding: 'utf8' });
|
|
143
|
+
const branch = gitBranch.status === 0 && gitBranch.stdout.trim() ? gitBranch.stdout.trim() : 'sem git';
|
|
144
|
+
const dirty = gitStatus.status === 0
|
|
145
|
+
? gitStatus.stdout.split(/\r?\n/).filter(Boolean).length
|
|
146
|
+
: 0;
|
|
147
|
+
console.log();
|
|
148
|
+
printStatusBar(settings, mode);
|
|
149
|
+
printBox('sessao', [
|
|
150
|
+
`IA Gateway ${AI_GATEWAY_CHAT_PATH}`,
|
|
151
|
+
`Modelo ${settings.model}`,
|
|
152
|
+
`Pasta ${truncateMiddle(settings.cwd, terminalWidth() - 18)}`,
|
|
153
|
+
`Git ${branch} | ${dirty} arquivo(s) alterado(s)`,
|
|
154
|
+
`Patch ${settings.apply ? (settings.yes ? 'aplica sem perguntar' : 'pede confirmacao') : 'somente plano'}`,
|
|
155
|
+
`Limites ${settings.maxTurns} turno(s) | ${settings.maxTokens} tokens | temp ${settings.temperature}`,
|
|
156
|
+
`Contexto ${settings.files.length ? settings.files.join(', ') : 'sem arquivo inicial'}`,
|
|
157
|
+
]);
|
|
158
|
+
console.log();
|
|
159
|
+
}
|
|
160
|
+
export function renderInteractiveHelp() {
|
|
161
|
+
printBox('comandos', [
|
|
162
|
+
'/files listar arquivos do projeto',
|
|
163
|
+
'/pick escolher arquivo(s) por numero e anexar ao contexto',
|
|
164
|
+
'/status mostrar sessao, git e contexto',
|
|
165
|
+
'/overview mostrar visao geral do projeto',
|
|
166
|
+
'/diff mostrar diff git atual',
|
|
167
|
+
'/review pedir revisao das mudancas atuais',
|
|
168
|
+
'/save salvar conversa em .neetru/code/sessions',
|
|
169
|
+
'/resume listar e retomar uma sessao salva',
|
|
170
|
+
'/compact manter system prompt e ultimas mensagens',
|
|
171
|
+
'/model mostrar modelo atual',
|
|
172
|
+
'/plan nao aplicar patches',
|
|
173
|
+
'/apply pedir confirmacao antes de aplicar',
|
|
174
|
+
'/yes aplicar patch sem perguntar',
|
|
175
|
+
'/no voltar para confirmacao manual',
|
|
176
|
+
'/clear limpar tela e conversa',
|
|
177
|
+
'/help mostrar estes comandos',
|
|
178
|
+
'/exit sair',
|
|
179
|
+
]);
|
|
180
|
+
console.log(chalk.dim('Escreva a tarefa direto no prompt. O agente pede arquivos, mostra o fluxo e propoe patch.'));
|
|
181
|
+
console.log();
|
|
182
|
+
}
|
|
183
|
+
export function renderSessionStatus(settings, history = []) {
|
|
184
|
+
const gitStatus = spawnSync('git', ['status', '--short'], { cwd: settings.cwd, encoding: 'utf8' });
|
|
185
|
+
const changed = gitStatus.status === 0
|
|
186
|
+
? gitStatus.stdout.split(/\r?\n/).filter(Boolean)
|
|
187
|
+
: [];
|
|
188
|
+
printBox('status', [
|
|
189
|
+
`modelo: ${settings.model}`,
|
|
190
|
+
`pasta: ${settings.cwd}`,
|
|
191
|
+
`patch: ${settings.apply ? (settings.yes ? 'auto-aplica' : 'confirma antes') : 'somente plano'}`,
|
|
192
|
+
`mensagens na conversa: ${history.length}`,
|
|
193
|
+
`contexto inicial: ${settings.files.length ? settings.files.join(', ') : 'nenhum'}`,
|
|
194
|
+
`git alterado: ${changed.length} arquivo(s)`,
|
|
195
|
+
...(changed.length ? changed.slice(0, 8) : []),
|
|
196
|
+
...(changed.length > 8 ? [`... mais ${changed.length - 8}`] : []),
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
199
|
+
export function renderPrompt(settings) {
|
|
200
|
+
const repo = path.basename(settings.cwd) || 'projeto';
|
|
201
|
+
const mode = settings.apply ? (settings.yes ? 'auto' : 'confirmar') : 'plano';
|
|
202
|
+
return chalk.cyan(`neetru code ${repo} [${mode}] > `);
|
|
203
|
+
}
|
|
204
|
+
export function printFileSample(files, total) {
|
|
205
|
+
if (files.length === 0) {
|
|
206
|
+
printEvent('warn', 'Nenhum arquivo encontrado');
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
printBox('arquivos', [
|
|
210
|
+
`mostrando ${files.length} de ${total}`,
|
|
211
|
+
...files,
|
|
212
|
+
...(total > files.length ? ['... lista truncada em 60 arquivos.'] : []),
|
|
213
|
+
]);
|
|
214
|
+
}
|
|
215
|
+
/** Picker de arquivos (Fase 5) — lista numerada; `/pick` pede o(s) numero(s) ao usuario. */
|
|
216
|
+
export function printFilePicker(files, total) {
|
|
217
|
+
if (files.length === 0) {
|
|
218
|
+
printEvent('warn', 'Nenhum arquivo encontrado');
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
printBox('escolher arquivos', [
|
|
222
|
+
`mostrando ${files.length} de ${total}`,
|
|
223
|
+
...files.map((file, i) => `${i + 1}. ${file}`),
|
|
224
|
+
...(total > files.length ? ['... lista truncada em 60 arquivos.'] : []),
|
|
225
|
+
]);
|
|
226
|
+
}
|
|
227
|
+
/** Lista sessoes salvas numeradas (Fase 4) — usuario escolhe pelo numero em `/resume`. */
|
|
228
|
+
export function printSessionList(sessions) {
|
|
229
|
+
if (sessions.length === 0) {
|
|
230
|
+
printEvent('warn', 'Nenhuma sessao salva encontrada', '.neetru/code/sessions/');
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
printBox('sessoes salvas', sessions.map((s, i) => {
|
|
234
|
+
const label = s.preview ? ` — ${s.preview}` : '';
|
|
235
|
+
return `${i + 1}. ${s.timestamp} (${s.messageCount} msg)${label}`;
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
export function toolDetail(tool) {
|
|
239
|
+
if (!tool)
|
|
240
|
+
return '';
|
|
241
|
+
if (tool.tool === 'read_file' && typeof tool.path === 'string')
|
|
242
|
+
return tool.path;
|
|
243
|
+
if (tool.tool === 'list_files' && typeof tool.pattern === 'string' && tool.pattern)
|
|
244
|
+
return tool.pattern;
|
|
245
|
+
if (tool.tool === 'search' && typeof tool.query === 'string')
|
|
246
|
+
return tool.query;
|
|
247
|
+
if (tool.tool === 'read_many_files' && Array.isArray(tool.paths)) {
|
|
248
|
+
return `${tool.paths.length} arquivo(s)`;
|
|
249
|
+
}
|
|
250
|
+
if (tool.tool === 'search_regex' && typeof tool.pattern === 'string') {
|
|
251
|
+
const flags = typeof tool.flags === 'string' && tool.flags ? `/${tool.flags}` : '';
|
|
252
|
+
return `/${tool.pattern}/${flags}`;
|
|
253
|
+
}
|
|
254
|
+
if (tool.tool === 'project_symbols' && typeof tool.path === 'string' && tool.path)
|
|
255
|
+
return tool.path;
|
|
256
|
+
return '';
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=code-agent-ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-agent-ui.js","sourceRoot":"","sources":["../../src/lib/code-agent-ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consome um `ReadableStream` de bytes no formato SSE (`data: <payload>\n\n`,
|
|
3
|
+
* uma ou mais linhas por chunk de rede) e chama `onLine(payload)` pra cada
|
|
4
|
+
* linha `data: ` encontrada — `payload` é a string crua (sem parse; o caller
|
|
5
|
+
* decide o shape do JSON e trata `[DONE]`/keep-alives à sua maneira).
|
|
6
|
+
*
|
|
7
|
+
* Extraído de `src/lib/ai/orchestrator.ts` (onde nasceu pra reusar o parsing
|
|
8
|
+
* manual que `streamGemini` já fazia em `streamGateway`) pra um módulo sem
|
|
9
|
+
* dependências pesadas — `code-agent-gateway.ts` (`neetru code`) reusa o
|
|
10
|
+
* mesmo parser sem herdar o bundle inteiro do orchestrator (@anthropic-ai/sdk
|
|
11
|
+
* + openai). Cleanup do reader é feito aqui (`reader.cancel()` em finally) —
|
|
12
|
+
* o caller só precisa gerenciar seu próprio timeout/AbortController.
|
|
13
|
+
*/
|
|
14
|
+
export declare function readSseLines(body: ReadableStream<Uint8Array>, onLine: (payload: string) => void): Promise<void>;
|
package/dist/lib/sse.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consome um `ReadableStream` de bytes no formato SSE (`data: <payload>\n\n`,
|
|
3
|
+
* uma ou mais linhas por chunk de rede) e chama `onLine(payload)` pra cada
|
|
4
|
+
* linha `data: ` encontrada — `payload` é a string crua (sem parse; o caller
|
|
5
|
+
* decide o shape do JSON e trata `[DONE]`/keep-alives à sua maneira).
|
|
6
|
+
*
|
|
7
|
+
* Extraído de `src/lib/ai/orchestrator.ts` (onde nasceu pra reusar o parsing
|
|
8
|
+
* manual que `streamGemini` já fazia em `streamGateway`) pra um módulo sem
|
|
9
|
+
* dependências pesadas — `code-agent-gateway.ts` (`neetru code`) reusa o
|
|
10
|
+
* mesmo parser sem herdar o bundle inteiro do orchestrator (@anthropic-ai/sdk
|
|
11
|
+
* + openai). Cleanup do reader é feito aqui (`reader.cancel()` em finally) —
|
|
12
|
+
* o caller só precisa gerenciar seu próprio timeout/AbortController.
|
|
13
|
+
*/
|
|
14
|
+
export async function readSseLines(body, onLine) {
|
|
15
|
+
const reader = body.getReader();
|
|
16
|
+
const dec = new TextDecoder();
|
|
17
|
+
let buf = '';
|
|
18
|
+
try {
|
|
19
|
+
while (true) {
|
|
20
|
+
const { value, done } = await reader.read();
|
|
21
|
+
if (done)
|
|
22
|
+
break;
|
|
23
|
+
buf += dec.decode(value, { stream: true });
|
|
24
|
+
const lines = buf.split('\n');
|
|
25
|
+
buf = lines.pop() ?? '';
|
|
26
|
+
for (const line of lines) {
|
|
27
|
+
const matchData = line.match(/^data:\s*(.*)$/);
|
|
28
|
+
if (!matchData)
|
|
29
|
+
continue;
|
|
30
|
+
onLine(matchData[1]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
try {
|
|
36
|
+
await reader.cancel();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// reader já fechado, ignora.
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=sse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/lib/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAgC,EAChC,MAAiC;IAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;IAC9B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAChB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YACxB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;gBAC/C,IAAI,CAAC,SAAS;oBAAE,SAAS;gBACzB,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template — `src/lib/neetru/auth/callback.ts` (gerado por `neetru add auth`).
|
|
3
|
-
*
|
|
4
|
-
* Handler de callback OIDC (auth code → id_token). Use em `app/oauth/callback/route.ts`.
|
|
5
|
-
*/
|
|
6
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
7
|
-
|
|
8
|
-
export const runtime = 'nodejs';
|
|
9
|
-
|
|
10
|
-
export async function GET(request: NextRequest) {
|
|
11
|
-
const { searchParams } = new URL(request.url);
|
|
12
|
-
const code = searchParams.get('code');
|
|
13
|
-
const state = searchParams.get('state');
|
|
14
|
-
|
|
15
|
-
if (!code) {
|
|
16
|
-
return NextResponse.json({ error: 'missing_code' }, { status: 400 });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Trocar code → id_token contra auth.neetru.com/token
|
|
20
|
-
// Implementação detalhada em docs/PLATFORM_AUTH.md §4
|
|
21
|
-
return NextResponse.redirect(state ?? '/');
|
|
22
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Template — `src/lib/neetru/auth/callback.ts` (gerado por `neetru add auth`).
|
|
3
|
+
*
|
|
4
|
+
* Handler de callback OIDC (auth code → id_token). Use em `app/oauth/callback/route.ts`.
|
|
5
|
+
*/
|
|
6
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
7
|
+
|
|
8
|
+
export const runtime = 'nodejs';
|
|
9
|
+
|
|
10
|
+
export async function GET(request: NextRequest) {
|
|
11
|
+
const { searchParams } = new URL(request.url);
|
|
12
|
+
const code = searchParams.get('code');
|
|
13
|
+
const state = searchParams.get('state');
|
|
14
|
+
|
|
15
|
+
if (!code) {
|
|
16
|
+
return NextResponse.json({ error: 'missing_code' }, { status: 400 });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Trocar code → id_token contra auth.neetru.com/token
|
|
20
|
+
// Implementação detalhada em docs/PLATFORM_AUTH.md §4
|
|
21
|
+
return NextResponse.redirect(state ?? '/');
|
|
22
|
+
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template — `src/lib/neetru/auth/sign-in.tsx` (gerado por `neetru add auth`).
|
|
3
|
-
*
|
|
4
|
-
* Botão Google → redireciona pra auth.neetru.com via SDK (`client.auth.signIn`).
|
|
5
|
-
*
|
|
6
|
-
* Customização: ajuste `redirectUri` se hospedar fora do domínio default.
|
|
7
|
-
*/
|
|
8
|
-
'use client';
|
|
9
|
-
|
|
10
|
-
import { useState } from 'react';
|
|
11
|
-
import { createNeetruClient } from '@neetru/sdk';
|
|
12
|
-
|
|
13
|
-
const client = createNeetruClient({
|
|
14
|
-
apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
|
|
15
|
-
productId: process.env.NEXT_PUBLIC_NEETRU_PRODUCT_ID,
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export function SignInButton() {
|
|
19
|
-
const [loading, setLoading] = useState(false);
|
|
20
|
-
|
|
21
|
-
async function handleSignIn() {
|
|
22
|
-
setLoading(true);
|
|
23
|
-
try {
|
|
24
|
-
await client.auth.signIn();
|
|
25
|
-
} catch (err) {
|
|
26
|
-
console.error('signIn failed', err);
|
|
27
|
-
setLoading(false);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<button
|
|
33
|
-
type="button"
|
|
34
|
-
onClick={handleSignIn}
|
|
35
|
-
disabled={loading}
|
|
36
|
-
className="inline-flex items-center justify-center px-4 py-2 border bg-white hover:bg-zinc-50 text-zinc-900 font-medium"
|
|
37
|
-
>
|
|
38
|
-
{loading ? 'Redirecionando...' : 'Entrar com Neetru'}
|
|
39
|
-
</button>
|
|
40
|
-
);
|
|
41
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Template — `src/lib/neetru/auth/sign-in.tsx` (gerado por `neetru add auth`).
|
|
3
|
+
*
|
|
4
|
+
* Botão Google → redireciona pra auth.neetru.com via SDK (`client.auth.signIn`).
|
|
5
|
+
*
|
|
6
|
+
* Customização: ajuste `redirectUri` se hospedar fora do domínio default.
|
|
7
|
+
*/
|
|
8
|
+
'use client';
|
|
9
|
+
|
|
10
|
+
import { useState } from 'react';
|
|
11
|
+
import { createNeetruClient } from '@neetru/sdk';
|
|
12
|
+
|
|
13
|
+
const client = createNeetruClient({
|
|
14
|
+
apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
|
|
15
|
+
productId: process.env.NEXT_PUBLIC_NEETRU_PRODUCT_ID,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export function SignInButton() {
|
|
19
|
+
const [loading, setLoading] = useState(false);
|
|
20
|
+
|
|
21
|
+
async function handleSignIn() {
|
|
22
|
+
setLoading(true);
|
|
23
|
+
try {
|
|
24
|
+
await client.auth.signIn();
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.error('signIn failed', err);
|
|
27
|
+
setLoading(false);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<button
|
|
33
|
+
type="button"
|
|
34
|
+
onClick={handleSignIn}
|
|
35
|
+
disabled={loading}
|
|
36
|
+
className="inline-flex items-center justify-center px-4 py-2 border bg-white hover:bg-zinc-50 text-zinc-900 font-medium"
|
|
37
|
+
>
|
|
38
|
+
{loading ? 'Redirecionando...' : 'Entrar com Neetru'}
|
|
39
|
+
</button>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template — `src/lib/neetru/billing/checkout.ts` (gerado por `neetru add billing`).
|
|
3
|
-
*
|
|
4
|
-
* Inicia checkout Stripe via Core. Server route handler.
|
|
5
|
-
*/
|
|
6
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
7
|
-
|
|
8
|
-
export const runtime = 'nodejs';
|
|
9
|
-
|
|
10
|
-
export async function POST(request: NextRequest) {
|
|
11
|
-
const body = await request.json();
|
|
12
|
-
const slug = body?.slug as string | undefined;
|
|
13
|
-
if (!slug) {
|
|
14
|
-
return NextResponse.json({ error: 'slug required' }, { status: 400 });
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Hit Core REST: POST /api/v1/billing/checkout
|
|
18
|
-
// (Sprint 9 expõe via SDK direto)
|
|
19
|
-
return NextResponse.json({
|
|
20
|
-
redirectUrl: `https://minhaconta.neetru.com/checkout?slug=${slug}`,
|
|
21
|
-
});
|
|
22
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Template — `src/lib/neetru/billing/checkout.ts` (gerado por `neetru add billing`).
|
|
3
|
+
*
|
|
4
|
+
* Inicia checkout Stripe via Core. Server route handler.
|
|
5
|
+
*/
|
|
6
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
7
|
+
|
|
8
|
+
export const runtime = 'nodejs';
|
|
9
|
+
|
|
10
|
+
export async function POST(request: NextRequest) {
|
|
11
|
+
const body = await request.json();
|
|
12
|
+
const slug = body?.slug as string | undefined;
|
|
13
|
+
if (!slug) {
|
|
14
|
+
return NextResponse.json({ error: 'slug required' }, { status: 400 });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Hit Core REST: POST /api/v1/billing/checkout
|
|
18
|
+
// (Sprint 9 expõe via SDK direto)
|
|
19
|
+
return NextResponse.json({
|
|
20
|
+
redirectUrl: `https://minhaconta.neetru.com/checkout?slug=${slug}`,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template — `src/lib/neetru/billing/page.tsx` (gerado por `neetru add billing`).
|
|
3
|
-
*
|
|
4
|
-
* Página simples: lista planos + botão checkout via SDK.
|
|
5
|
-
*/
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import { useEffect, useState } from 'react';
|
|
9
|
-
import { createNeetruClient, type Product } from '@neetru/sdk';
|
|
10
|
-
|
|
11
|
-
const client = createNeetruClient({
|
|
12
|
-
apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
export default function BillingPage() {
|
|
16
|
-
const [products, setProducts] = useState<Product[]>([]);
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
client.catalog
|
|
19
|
-
.list()
|
|
20
|
-
.then(({ products }) => setProducts(products))
|
|
21
|
-
.catch((err) => console.error(err));
|
|
22
|
-
}, []);
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<main className="p-8">
|
|
26
|
-
<h1 className="text-3xl font-bold mb-6">Planos</h1>
|
|
27
|
-
<div className="grid gap-4 md:grid-cols-3">
|
|
28
|
-
{products.map((p) => (
|
|
29
|
-
<article key={p.slug} className="border p-6">
|
|
30
|
-
<h2 className="text-xl font-semibold">{p.name}</h2>
|
|
31
|
-
<p className="text-sm text-zinc-600 mt-1">{p.tagline}</p>
|
|
32
|
-
<a
|
|
33
|
-
href={`/checkout?slug=${p.slug}`}
|
|
34
|
-
className="inline-block mt-4 px-4 py-2 bg-zinc-900 text-white"
|
|
35
|
-
>
|
|
36
|
-
Assinar
|
|
37
|
-
</a>
|
|
38
|
-
</article>
|
|
39
|
-
))}
|
|
40
|
-
</div>
|
|
41
|
-
</main>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Template — `src/lib/neetru/billing/page.tsx` (gerado por `neetru add billing`).
|
|
3
|
+
*
|
|
4
|
+
* Página simples: lista planos + botão checkout via SDK.
|
|
5
|
+
*/
|
|
6
|
+
'use client';
|
|
7
|
+
|
|
8
|
+
import { useEffect, useState } from 'react';
|
|
9
|
+
import { createNeetruClient, type Product } from '@neetru/sdk';
|
|
10
|
+
|
|
11
|
+
const client = createNeetruClient({
|
|
12
|
+
apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default function BillingPage() {
|
|
16
|
+
const [products, setProducts] = useState<Product[]>([]);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
client.catalog
|
|
19
|
+
.list()
|
|
20
|
+
.then(({ products }) => setProducts(products))
|
|
21
|
+
.catch((err) => console.error(err));
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<main className="p-8">
|
|
26
|
+
<h1 className="text-3xl font-bold mb-6">Planos</h1>
|
|
27
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
28
|
+
{products.map((p) => (
|
|
29
|
+
<article key={p.slug} className="border p-6">
|
|
30
|
+
<h2 className="text-xl font-semibold">{p.name}</h2>
|
|
31
|
+
<p className="text-sm text-zinc-600 mt-1">{p.tagline}</p>
|
|
32
|
+
<a
|
|
33
|
+
href={`/checkout?slug=${p.slug}`}
|
|
34
|
+
className="inline-block mt-4 px-4 py-2 bg-zinc-900 text-white"
|
|
35
|
+
>
|
|
36
|
+
Assinar
|
|
37
|
+
</a>
|
|
38
|
+
</article>
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
</main>
|
|
42
|
+
);
|
|
43
|
+
}
|