@neetru/cli 2.24.0 → 2.25.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 (41) hide show
  1. package/dist/commands/ai.js +8 -8
  2. package/dist/commands/bootstrap.js +18 -1
  3. package/dist/commands/bootstrap.js.map +1 -1
  4. package/dist/commands/deploy.js +2 -0
  5. package/dist/commands/deploy.js.map +1 -1
  6. package/dist/commands/deployments.d.ts +35 -0
  7. package/dist/commands/deployments.js +149 -1
  8. package/dist/commands/deployments.js.map +1 -1
  9. package/dist/commands/dev-up.js +82 -12
  10. package/dist/commands/dev-up.js.map +1 -1
  11. package/dist/commands/doctor.js +10 -4
  12. package/dist/commands/doctor.js.map +1 -1
  13. package/dist/commands/init.js +147 -147
  14. package/dist/commands/promote.js +14 -0
  15. package/dist/commands/promote.js.map +1 -1
  16. package/dist/index.js +23 -10
  17. package/dist/index.js.map +1 -1
  18. package/dist/lib/ai/context.js +91 -91
  19. package/dist/lib/compose-generator.d.ts +36 -0
  20. package/dist/lib/compose-generator.js +148 -0
  21. package/dist/lib/compose-generator.js.map +1 -0
  22. package/dist/lib/config-schema.d.ts +18 -0
  23. package/dist/lib/config-schema.js +4 -0
  24. package/dist/lib/config-schema.js.map +1 -1
  25. package/package.json +1 -1
  26. package/templates/auth/callback.ts +22 -22
  27. package/templates/auth/sign-in.tsx +41 -41
  28. package/templates/billing/checkout.ts +22 -22
  29. package/templates/billing/page.tsx +43 -43
  30. package/templates/dev/Dockerfile.agent +39 -0
  31. package/templates/dev/agent-entrypoint.sh +41 -0
  32. package/templates/dev/docker-compose.dev.yml +63 -0
  33. package/templates/support/ticket-form.tsx +68 -68
  34. package/templates/usage/track.ts +30 -30
  35. package/templates/users/profile.tsx +43 -43
  36. package/dist/commands/fn.d.ts +0 -6
  37. package/dist/commands/fn.js +0 -88
  38. package/dist/commands/fn.js.map +0 -1
  39. package/dist/commands/marketplace.d.ts +0 -36
  40. package/dist/commands/marketplace.js +0 -585
  41. package/dist/commands/marketplace.js.map +0 -1
