@neetru/cli 2.7.5 → 2.8.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 +220 -220
- package/README.md +137 -137
- package/dist/cli-kit/format.d.ts +49 -0
- package/dist/cli-kit/format.js +88 -0
- package/dist/cli-kit/format.js.map +1 -0
- package/dist/cli-kit/glyphs.d.ts +22 -0
- package/dist/cli-kit/glyphs.js +22 -0
- package/dist/cli-kit/glyphs.js.map +1 -0
- package/dist/cli-kit/index.d.ts +13 -0
- package/dist/cli-kit/index.js +12 -0
- package/dist/cli-kit/index.js.map +1 -0
- package/dist/cli-kit/palette.d.ts +10 -0
- package/dist/cli-kit/palette.js +36 -0
- package/dist/cli-kit/palette.js.map +1 -0
- package/dist/commands/ai.js +8 -8
- package/dist/commands/autocomplete.js +34 -34
- package/dist/commands/db.d.ts +87 -7
- package/dist/commands/db.js +697 -126
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts +5 -0
- package/dist/commands/deploy.js +68 -0
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +68 -0
- package/dist/commands/dev.js +345 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/init.js +121 -121
- package/dist/commands/new.d.ts +6 -0
- package/dist/commands/new.js +31 -10
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/products-db.d.ts +1 -1
- package/dist/commands/products-db.js +17 -4
- package/dist/commands/products-db.js.map +1 -1
- package/dist/index.js +258 -42
- package/dist/index.js.map +1 -1
- package/dist/lib/ai/context.js +90 -90
- package/dist/lib/db-local/db-json.d.ts +63 -0
- package/dist/lib/db-local/db-json.js +189 -0
- package/dist/lib/db-local/db-json.js.map +1 -0
- package/dist/lib/db-local/env.d.ts +26 -0
- package/dist/lib/db-local/env.js +64 -0
- package/dist/lib/db-local/env.js.map +1 -0
- package/dist/lib/db-local/fingerprint.d.ts +8 -0
- package/dist/lib/db-local/fingerprint.js +28 -0
- package/dist/lib/db-local/fingerprint.js.map +1 -0
- package/dist/lib/db-local/index.d.ts +15 -0
- package/dist/lib/db-local/index.js +14 -0
- package/dist/lib/db-local/index.js.map +1 -0
- package/dist/lib/db-pipeline/build-deps.d.ts +14 -0
- package/dist/lib/db-pipeline/build-deps.js +158 -0
- package/dist/lib/db-pipeline/build-deps.js.map +1 -0
- package/dist/lib/db-pipeline/errors.d.ts +29 -0
- package/dist/lib/db-pipeline/errors.js +29 -0
- package/dist/lib/db-pipeline/errors.js.map +1 -0
- package/dist/lib/db-pipeline/index.d.ts +26 -0
- package/dist/lib/db-pipeline/index.js +25 -0
- package/dist/lib/db-pipeline/index.js.map +1 -0
- package/dist/lib/db-pipeline/pipeline.d.ts +13 -0
- package/dist/lib/db-pipeline/pipeline.js +119 -0
- package/dist/lib/db-pipeline/pipeline.js.map +1 -0
- package/dist/lib/db-pipeline/rehearse.d.ts +99 -0
- package/dist/lib/db-pipeline/rehearse.js +219 -0
- package/dist/lib/db-pipeline/rehearse.js.map +1 -0
- package/dist/lib/db-pipeline/types.d.ts +112 -0
- package/dist/lib/db-pipeline/types.js +20 -0
- package/dist/lib/db-pipeline/types.js.map +1 -0
- package/package.json +63 -62
- 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,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `neetru dev` — banco local Docker + watch de schema (M1 GAP-M1-4).
|
|
3
|
+
*
|
|
4
|
+
* Orquestra o ambiente de desenvolvimento local do produto:
|
|
5
|
+
*
|
|
6
|
+
* 1. Lê `.neetru/db.json` para descobrir engine e banco do produto.
|
|
7
|
+
* 2. Sobe (ou reutiliza) um container Docker compatível com a engine:
|
|
8
|
+
* - Postgres → `postgres:16-alpine`
|
|
9
|
+
* - MySQL → `mysql:8.0`
|
|
10
|
+
* - Firestore → aviso: use o emulador Firebase (`firebase emulators:start`)
|
|
11
|
+
* 3. Observa `db/schema.ts` (ou `--schema`): ao salvar, roda o pipeline
|
|
12
|
+
* `neetru db apply` contra o banco dev-local — "salvar = aplicado".
|
|
13
|
+
* 4. Encerra limpo no Ctrl-C: para o container se foi nós quem iniciamos.
|
|
14
|
+
*
|
|
15
|
+
* A lógica de Docker e fs-watch é injetada via `DevDeps` para que o comando
|
|
16
|
+
* seja completamente unit-testável sem container real.
|
|
17
|
+
*
|
|
18
|
+
* Plain PT-BR em todas as strings visíveis ao usuário.
|
|
19
|
+
*/
|
|
20
|
+
import * as fsSync from 'node:fs';
|
|
21
|
+
import * as path from 'node:path';
|
|
22
|
+
import { spawn } from 'node:child_process';
|
|
23
|
+
import chalk from 'chalk';
|
|
24
|
+
import ora from 'ora';
|
|
25
|
+
import { log } from '../utils/logger.js';
|
|
26
|
+
import { readDbJson } from '../lib/db-local/index.js';
|
|
27
|
+
import { runApplyPipeline, buildPipelineDeps, isPipelineError, } from '../lib/db-pipeline/index.js';
|
|
28
|
+
/** Caminho canônico do registry local de bancos. */
|
|
29
|
+
const DB_JSON_REL = '.neetru/db.json';
|
|
30
|
+
/** Caminho default do schema DrizzleORM. */
|
|
31
|
+
const DEFAULT_SCHEMA_PATH = 'db/schema.ts';
|
|
32
|
+
/** Arquivos aceitos como configuração do produto. */
|
|
33
|
+
const CONFIG_FILES = ['neetru.config.json', '.neetru.json'];
|
|
34
|
+
/**
|
|
35
|
+
* Mapeamento engine → imagem Docker.
|
|
36
|
+
*
|
|
37
|
+
* Engines sem suporte Docker nativo (Firestore) retornam `null` — o comando
|
|
38
|
+
* trata esse caso com um aviso explicativo.
|
|
39
|
+
*/
|
|
40
|
+
const ENGINE_TO_IMAGE = {
|
|
41
|
+
'vm-postgres-single': 'postgres:16-alpine',
|
|
42
|
+
'vm-postgres-cluster': 'postgres:16-alpine',
|
|
43
|
+
'vm-mysql-single': 'mysql:8.0',
|
|
44
|
+
'vm-mysql-cluster': 'mysql:8.0',
|
|
45
|
+
'cloud-sql-postgres': 'postgres:16-alpine',
|
|
46
|
+
'cloud-sql-mysql': 'mysql:8.0',
|
|
47
|
+
'firestore-instance': null, // sem container — usa emulador Firebase
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Variáveis de ambiente padrão por imagem Docker.
|
|
51
|
+
* Sane defaults que tornam o container imediatamente utilizável em dev-local.
|
|
52
|
+
*/
|
|
53
|
+
function defaultEnvVars(image) {
|
|
54
|
+
if (image.startsWith('postgres')) {
|
|
55
|
+
return [
|
|
56
|
+
'-e', 'POSTGRES_USER=neetru',
|
|
57
|
+
'-e', 'POSTGRES_PASSWORD=neetru_dev',
|
|
58
|
+
'-e', 'POSTGRES_DB=neetru_dev',
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
if (image.startsWith('mysql')) {
|
|
62
|
+
return [
|
|
63
|
+
'-e', 'MYSQL_ROOT_PASSWORD=neetru_dev',
|
|
64
|
+
'-e', 'MYSQL_DATABASE=neetru_dev',
|
|
65
|
+
'-e', 'MYSQL_USER=neetru',
|
|
66
|
+
'-e', 'MYSQL_PASSWORD=neetru_dev',
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Porta default por imagem Docker.
|
|
73
|
+
*/
|
|
74
|
+
function defaultPort(image) {
|
|
75
|
+
if (image.startsWith('postgres'))
|
|
76
|
+
return 5432;
|
|
77
|
+
if (image.startsWith('mysql'))
|
|
78
|
+
return 3306;
|
|
79
|
+
return 5432;
|
|
80
|
+
}
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Helpers internos
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
/** Lê o neetru.config.json do cwd ou retorna null. */
|
|
85
|
+
function loadProductConfig() {
|
|
86
|
+
for (const name of CONFIG_FILES) {
|
|
87
|
+
const filePath = path.resolve(process.cwd(), name);
|
|
88
|
+
if (!fsSync.existsSync(filePath))
|
|
89
|
+
continue;
|
|
90
|
+
try {
|
|
91
|
+
const raw = fsSync.readFileSync(filePath, 'utf8');
|
|
92
|
+
const parsed = JSON.parse(raw);
|
|
93
|
+
if (typeof parsed.slug !== 'string' || !parsed.slug)
|
|
94
|
+
return null;
|
|
95
|
+
return parsed;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
/** Nome canônico do container por banco. */
|
|
104
|
+
function containerName(productSlug, dbName) {
|
|
105
|
+
// ex.: "neetru-dev-meu-saas-principal"
|
|
106
|
+
return `neetru-dev-${productSlug}-${dbName}`.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Verifica se o container já está rodando.
|
|
110
|
+
* `docker ps -a --filter name=<name> --format {{.Status}}` → "Up N hours" se rodando.
|
|
111
|
+
*/
|
|
112
|
+
async function isContainerRunning(deps, name) {
|
|
113
|
+
const result = await deps.execDocker([
|
|
114
|
+
'ps', '-a',
|
|
115
|
+
'--filter', `name=^/${name}$`,
|
|
116
|
+
'--format', '{{.Status}}',
|
|
117
|
+
]);
|
|
118
|
+
return result.stdout.trim().toLowerCase().startsWith('up');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Inicia o container Docker.
|
|
122
|
+
* Retorna o ID do container iniciado.
|
|
123
|
+
*/
|
|
124
|
+
async function startContainer(deps, name, image) {
|
|
125
|
+
const port = defaultPort(image);
|
|
126
|
+
const envVars = defaultEnvVars(image);
|
|
127
|
+
const args = [
|
|
128
|
+
'run', '--detach',
|
|
129
|
+
'--name', name,
|
|
130
|
+
'-p', `${port}:${port}`,
|
|
131
|
+
...envVars,
|
|
132
|
+
image,
|
|
133
|
+
];
|
|
134
|
+
const result = await deps.execDocker(args);
|
|
135
|
+
return result.stdout.trim();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Para o container Docker.
|
|
139
|
+
*/
|
|
140
|
+
async function stopContainer(deps, name) {
|
|
141
|
+
await deps.execDocker(['stop', name]);
|
|
142
|
+
}
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// buildDevDeps — fiação de produção
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
/**
|
|
147
|
+
* Constrói as deps reais de produção para o `runDev`.
|
|
148
|
+
*
|
|
149
|
+
* `execDocker` → `child_process.spawn('docker', args)`
|
|
150
|
+
* `watchFile` → `fs.watch` nativo do Node.
|
|
151
|
+
*/
|
|
152
|
+
export function buildDevDeps() {
|
|
153
|
+
return {
|
|
154
|
+
execDocker(args) {
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
const child = spawn('docker', args, {
|
|
157
|
+
shell: process.platform === 'win32',
|
|
158
|
+
});
|
|
159
|
+
let stdout = '';
|
|
160
|
+
child.stdout?.on('data', (chunk) => { stdout += String(chunk); });
|
|
161
|
+
child.on('error', () => resolve({ stdout, exit: 1 }));
|
|
162
|
+
child.on('exit', (code) => resolve({ stdout, exit: code ?? 1 }));
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
watchFile(filePath, cb) {
|
|
166
|
+
const watcher = fsSync.watch(filePath, { persistent: false }, () => {
|
|
167
|
+
void (async () => {
|
|
168
|
+
try {
|
|
169
|
+
await cb();
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// erros do callback são tratados no próprio callback
|
|
173
|
+
}
|
|
174
|
+
})();
|
|
175
|
+
});
|
|
176
|
+
return () => watcher.close();
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
// runDev — o orquestrador
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
/**
|
|
184
|
+
* Executa o comando `neetru dev`.
|
|
185
|
+
*
|
|
186
|
+
* @param opts Opções do comando.
|
|
187
|
+
* @param deps Deps injetadas (default: fiação real de produção).
|
|
188
|
+
*/
|
|
189
|
+
export async function runDev(opts = {}, deps = buildDevDeps()) {
|
|
190
|
+
log.banner();
|
|
191
|
+
log.heading('neetru dev');
|
|
192
|
+
const cwd = process.cwd();
|
|
193
|
+
// ── 1. Carrega config do produto ──────────────────────────────────────────
|
|
194
|
+
const cfg = loadProductConfig();
|
|
195
|
+
if (!cfg) {
|
|
196
|
+
log.error('neetru.config.json não encontrado. Rode `neetru init` no diretório do produto.');
|
|
197
|
+
process.exit(1);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// ── 2. Lê .neetru/db.json ─────────────────────────────────────────────────
|
|
201
|
+
const dbJsonPath = path.resolve(cwd, DB_JSON_REL);
|
|
202
|
+
const dbJson = readDbJson(dbJsonPath);
|
|
203
|
+
if (dbJson.databases.length === 0) {
|
|
204
|
+
log.error(`Nenhum banco registrado em ${chalk.bold(DB_JSON_REL)}. ` +
|
|
205
|
+
'Rode `neetru db init` para registrar um banco primeiro.');
|
|
206
|
+
process.exit(1);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// ── 3. Resolve banco alvo ─────────────────────────────────────────────────
|
|
210
|
+
let dbEntry = dbJson.databases[0];
|
|
211
|
+
if (opts.db) {
|
|
212
|
+
const found = dbJson.databases.find((d) => d.name === opts.db);
|
|
213
|
+
if (!found) {
|
|
214
|
+
log.error(`Banco "${opts.db}" não encontrado em ${chalk.bold(DB_JSON_REL)}. ` +
|
|
215
|
+
`Bancos disponíveis: ${dbJson.databases.map((d) => d.name).join(', ')}.`);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
dbEntry = found;
|
|
220
|
+
}
|
|
221
|
+
const { name: dbName, engine, productId } = dbEntry;
|
|
222
|
+
const schemaFile = opts.schema ?? DEFAULT_SCHEMA_PATH;
|
|
223
|
+
const schemaAbs = path.resolve(cwd, schemaFile);
|
|
224
|
+
log.dim('');
|
|
225
|
+
log.dim(` Produto: ${chalk.bold(productId)}`);
|
|
226
|
+
log.dim(` Banco: ${chalk.bold(dbName)} ${chalk.dim('(' + engine + ')')}`);
|
|
227
|
+
log.dim(` Schema: ${schemaFile}`);
|
|
228
|
+
// ── 4. Verifica/inicia container Docker ──────────────────────────────────
|
|
229
|
+
const image = ENGINE_TO_IMAGE[engine] ?? ENGINE_TO_IMAGE[engine];
|
|
230
|
+
if (image === null || image === undefined) {
|
|
231
|
+
// Firestore ou engine sem Docker
|
|
232
|
+
log.warn(`Engine "${engine}" não usa container Docker local. ` +
|
|
233
|
+
'Para Firestore, use o emulador Firebase: ' +
|
|
234
|
+
chalk.cyan('firebase emulators:start --only firestore'));
|
|
235
|
+
log.dim(' O watch de schema ainda funcionará para registrar mudanças.');
|
|
236
|
+
}
|
|
237
|
+
const contName = containerName(cfg.slug, dbName);
|
|
238
|
+
let weStartedContainer = false;
|
|
239
|
+
if (image) {
|
|
240
|
+
const spinner = ora({ text: 'Verificando container Docker…', color: 'blue' }).start();
|
|
241
|
+
const running = await isContainerRunning(deps, contName);
|
|
242
|
+
if (running) {
|
|
243
|
+
spinner.succeed(`Container ${chalk.bold(contName)} já está rodando — reutilizando.`);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
spinner.text = `Iniciando ${chalk.bold(image)} como "${contName}"…`;
|
|
247
|
+
await startContainer(deps, contName, image);
|
|
248
|
+
weStartedContainer = true;
|
|
249
|
+
const port = defaultPort(image);
|
|
250
|
+
spinner.succeed(`Container iniciado: ${chalk.bold(contName)} ` +
|
|
251
|
+
`${chalk.dim('→ porta ' + port)}`);
|
|
252
|
+
const connExample = image.startsWith('postgres')
|
|
253
|
+
? `postgresql://neetru:neetru_dev@localhost:${port}/neetru_dev`
|
|
254
|
+
: `mysql://neetru:neetru_dev@localhost:${port}/neetru_dev`;
|
|
255
|
+
log.dim(` Conexão: ${chalk.cyan(connExample)}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// ── 5. Watch de schema ───────────────────────────────────────────────────
|
|
259
|
+
let stopWatcher = null;
|
|
260
|
+
if (fsSync.existsSync(schemaAbs)) {
|
|
261
|
+
log.dim('');
|
|
262
|
+
log.info(`Observando ${chalk.bold(schemaFile)} — salvar = aplicar migração.`);
|
|
263
|
+
log.dim(' (Ctrl-C para encerrar)');
|
|
264
|
+
stopWatcher = deps.watchFile(schemaAbs, async () => {
|
|
265
|
+
log.dim('');
|
|
266
|
+
log.info(`Schema alterado — aplicando pipeline (env: dev-local)…`);
|
|
267
|
+
const schemaSpinner = ora({ text: 'Rodando pipeline…', color: 'blue' }).start();
|
|
268
|
+
let result;
|
|
269
|
+
try {
|
|
270
|
+
const pipelineDeps = buildPipelineDeps({
|
|
271
|
+
// Em dev-local, a ensaiada é substituída por um stub de sucesso pois
|
|
272
|
+
// o container Docker que o `neetru dev` sobe SIM é o Postgres alvo —
|
|
273
|
+
// a ensaiada real seria redundante. O rehearse verdadeiro existe pra
|
|
274
|
+
// o `neetru db apply` (que usa um container EFÊMERO separado).
|
|
275
|
+
rehearseInContainer: async () => ({ ok: true }),
|
|
276
|
+
// Ajusta o pushToCore pra apontar ao banco local (dev-local).
|
|
277
|
+
});
|
|
278
|
+
result = await runApplyPipeline({
|
|
279
|
+
schemaPath: schemaAbs,
|
|
280
|
+
env: 'dev-local',
|
|
281
|
+
// BL-5 fix: passa o ID do banco dev-local (pode ser vazio se ainda
|
|
282
|
+
// não registrado; nesse caso o pipeline vai falhar na fase push com
|
|
283
|
+
// erro legível em vez de 400 silencioso).
|
|
284
|
+
dbId: dbEntry.ids['dev-local'] ?? '',
|
|
285
|
+
}, pipelineDeps);
|
|
286
|
+
schemaSpinner.stop();
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
schemaSpinner.fail('Pipeline falhou.');
|
|
290
|
+
if (isPipelineError(err)) {
|
|
291
|
+
const pe = err;
|
|
292
|
+
log.warn(` Fase "${pe.phase}": ${pe.message}`);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
log.warn(` Erro: ${err.message ?? String(err)}`);
|
|
296
|
+
}
|
|
297
|
+
return; // não encerra o processo — continua assistindo
|
|
298
|
+
}
|
|
299
|
+
if (result.status === 'no_changes') {
|
|
300
|
+
log.dim(' Sem mudanças no schema — nenhuma migração necessária.');
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const severityLabel = result.severity === 'destrutiva'
|
|
304
|
+
? chalk.red('destrutiva')
|
|
305
|
+
: chalk.green('aditiva');
|
|
306
|
+
log.success(`Migração ${chalk.bold(result.migrationId)} aplicada ` +
|
|
307
|
+
`(${severityLabel}, status: ${result.status}).`);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
log.warn(`Schema não encontrado em ${chalk.bold(schemaFile)}. ` +
|
|
312
|
+
'O watch não será ativado. Crie o arquivo e reinicie `neetru dev`.');
|
|
313
|
+
}
|
|
314
|
+
// ── 6. Aguarda Ctrl-C / autoStop ─────────────────────────────────────────
|
|
315
|
+
const teardown = async () => {
|
|
316
|
+
log.dim('');
|
|
317
|
+
log.info('Encerrando…');
|
|
318
|
+
if (stopWatcher) {
|
|
319
|
+
stopWatcher();
|
|
320
|
+
stopWatcher = null;
|
|
321
|
+
}
|
|
322
|
+
if (weStartedContainer && image) {
|
|
323
|
+
const stopSpinner = ora({
|
|
324
|
+
text: `Parando container ${contName}…`,
|
|
325
|
+
color: 'yellow',
|
|
326
|
+
}).start();
|
|
327
|
+
await stopContainer(deps, contName);
|
|
328
|
+
stopSpinner.succeed(`Container ${chalk.bold(contName)} parado.`);
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
if (opts.autoStop) {
|
|
332
|
+
// Modo de teste / CI — encerra imediatamente após o startup.
|
|
333
|
+
await teardown();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// Produção: bloqueia até Ctrl-C.
|
|
337
|
+
await new Promise((resolve) => {
|
|
338
|
+
const onSignal = () => {
|
|
339
|
+
teardown().then(resolve).catch(() => resolve());
|
|
340
|
+
};
|
|
341
|
+
process.once('SIGINT', onSignal);
|
|
342
|
+
process.once('SIGTERM', onSignal);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/init.js
CHANGED
|
@@ -298,96 +298,96 @@ async function scaffoldNextjs(dir, name, write) {
|
|
|
298
298
|
},
|
|
299
299
|
}, null, 2));
|
|
300
300
|
// next.config.mjs
|
|
301
|
-
await write(path.join(dir, 'next.config.mjs'), `/** @type {import('next').NextConfig} */
|
|
302
|
-
const nextConfig = {};
|
|
303
|
-
export default nextConfig;
|
|
301
|
+
await write(path.join(dir, 'next.config.mjs'), `/** @type {import('next').NextConfig} */
|
|
302
|
+
const nextConfig = {};
|
|
303
|
+
export default nextConfig;
|
|
304
304
|
`);
|
|
305
305
|
// Layout raiz
|
|
306
|
-
await write(path.join(dir, 'src', 'app', 'layout.tsx'), `import type { Metadata } from 'next';
|
|
307
|
-
|
|
308
|
-
export const metadata: Metadata = {
|
|
309
|
-
title: '${name}',
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
313
|
-
return (
|
|
314
|
-
<html lang="pt-BR">
|
|
315
|
-
<body>{children}</body>
|
|
316
|
-
</html>
|
|
317
|
-
);
|
|
318
|
-
}
|
|
306
|
+
await write(path.join(dir, 'src', 'app', 'layout.tsx'), `import type { Metadata } from 'next';
|
|
307
|
+
|
|
308
|
+
export const metadata: Metadata = {
|
|
309
|
+
title: '${name}',
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
313
|
+
return (
|
|
314
|
+
<html lang="pt-BR">
|
|
315
|
+
<body>{children}</body>
|
|
316
|
+
</html>
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
319
|
`);
|
|
320
320
|
// Página inicial com auth gate via SDK 1.1
|
|
321
|
-
await write(path.join(dir, 'src', 'app', 'page.tsx'), `// Produto Neetru — gerado por neetru init
|
|
322
|
-
// Auth via @neetru/sdk client (createNeetruClient + auth namespace)
|
|
323
|
-
|
|
324
|
-
'use client';
|
|
325
|
-
|
|
326
|
-
import { createNeetruClient } from '@neetru/sdk';
|
|
327
|
-
import { useEffect, useState } from 'react';
|
|
328
|
-
import type { NeetruUser } from '@neetru/sdk';
|
|
329
|
-
|
|
330
|
-
const neetru = createNeetruClient({
|
|
331
|
-
apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
|
|
332
|
-
env: (process.env.NEXT_PUBLIC_NEETRU_ENV as 'dev' | 'prod') ?? 'dev',
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
export default function HomePage() {
|
|
336
|
-
const [user, setUser] = useState<NeetruUser | null>(null);
|
|
337
|
-
const [loading, setLoading] = useState(true);
|
|
338
|
-
|
|
339
|
-
useEffect(() => {
|
|
340
|
-
let unsub: (() => void) | undefined;
|
|
341
|
-
neetru.auth.getUser().then((u) => {
|
|
342
|
-
setUser(u);
|
|
343
|
-
setLoading(false);
|
|
344
|
-
});
|
|
345
|
-
unsub = neetru.auth.onAuthStateChanged((u) => setUser(u));
|
|
346
|
-
return () => unsub?.();
|
|
347
|
-
}, []);
|
|
348
|
-
|
|
349
|
-
if (loading) return <main><p>Carregando...</p></main>;
|
|
350
|
-
if (!user) {
|
|
351
|
-
return (
|
|
352
|
-
<main>
|
|
353
|
-
<h1>${name}</h1>
|
|
354
|
-
<button onClick={() => neetru.auth.signIn()}>Entrar com Neetru</button>
|
|
355
|
-
</main>
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
return (
|
|
359
|
-
<main>
|
|
360
|
-
<h1>Bem-vindo, {user.email}</h1>
|
|
361
|
-
<p>UID: {user.uid}</p>
|
|
362
|
-
<button onClick={() => neetru.auth.signOut()}>Sair</button>
|
|
363
|
-
</main>
|
|
364
|
-
);
|
|
365
|
-
}
|
|
321
|
+
await write(path.join(dir, 'src', 'app', 'page.tsx'), `// Produto Neetru — gerado por neetru init
|
|
322
|
+
// Auth via @neetru/sdk client (createNeetruClient + auth namespace)
|
|
323
|
+
|
|
324
|
+
'use client';
|
|
325
|
+
|
|
326
|
+
import { createNeetruClient } from '@neetru/sdk';
|
|
327
|
+
import { useEffect, useState } from 'react';
|
|
328
|
+
import type { NeetruUser } from '@neetru/sdk';
|
|
329
|
+
|
|
330
|
+
const neetru = createNeetruClient({
|
|
331
|
+
apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
|
|
332
|
+
env: (process.env.NEXT_PUBLIC_NEETRU_ENV as 'dev' | 'prod') ?? 'dev',
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
export default function HomePage() {
|
|
336
|
+
const [user, setUser] = useState<NeetruUser | null>(null);
|
|
337
|
+
const [loading, setLoading] = useState(true);
|
|
338
|
+
|
|
339
|
+
useEffect(() => {
|
|
340
|
+
let unsub: (() => void) | undefined;
|
|
341
|
+
neetru.auth.getUser().then((u) => {
|
|
342
|
+
setUser(u);
|
|
343
|
+
setLoading(false);
|
|
344
|
+
});
|
|
345
|
+
unsub = neetru.auth.onAuthStateChanged((u) => setUser(u));
|
|
346
|
+
return () => unsub?.();
|
|
347
|
+
}, []);
|
|
348
|
+
|
|
349
|
+
if (loading) return <main><p>Carregando...</p></main>;
|
|
350
|
+
if (!user) {
|
|
351
|
+
return (
|
|
352
|
+
<main>
|
|
353
|
+
<h1>${name}</h1>
|
|
354
|
+
<button onClick={() => neetru.auth.signIn()}>Entrar com Neetru</button>
|
|
355
|
+
</main>
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return (
|
|
359
|
+
<main>
|
|
360
|
+
<h1>Bem-vindo, {user.email}</h1>
|
|
361
|
+
<p>UID: {user.uid}</p>
|
|
362
|
+
<button onClick={() => neetru.auth.signOut()}>Sair</button>
|
|
363
|
+
</main>
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
366
|
`);
|
|
367
367
|
// Middleware Next.js — gate de cookie de sessão em rotas privadas
|
|
368
|
-
await write(path.join(dir, 'src', 'middleware.ts'), `import { NextRequest, NextResponse } from 'next/server';
|
|
369
|
-
|
|
370
|
-
const PUBLIC_PATHS = ['/login', '/api/auth', '/_next', '/favicon.ico'];
|
|
371
|
-
|
|
372
|
-
export function middleware(request: NextRequest) {
|
|
373
|
-
const { pathname } = request.nextUrl;
|
|
374
|
-
if (PUBLIC_PATHS.some((p) => pathname.startsWith(p))) {
|
|
375
|
-
return NextResponse.next();
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const hasSession = request.cookies.has('__session');
|
|
379
|
-
if (!hasSession) {
|
|
380
|
-
const url = request.nextUrl.clone();
|
|
381
|
-
url.pathname = '/login';
|
|
382
|
-
return NextResponse.redirect(url);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return NextResponse.next();
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
export const config = {
|
|
389
|
-
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
|
|
390
|
-
};
|
|
368
|
+
await write(path.join(dir, 'src', 'middleware.ts'), `import { NextRequest, NextResponse } from 'next/server';
|
|
369
|
+
|
|
370
|
+
const PUBLIC_PATHS = ['/login', '/api/auth', '/_next', '/favicon.ico'];
|
|
371
|
+
|
|
372
|
+
export function middleware(request: NextRequest) {
|
|
373
|
+
const { pathname } = request.nextUrl;
|
|
374
|
+
if (PUBLIC_PATHS.some((p) => pathname.startsWith(p))) {
|
|
375
|
+
return NextResponse.next();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const hasSession = request.cookies.has('__session');
|
|
379
|
+
if (!hasSession) {
|
|
380
|
+
const url = request.nextUrl.clone();
|
|
381
|
+
url.pathname = '/login';
|
|
382
|
+
return NextResponse.redirect(url);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return NextResponse.next();
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export const config = {
|
|
389
|
+
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
|
|
390
|
+
};
|
|
391
391
|
`);
|
|
392
392
|
// tsconfig.json
|
|
393
393
|
await write(path.join(dir, 'tsconfig.json'), JSON.stringify({
|
|
@@ -433,43 +433,43 @@ async function scaffoldNodeApi(dir, name, write) {
|
|
|
433
433
|
'@types/node': '^22.0.0',
|
|
434
434
|
},
|
|
435
435
|
}, null, 2));
|
|
436
|
-
await write(path.join(dir, 'src', 'index.ts'), `import Fastify from 'fastify';
|
|
437
|
-
import { createNeetruClient } from '@neetru/sdk';
|
|
438
|
-
|
|
439
|
-
// Padrão @neetru/sdk@1.1 — namespaces server-side: entitlements/usage/telemetry.
|
|
440
|
-
const neetru = createNeetruClient({
|
|
441
|
-
apiKey: process.env.NEETRU_API_KEY,
|
|
442
|
-
env: (process.env.NEETRU_ENV as 'dev' | 'prod') ?? 'dev',
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
const PRODUCT_SLUG = process.env.NEETRU_PRODUCT_SLUG ?? '${name}';
|
|
446
|
-
|
|
447
|
-
const app = Fastify({ logger: true });
|
|
448
|
-
|
|
449
|
-
function requireEntitlement(feature: string) {
|
|
450
|
-
return async (
|
|
451
|
-
_request: import('fastify').FastifyRequest,
|
|
452
|
-
reply: import('fastify').FastifyReply,
|
|
453
|
-
) => {
|
|
454
|
-
const allowed = await neetru.entitlements.check(PRODUCT_SLUG, feature);
|
|
455
|
-
if (!allowed) {
|
|
456
|
-
return reply.code(403).send({ error: 'entitlement_denied', feature });
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
app.get('/health', async () => ({ status: 'ok' }));
|
|
462
|
-
|
|
463
|
-
app.get(
|
|
464
|
-
'/api/data',
|
|
465
|
-
{ preHandler: requireEntitlement('api-access') },
|
|
466
|
-
async () => {
|
|
467
|
-
await neetru.usage.report('api_call', 1, { productId: PRODUCT_SLUG });
|
|
468
|
-
return { data: [] };
|
|
469
|
-
},
|
|
470
|
-
);
|
|
471
|
-
|
|
472
|
-
await app.listen({ port: 3000, host: '0.0.0.0' });
|
|
436
|
+
await write(path.join(dir, 'src', 'index.ts'), `import Fastify from 'fastify';
|
|
437
|
+
import { createNeetruClient } from '@neetru/sdk';
|
|
438
|
+
|
|
439
|
+
// Padrão @neetru/sdk@1.1 — namespaces server-side: entitlements/usage/telemetry.
|
|
440
|
+
const neetru = createNeetruClient({
|
|
441
|
+
apiKey: process.env.NEETRU_API_KEY,
|
|
442
|
+
env: (process.env.NEETRU_ENV as 'dev' | 'prod') ?? 'dev',
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const PRODUCT_SLUG = process.env.NEETRU_PRODUCT_SLUG ?? '${name}';
|
|
446
|
+
|
|
447
|
+
const app = Fastify({ logger: true });
|
|
448
|
+
|
|
449
|
+
function requireEntitlement(feature: string) {
|
|
450
|
+
return async (
|
|
451
|
+
_request: import('fastify').FastifyRequest,
|
|
452
|
+
reply: import('fastify').FastifyReply,
|
|
453
|
+
) => {
|
|
454
|
+
const allowed = await neetru.entitlements.check(PRODUCT_SLUG, feature);
|
|
455
|
+
if (!allowed) {
|
|
456
|
+
return reply.code(403).send({ error: 'entitlement_denied', feature });
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
app.get('/health', async () => ({ status: 'ok' }));
|
|
462
|
+
|
|
463
|
+
app.get(
|
|
464
|
+
'/api/data',
|
|
465
|
+
{ preHandler: requireEntitlement('api-access') },
|
|
466
|
+
async () => {
|
|
467
|
+
await neetru.usage.report('api_call', 1, { productId: PRODUCT_SLUG });
|
|
468
|
+
return { data: [] };
|
|
469
|
+
},
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
await app.listen({ port: 3000, host: '0.0.0.0' });
|
|
473
473
|
`);
|
|
474
474
|
}
|
|
475
475
|
//# sourceMappingURL=init.js.map
|
package/dist/commands/new.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export interface NewMacroOptions {
|
|
|
7
7
|
skipInit?: boolean;
|
|
8
8
|
/** Pula a abertura do browser (útil em CI). */
|
|
9
9
|
skipOpen?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* GAP-X-6: pula o 5º passo de inicialização do banco de dados.
|
|
12
|
+
* Útil quando o produto não precisa de banco ou quando o dev prefere
|
|
13
|
+
* rodar `neetru db init` manualmente depois.
|
|
14
|
+
*/
|
|
15
|
+
skipDbInit?: boolean;
|
|
10
16
|
json?: boolean;
|
|
11
17
|
}
|
|
12
18
|
export declare function runNewMacro(name: string, opts?: NewMacroOptions): Promise<void>;
|