@@ -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
+ }
@@ -0,0 +1,39 @@
1
+ # Neetru Agent — modo dev (Docker container, sem systemd)
2
+ #
3
+ # Em produção, o agente roda como systemd service na VM.
4
+ # Em dev-local, roda como processo Node direto no container.
5
+ # O deploy do app SaaS é feito como child process (não systemd unit).
6
+ #
7
+ # Build:
8
+ # docker build -f Dockerfile.agent -t neetru-agent-dev .
9
+
10
+ FROM node:22-slim
11
+
12
+ # Dependências do agente em produção (apt, certbot, etc.)
13
+ RUN apt-get update && apt-get install -y --no-install-recommends \
14
+ curl ca-certificates systemctl \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ # Diretório do agente
18
+ WORKDIR /opt/neetru
19
+
20
+ # Baixa o agente mais recente do Core
21
+ ARG CORE_URL=https://core.neetru.com
22
+ ENV NEETRU_CORE_URL=${CORE_URL}
23
+
24
+ # Download do binário (fallback: usa curl se GCS não disponível)
25
+ RUN ARCH=$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/') && \
26
+ curl -fsSL -o /usr/local/bin/neetru-agent \
27
+ "${NEETRU_CORE_URL}/releases/latest/neetru-agent-linux-${ARCH}" || \
28
+ echo "Agente não encontrado no Core — será montado via volume" && \
29
+ chmod +x /usr/local/bin/neetru-agent || true
30
+
31
+ # Entrypoint: agente em modo dev
32
+ # - NEETRU_DEV_MODE=true desabilita systemd, usa child_process direto
33
+ # - NEETRU_APP_PORT define a porta onde o app SaaS vai rodar
34
+ COPY templates/dev/agent-entrypoint.sh /usr/local/bin/neetru-agent-entrypoint
35
+ RUN chmod +x /usr/local/bin/neetru-agent-entrypoint
36
+
37
+ EXPOSE 3000
38
+
39
+ ENTRYPOINT ["/usr/local/bin/neetru-agent-entrypoint"]
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+ # Neetru Agent — entrypoint modo dev (Docker container)
3
+ #
4
+ # Em modo dev, o agente NAO usa systemd. Em vez disso:
5
+ # - Deploy = child process (npm install + node server)
6
+ # - Funções = child process (neetru-functions)
7
+ # - Healthcheck = /health endpoint no próprio agente
8
+ #
9
+ # Env vars obrigatórias:
10
+ # NEETRU_SERVER_ID — id do servidor (ex: dev-local-meuproduto)
11
+ # NEETRU_CORE_URL — URL do Core (ex: https://core.neetru.com)
12
+ # NEETRU_FIREBASE_PROJECT — projeto Firebase
13
+ # NEETRU_DEV_MODE — "true" ativa modo dev
14
+
15
+ set -e
16
+
17
+ echo "═══════════════════════════════════════════"
18
+ echo " Neetru Agent — Dev Mode"
19
+ echo " Server: ${NEETRU_SERVER_ID}"
20
+ echo " Core: ${NEETRU_CORE_URL}"
21
+ echo "═══════════════════════════════════════════"
22
+
23
+ # Verifica binário
24
+ if [ ! -f /usr/local/bin/neetru-agent ]; then
25
+ echo "[AGENT] Binário não encontrado. Montando via volume..."
26
+ echo "[AGENT] Certifique-se de que o agente está em /opt/neetru/neetru-agent"
27
+ ls -la /opt/neetru/ || true
28
+ fi
29
+
30
+ # Cria diretórios necessários
31
+ mkdir -p /var/cache/neetru /opt/neetru/deploys
32
+
33
+ # Inicia o agente
34
+ echo "[AGENT] Iniciando agente Neetru..."
35
+ exec node /usr/local/bin/neetru-agent 2>&1 || exec node /opt/neetru/neetru-agent 2>&1 || {
36
+ echo "[AGENT] ERRO: Não foi possível iniciar o agente."
37
+ echo "[AGENT] Verifique se o binário existe em /usr/local/bin/neetru-agent"
38
+ echo "[AGENT] ou monte o binário via volume em /opt/neetru/neetru-agent"
39
+ sleep 10
40
+ exit 1
41
+ }
@@ -0,0 +1,63 @@
1
+ # Neetru Dev Local — emulador de VM ({{ENGINE}})
2
+ # Gerado por `neetru dev up`. Modifique o neetru.config.json e rode novamente.
3
+ #
4
+ # Este compose simula uma VM de produção Neetru:
5
+ # 1. Banco de dados ({{ENGINE}}) = mesmo engine que vai pra produção
6
+ # 2. Agente Neetru = recebe comandos do Core, faz deploy, npm install, healthcheck
7
+ # 3. App SaaS = deployado pelo agente, acessível em http://localhost:{{APP_PORT}}
8
+ #
9
+ # Uso:
10
+ # neetru dev up # gera este compose + sobe tudo
11
+ # docker compose -f neetru-compose.dev.yml up -d # manual
12
+ # docker compose -f neetru-compose.dev.yml down # desliga
13
+
14
+ services:
15
+ # ── Banco de dados ({{ENGINE}}) ────────────────────────────────────────────
16
+ database:
17
+ image: {{DB_IMAGE}}
18
+ container_name: neetru-dev-db
19
+ environment:
20
+ {{DB_ENV}}
21
+ ports:
22
+ - "{{DB_PORT}}:{{DB_INTERNAL_PORT}}"
23
+ volumes:
24
+ - neetru-db-data:{{DB_DATA_DIR}}
25
+ healthcheck:
26
+ {{DB_HEALTHCHECK}}
27
+ restart: unless-stopped
28
+ networks:
29
+ - neetru-dev-net
30
+
31
+ # ── Agente Neetru (modo dev — sem systemd) ────────────────────────────────
32
+ agent:
33
+ build:
34
+ context: .
35
+ dockerfile: Dockerfile.agent
36
+ container_name: neetru-dev-agent
37
+ environment:
38
+ - NEETRU_SERVER_ID=dev-local-{{PRODUCT_SLUG}}
39
+ - NEETRU_CORE_URL={{CORE_URL}}
40
+ - NEETRU_FIREBASE_PROJECT={{FIREBASE_PROJECT}}
41
+ - NEETRU_FIREBASE_API_KEY={{FIREBASE_API_KEY}}
42
+ - NEETRU_DEV_MODE=true
43
+ - NEETRU_APP_PORT={{APP_PORT}}
44
+ ports:
45
+ - "{{APP_PORT}}:{{APP_PORT}}"
46
+ volumes:
47
+ - /var/run/docker.sock:/var/run/docker.sock
48
+ - neetru-agent-data:/var/cache/neetru
49
+ - .:/app/product:cached
50
+ depends_on:
51
+ database:
52
+ condition: service_healthy
53
+ restart: unless-stopped
54
+ networks:
55
+ - neetru-dev-net
56
+
57
+ volumes:
58
+ neetru-db-data:
59
+ neetru-agent-data:
60
+
61
+ networks:
62
+ neetru-dev-net:
63
+ driver: bridge
@@ -1,68 +1,68 @@
1
- /**
2
- * Template — `src/lib/neetru/support/ticket-form.tsx` (gerado por `neetru add support`).
3
- *
4
- * Form de suporte: cria ticket via SDK.
5
- */
6
- 'use client';
7
-
8
- import { useState } from 'react';
9
- import { createNeetruClient } from '@neetru/sdk';
10
-
11
- const client = createNeetruClient({
12
- apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
13
- });
14
-
15
- export function SupportTicketForm() {
16
- const [subject, setSubject] = useState('');
17
- const [message, setMessage] = useState('');
18
- const [submitting, setSubmitting] = useState(false);
19
- const [result, setResult] = useState<string | null>(null);
20
-
21
- async function handleSubmit(e: React.FormEvent) {
22
- e.preventDefault();
23
- setSubmitting(true);
24
- try {
25
- const ticket = await client.support.createTicket({ subject, message });
26
- setResult(`Ticket criado: ${ticket.id}`);
27
- setSubject('');
28
- setMessage('');
29
- } catch (err) {
30
- setResult('Falha ao criar ticket.');
31
- console.error(err);
32
- } finally {
33
- setSubmitting(false);
34
- }
35
- }
36
-
37
- return (
38
- <form onSubmit={handleSubmit} className="grid gap-3 max-w-md">
39
- <label className="grid gap-1">
40
- <span className="text-sm font-medium">Assunto</span>
41
- <input
42
- required
43
- value={subject}
44
- onChange={(e) => setSubject(e.target.value)}
45
- className="border px-3 py-2"
46
- />
47
- </label>
48
- <label className="grid gap-1">
49
- <span className="text-sm font-medium">Mensagem</span>
50
- <textarea
51
- required
52
- rows={5}
53
- value={message}
54
- onChange={(e) => setMessage(e.target.value)}
55
- className="border px-3 py-2"
56
- />
57
- </label>
58
- <button
59
- type="submit"
60
- disabled={submitting}
61
- className="px-4 py-2 bg-zinc-900 text-white"
62
- >
63
- {submitting ? 'Enviando...' : 'Enviar'}
64
- </button>
65
- {result && <p className="text-sm">{result}</p>}
66
- </form>
67
- );
68
- }
1
+ /**
2
+ * Template — `src/lib/neetru/support/ticket-form.tsx` (gerado por `neetru add support`).
3
+ *
4
+ * Form de suporte: cria ticket via SDK.
5
+ */
6
+ 'use client';
7
+
8
+ import { useState } from 'react';
9
+ import { createNeetruClient } from '@neetru/sdk';
10
+
11
+ const client = createNeetruClient({
12
+ apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
13
+ });
14
+
15
+ export function SupportTicketForm() {
16
+ const [subject, setSubject] = useState('');
17
+ const [message, setMessage] = useState('');
18
+ const [submitting, setSubmitting] = useState(false);
19
+ const [result, setResult] = useState<string | null>(null);
20
+
21
+ async function handleSubmit(e: React.FormEvent) {
22
+ e.preventDefault();
23
+ setSubmitting(true);
24
+ try {
25
+ const ticket = await client.support.createTicket({ subject, message });
26
+ setResult(`Ticket criado: ${ticket.id}`);
27
+ setSubject('');
28
+ setMessage('');
29
+ } catch (err) {
30
+ setResult('Falha ao criar ticket.');
31
+ console.error(err);
32
+ } finally {
33
+ setSubmitting(false);
34
+ }
35
+ }
36
+
37
+ return (
38
+ <form onSubmit={handleSubmit} className="grid gap-3 max-w-md">
39
+ <label className="grid gap-1">
40
+ <span className="text-sm font-medium">Assunto</span>
41
+ <input
42
+ required
43
+ value={subject}
44
+ onChange={(e) => setSubject(e.target.value)}
45
+ className="border px-3 py-2"
46
+ />
47
+ </label>
48
+ <label className="grid gap-1">
49
+ <span className="text-sm font-medium">Mensagem</span>
50
+ <textarea
51
+ required
52
+ rows={5}
53
+ value={message}
54
+ onChange={(e) => setMessage(e.target.value)}
55
+ className="border px-3 py-2"
56
+ />
57
+ </label>
58
+ <button
59
+ type="submit"
60
+ disabled={submitting}
61
+ className="px-4 py-2 bg-zinc-900 text-white"
62
+ >
63
+ {submitting ? 'Enviando...' : 'Enviar'}
64
+ </button>
65
+ {result && <p className="text-sm">{result}</p>}
66
+ </form>
67
+ );
68
+ }
@@ -1,30 +1,30 @@
1
- /**
2
- * Template — `src/lib/neetru/usage/track.ts` (gerado por `neetru add usage`).
3
- *
4
- * Helper para reportar uso de resources metered ao Core.
5
- *
6
- * @example
7
- * ```ts
8
- * import { reportApiCall } from '@/lib/neetru/usage/track';
9
- * await reportApiCall();
10
- * ```
11
- */
12
- import { createNeetruClient } from '@neetru/sdk';
13
-
14
- const client = createNeetruClient({
15
- apiKey: process.env.NEETRU_API_KEY,
16
- productId: process.env.NEETRU_PRODUCT_ID,
17
- tenantId: process.env.NEETRU_TENANT_ID,
18
- });
19
-
20
- export async function reportApiCall(qty = 1): Promise<void> {
21
- try {
22
- await client.usage.report('api_calls', qty);
23
- } catch (err) {
24
- console.warn('usage.report failed', err);
25
- }
26
- }
27
-
28
- export async function checkApiCallLimit() {
29
- return client.usage.check('api_calls');
30
- }
1
+ /**
2
+ * Template — `src/lib/neetru/usage/track.ts` (gerado por `neetru add usage`).
3
+ *
4
+ * Helper para reportar uso de resources metered ao Core.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { reportApiCall } from '@/lib/neetru/usage/track';
9
+ * await reportApiCall();
10
+ * ```
11
+ */
12
+ import { createNeetruClient } from '@neetru/sdk';
13
+
14
+ const client = createNeetruClient({
15
+ apiKey: process.env.NEETRU_API_KEY,
16
+ productId: process.env.NEETRU_PRODUCT_ID,
17
+ tenantId: process.env.NEETRU_TENANT_ID,
18
+ });
19
+
20
+ export async function reportApiCall(qty = 1): Promise<void> {
21
+ try {
22
+ await client.usage.report('api_calls', qty);
23
+ } catch (err) {
24
+ console.warn('usage.report failed', err);
25
+ }
26
+ }
27
+
28
+ export async function checkApiCallLimit() {
29
+ return client.usage.check('api_calls');
30
+ }
@@ -1,43 +1,43 @@
1
- /**
2
- * Template — `src/lib/neetru/users/profile.tsx` (gerado por `neetru add users`).
3
- *
4
- * Componente de perfil mostra dados do user via SDK.
5
- */
6
- 'use client';
7
-
8
- import { useEffect, useState } from 'react';
9
- import { createNeetruClient, type NeetruUser } from '@neetru/sdk';
10
-
11
- const client = createNeetruClient({
12
- apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
13
- });
14
-
15
- export function UserProfile() {
16
- const [user, setUser] = useState<NeetruUser | null>(null);
17
- useEffect(() => {
18
- return client.auth.onAuthStateChanged(setUser);
19
- }, []);
20
-
21
- if (!user) return <p>Não autenticado.</p>;
22
-
23
- return (
24
- <div className="border p-4">
25
- <p>
26
- <strong>Nome:</strong> {user.displayName ?? '—'}
27
- </p>
28
- <p>
29
- <strong>Email:</strong> {user.email}
30
- </p>
31
- <p>
32
- <strong>UID:</strong> {user.uid}
33
- </p>
34
- <button
35
- type="button"
36
- onClick={() => client.auth.signOut()}
37
- className="mt-4 px-3 py-1 border"
38
- >
39
- Sair
40
- </button>
41
- </div>
42
- );
43
- }
1
+ /**
2
+ * Template — `src/lib/neetru/users/profile.tsx` (gerado por `neetru add users`).
3
+ *
4
+ * Componente de perfil mostra dados do user via SDK.
5
+ */
6
+ 'use client';
7
+
8
+ import { useEffect, useState } from 'react';
9
+ import { createNeetruClient, type NeetruUser } from '@neetru/sdk';
10
+
11
+ const client = createNeetruClient({
12
+ apiKey: process.env.NEXT_PUBLIC_NEETRU_API_KEY,
13
+ });
14
+
15
+ export function UserProfile() {
16
+ const [user, setUser] = useState<NeetruUser | null>(null);
17
+ useEffect(() => {
18
+ return client.auth.onAuthStateChanged(setUser);
19
+ }, []);
20
+
21
+ if (!user) return <p>Não autenticado.</p>;
22
+
23
+ return (
24
+ <div className="border p-4">
25
+ <p>
26
+ <strong>Nome:</strong> {user.displayName ?? '—'}
27
+ </p>
28
+ <p>
29
+ <strong>Email:</strong> {user.email}
30
+ </p>
31
+ <p>
32
+ <strong>UID:</strong> {user.uid}
33
+ </p>
34
+ <button
35
+ type="button"
36
+ onClick={() => client.auth.signOut()}
37
+ className="mt-4 px-3 py-1 border"
38
+ >
39
+ Sair
40
+ </button>
41
+ </div>
42
+ );
43
+ }
@@ -1,6 +0,0 @@
1
- export interface FnDeployOptions {
2
- version?: string;
3
- channel?: 'stable' | 'beta' | 'alpha';
4
- spec?: string;
5
- }
6
- export declare function runFnDeploy(opts?: FnDeployOptions): Promise<void>;
@@ -1,88 +0,0 @@
1
- /**
2
- * `neetru fn` — gestão de Functions/APIs do produto.
3
- *
4
- * Sprint 10 (CLI 1.4) — `neetru fn deploy`.
5
- * Stub: chama API Core (`/cli/v1/fn/deploy`) registrando uma nova versão da
6
- * API publicada no catálogo `neetru-apis` (Sprint 7 — `api-catalog/`).
7
- *
8
- * NOTA: O endpoint real ainda não existe (pendente Sprint 11). Por agora
9
- * o command apresenta o fluxo + faz uma chamada que retorna 404 ou 501 —
10
- * trata gracefully como "feature em construção" pra o owner saber que o
11
- * comando está wired mas o backend não está pronto.
12
- */
13
- import * as fs from 'node:fs/promises';
14
- import * as fsSync from 'node:fs';
15
- import * as path from 'node:path';
16
- import chalk from 'chalk';
17
- import { log } from '../utils/logger.js';
18
- import { apiRequest, CliApiError, CliNetworkError } from '../lib/api-client.js';
19
- import { safeExit } from '../utils/safe-exit.js';
20
- const CONFIG_FILENAMES = ['neetru.config.json', '.neetru.json'];
21
- async function loadProductConfig() {
22
- for (const name of CONFIG_FILENAMES) {
23
- const filePath = path.resolve(process.cwd(), name);
24
- if (fsSync.existsSync(filePath)) {
25
- try {
26
- const raw = await fs.readFile(filePath, 'utf8');
27
- return JSON.parse(raw);
28
- }
29
- catch {
30
- return null;
31
- }
32
- }
33
- }
34
- return null;
35
- }
36
- export async function runFnDeploy(opts = {}) {
37
- log.banner();
38
- log.heading('neetru fn deploy');
39
- const cfg = await loadProductConfig();
40
- if (!cfg) {
41
- log.error('neetru.config.json não encontrado.');
42
- safeExit(1);
43
- return;
44
- }
45
- const version = opts.version ?? cfg.apiVersion ?? 'v1';
46
- const channel = opts.channel ?? 'stable';
47
- // Optional spec file (OpenAPI / JSON schema). Apenas valida existência —
48
- // upload real virá no Sprint 11.
49
- if (opts.spec) {
50
- const specAbs = path.resolve(process.cwd(), opts.spec);
51
- if (!fsSync.existsSync(specAbs)) {
52
- log.error(`Spec não encontrado: ${opts.spec}`);
53
- safeExit(2);
54
- return;
55
- }
56
- log.info(`Spec carregado: ${chalk.bold(opts.spec)}`);
57
- }
58
- log.info(`Registering API ${chalk.bold(cfg.slug)} ${chalk.bold(version)} (${channel}) ...`);
59
- try {
60
- const r = await apiRequest('/cli/v1/fn/deploy', {
61
- method: 'POST',
62
- body: { productId: cfg.slug, apiVersion: version, channel, hasSpec: !!opts.spec },
63
- });
64
- log.success(`API ${r.productId}@${r.apiVersion} registrada no canal ${r.channel}.`);
65
- log.dim(` registered=${r.registered}`);
66
- }
67
- catch (err) {
68
- if (err instanceof CliApiError) {
69
- if (err.status === 404 || err.status === 501) {
70
- log.warn(`Endpoint /cli/v1/fn/deploy ainda não disponível (${err.status}).`);
71
- log.dim(' Esta funcionalidade entra em build no Sprint 11. Ver docs/PLATFORM_RELATORIO_FINAL_CTO.md.');
72
- safeExit(0);
73
- return;
74
- }
75
- log.error(`API ${err.status}: ${err.message}`);
76
- safeExit(3);
77
- return;
78
- }
79
- if (err instanceof CliNetworkError) {
80
- log.error(`Conexão falhou: ${err.message}`);
81
- safeExit(4);
82
- return;
83
- }
84
- log.error(err instanceof Error ? err.message : String(err));
85
- safeExit(5);
86
- }
87
- }
88
- //# sourceMappingURL=fn.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fn.js","sourceRoot":"","sources":["../../src/commands/fn.ts"],"names":[],"mappings":"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"}
@@ -1,36 +0,0 @@
1
- export declare function getCacheDir(): string;
2
- /**
3
- * Resolve o diretorio fonte das skills no cache local.
4
- *
5
- * Suporta 2 estruturas no repo neetru-libs/claude-skills/:
6
- *
7
- * 1. Marketplace estruturado (atual): plugins/PLUGIN/skills/SKILL/SKILL.md
8
- * - descobre todos os plugins/PLUGIN/skills/ e retorna o primeiro.
9
- * 2. Plugin direto (legado): skills/SKILL/SKILL.md
10
- * - retorna single path.
11
- *
12
- * Pra simplicidade, esta funcao devolve UMA root virtual:
13
- * - Se existir claude-skills/plugins/PLUGIN/skills/, retorna a primeira (assume 1 plugin).
14
- * - Senao, fallback pra claude-skills/skills/ (estrutura legada).
15
- */
16
- export declare function getSkillsSourceDir(): string;
17
- export declare function getClaudeSkillsDir(): string;
18
- export interface SkillInfo {
19
- name: string;
20
- description: string;
21
- version: string;
22
- installed: boolean;
23
- }
24
- export declare function listAvailableSkills(): Promise<SkillInfo[]>;
25
- export declare function runSkillsInstall(): Promise<void>;
26
- export declare function runSkillsUpdate(): Promise<void>;
27
- export declare function runSkillsList(): Promise<void>;
28
- export declare function runSkillsUninstall(opts?: {
29
- yes?: boolean;
30
- }): Promise<void>;
31
- export declare function runSdkInit(): Promise<void>;
32
- export declare function runSdkTemplates(): Promise<void>;
33
- export declare function runSdkAddTemplate(template: string, opts?: {
34
- force?: boolean;
35
- }): Promise<void>;
36
- export declare function runMarketplaceBrowse(): Promise<void>;