fg-tracker-mcp 0.4.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 +15 -0
- package/README.md +83 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +51 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +103 -0
- package/dist/client.js +166 -0
- package/dist/client.js.map +1 -0
- package/dist/database.d.ts +15 -0
- package/dist/database.js +119 -0
- package/dist/database.js.map +1 -0
- package/dist/docs.d.ts +13 -0
- package/dist/docs.js +127 -0
- package/dist/docs.js.map +1 -0
- package/dist/format.d.ts +27 -0
- package/dist/format.js +103 -0
- package/dist/format.js.map +1 -0
- package/dist/guide.d.ts +19 -0
- package/dist/guide.js +490 -0
- package/dist/guide.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.js +418 -0
- package/dist/server.js.map +1 -0
- package/package.json +71 -0
package/dist/docs.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conteúdo estático: resource `fg-tracker://docs/quickstart` e o prompt
|
|
3
|
+
* `instrument-project`.
|
|
4
|
+
*/
|
|
5
|
+
export const QUICKSTART_URI = 'fg-tracker://docs/quickstart';
|
|
6
|
+
/** @deprecated URI do `stread-track-mcp` ≤ 0.3; ainda registrada como alias, removida na 1.0. */
|
|
7
|
+
export const LEGACY_QUICKSTART_URI = 'stread-track://docs/quickstart';
|
|
8
|
+
export function quickstartMarkdown(endpoint) {
|
|
9
|
+
return `# FG Tracker — quickstart
|
|
10
|
+
|
|
11
|
+
APM leve para Node: traces (Express/NestJS/Next.js/Fastify), queries pg, chamadas HTTP de saída, logs e detecção automática de **N+1**, **loops**, **endpoints lentos** e **erros**. API em \`${endpoint}\` (Swagger em \`${endpoint}/docs\`).
|
|
12
|
+
|
|
13
|
+
## 1. Projeto e chave
|
|
14
|
+
- \`track_list_projects\` lista os projetos do usuário do token; \`track_create_project { name }\` cria um e devolve \`apiKey\` (\`stk_...\`).
|
|
15
|
+
- A chave vai no header \`x-fg-tracker-key\` da ingestão e em \`FG_TRACKER_KEY\` no app instrumentado.
|
|
16
|
+
|
|
17
|
+
## 2. SDK (\`fg-tracker-sdk\`)
|
|
18
|
+
\`\`\`ts
|
|
19
|
+
import { createTracker } from 'fg-tracker-sdk';
|
|
20
|
+
const tracker = createTracker({
|
|
21
|
+
apiKey: process.env.FG_TRACKER_KEY!, endpoint: '${endpoint}', serviceName: 'minha-app',
|
|
22
|
+
release: process.env.FG_TRACKER_RELEASE, // ou detectado de GITHUB_SHA/VERCEL_GIT_COMMIT_SHA → "minha-app@<sha>"
|
|
23
|
+
instrumentGlobalFetch: true, // chamadas a provedores (OpenRouter, Mureka…) viram spans http.client + traceparent
|
|
24
|
+
captureGlobalErrors: true, // uncaughtException/unhandledRejection viram issues
|
|
25
|
+
});
|
|
26
|
+
app.use(tracker.express()); // Express / NestJS — PRIMEIRO middleware (continua traceparent, lê req.user.id)
|
|
27
|
+
app.use(routes); app.use(tracker.expressErrorHandler()); // exceção real no span → issues por causa, não por status
|
|
28
|
+
tracker.instrumentPg(pool); // pg only; use track_detect_databases for other drivers // pg.Pool → spans db.query
|
|
29
|
+
const fetchTracked = tracker.wrapFetch(); // fetch → spans http.client
|
|
30
|
+
export const GET = tracker.wrapNextRoute(async (req) => Response.json({ ok: true })); // Next.js
|
|
31
|
+
await tracker.span('custom', 'send-email', async (span) => { /* ... */ });
|
|
32
|
+
tracker.setUser({ id: user.id }); // impacto por usuário nas issues
|
|
33
|
+
await tracker.checkIn('backup-diario', () => runBackup(), { intervalSeconds: 86400 }); // monitor de job (§18)
|
|
34
|
+
await tracker.shutdown(); // no SIGTERM
|
|
35
|
+
\`\`\`
|
|
36
|
+
No deploy: \`npx fg-tracker-release --service minha-app --previous-sha $PREV\` registra a release com commits/arquivos (commits suspeitos nas issues, comparação de latência entre versões).
|
|
37
|
+
Use \`track_instrumentation_guide { framework, projectId }\` para o passo a passo completo por framework com a chave real.
|
|
38
|
+
|
|
39
|
+
## 3. Logs
|
|
40
|
+
\`\`\`ts
|
|
41
|
+
import { createLogShipper } from 'fg-tracker-sdk';
|
|
42
|
+
const shipper = createLogShipper({ apiKey, endpoint: '${endpoint}', service: 'minha-app', env: 'production' });
|
|
43
|
+
// pino: pino({ transport: { target: 'fg-tracker-sdk/pino', options: { apiKey, endpoint, service } } })
|
|
44
|
+
// winston: import { winstonTransport } from 'fg-tracker-sdk/winston'; transports: [winstonTransport(shipper)]
|
|
45
|
+
// nest: NestFactory.create(AppModule, { logger: nestLogger(shipper) })
|
|
46
|
+
\`\`\`
|
|
47
|
+
Logs emitidos dentro de um request instrumentado ganham \`traceId\`/\`spanId\`.
|
|
48
|
+
|
|
49
|
+
## 4. Ingestão crua (qualquer linguagem)
|
|
50
|
+
\`\`\`bash
|
|
51
|
+
curl -X POST ${endpoint}/v1/ingest -H 'content-type: application/json' -H 'x-fg-tracker-key: stk_...' -d '{
|
|
52
|
+
"traces": [{ "traceId": "0123456789abcdef0123456789abcdef", "spans": [
|
|
53
|
+
{ "spanId": "0123456789abcdef", "parentSpanId": null, "kind": "http.server", "name": "GET /users/:id",
|
|
54
|
+
"method": "GET", "route": "/users/:id", "statusCode": 200,
|
|
55
|
+
"startedAt": "2026-09-12T12:00:00.000Z", "endedAt": "2026-09-12T12:00:00.123Z", "durationMs": 123.4,
|
|
56
|
+
"attributes": { "url": "/users/42" }, "error": null } ] }] }'
|
|
57
|
+
# → 202 { "accepted": 1, "issuesDetected": 0 }
|
|
58
|
+
|
|
59
|
+
curl -X POST ${endpoint}/v1/logs -H 'content-type: application/json' -H 'x-fg-tracker-key: stk_...' -d '{
|
|
60
|
+
"logs": [{ "ts": "2026-09-12T12:00:00.000Z", "level": "info", "service": "minha-app", "message": "pedido criado", "context": { "orderId": 42 } }] }'
|
|
61
|
+
# → 202 { "accepted": 1 }
|
|
62
|
+
\`\`\`
|
|
63
|
+
Kinds de span: \`http.server\` (raiz por request), \`db.query\` (nome = SQL normalizado), \`http.client\`, \`custom\`.
|
|
64
|
+
|
|
65
|
+
## 5. Verificar e explorar
|
|
66
|
+
- \`track_verify_ingest { projectId }\` — confirma spans/logs recentes.
|
|
67
|
+
- \`track_get_overview { projectId, range }\` — requests, erro, p50/p95/p99, apdex, top lentos.
|
|
68
|
+
- \`track_list_endpoints\`, \`track_list_issues\`, \`track_list_traces\` → \`track_get_trace { traceId }\` (waterfall).
|
|
69
|
+
- \`track_search_logs { projectId, q, service, level, range }\` — sintaxe: texto livre, \`"frase"\`, \`key=value\`, \`~substring\`.
|
|
70
|
+
- \`track_get_issue { projectId, issueId }\` — ocorrências, usuários afetados, releases, regressões e commits/PRs suspeitos.
|
|
71
|
+
- \`track_list_releases { projectId, version? }\`, \`track_register_release\`, \`track_endpoint_history { projectId, name, days }\` — saúde por deploy e latência por rota ao longo do tempo.
|
|
72
|
+
- \`track_list_providers { projectId, range }\` (chamadas de saída por host) e \`track_list_monitors { projectId }\` (uptime e jobs).
|
|
73
|
+
|
|
74
|
+
## 6. Detectores (rodam na ingestão)
|
|
75
|
+
| tipo | regra |
|
|
76
|
+
|---|---|
|
|
77
|
+
| N_PLUS_ONE | ≥ \`loopThreshold\` (default 10) queries iguais sob o mesmo pai no mesmo trace |
|
|
78
|
+
| LOOP | ≥ \`loopThreshold\` spans \`http.client\`/\`custom\` iguais sob o mesmo pai |
|
|
79
|
+
| SLOW_ENDPOINT | raiz \`http.server\` com \`durationMs > slowThresholdMs\` (default 1000) |
|
|
80
|
+
| ERROR | raiz com status ≥ 500 ou \`error != null\` |
|
|
81
|
+
|
|
82
|
+
Ranges aceitos: \`15m|1h|6h|24h|7d|30d\`.
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
export function instrumentProjectPrompt(args, endpoint) {
|
|
86
|
+
const fw = args.framework ? `O usuário indicou o framework **${args.framework}**; confirme lendo o código antes de seguir.` : 'O framework NÃO foi informado: detecte-o.';
|
|
87
|
+
const proj = args.projectName
|
|
88
|
+
? `Use (ou crie) o projeto chamado **${args.projectName}** no FG Tracker.`
|
|
89
|
+
: 'Nenhum nome de projeto foi informado: use o nome do pacote (`package.json#name`) ou o nome do diretório.';
|
|
90
|
+
return `Você vai conectar o projeto de código atual ao FG Tracker (APM em ${endpoint}) usando as tools deste servidor MCP. Trabalhe passo a passo, mostre o que fez em cada etapa e só avance quando a anterior estiver ok.
|
|
91
|
+
|
|
92
|
+
${fw} ${proj}
|
|
93
|
+
|
|
94
|
+
## Plano
|
|
95
|
+
|
|
96
|
+
1. **Detectar framework e logger.** Leia \`package.json\` (dependências: express, @nestjs/core, next, fastify; pino, winston; pg, drizzle-orm, kysely, knex) e o ponto de entrada (\`src/main.ts\`, \`src/index.ts\`, \`app/\`). Anote: framework HTTP, logger, os drivers e os pontos de criação dos clientes, gerenciador de pacotes (lockfile) e como o app é iniciado.
|
|
97
|
+
|
|
98
|
+
2. **Detectar bancos.** Chame \`track_detect_databases { projectPath, serviceName }\`. Confirme os imports e pontos de criação retornados; siga o adapter de cada driver ativo. Não suponha pg.Pool para Postgres.js, Prisma ou outro driver.
|
|
99
|
+
|
|
100
|
+
2b. **Checar o FG Tracker.** Chame \`track_status\`. Se a API estiver fora do ar ou faltar \`FG_TRACKER_TOKEN\`, pare e explique ao usuário o que configurar.
|
|
101
|
+
|
|
102
|
+
3. **Escolher ou criar o projeto.** Chame \`track_list_projects\`. Se já existe um projeto com o nome esperado, use-o; senão \`track_create_project { name }\`. Guarde \`projectId\` e \`apiKey\`. Nunca imprima a chave em commits/logs — só em \`.env\` (confira que \`.env\` está no \`.gitignore\`; adicione a variável em \`.env.example\` sem o valor).
|
|
103
|
+
|
|
104
|
+
4. **Obter o guia.** Chame \`track_instrumentation_guide { framework, projectId }\` para o framework detectado. Se o app tem pino ou winston, chame também com \`framework: "pino"\` ou \`"winston"\`.
|
|
105
|
+
|
|
106
|
+
5. **Instalar o SDK.** \`pnpm add fg-tracker-sdk\` (ou npm/yarn conforme o lockfile). Se o projeto já usa \`stread-track-sdk\`, troque pelo \`fg-tracker-sdk\` (mesma API).
|
|
107
|
+
|
|
108
|
+
6. **Aplicar a instrumentação** seguindo o guia, com edits mínimos e idiomáticos ao projeto:
|
|
109
|
+
- criar o tracker (um por processo) com \`apiKey\` de \`process.env.FG_TRACKER_KEY\` e \`endpoint\` de \`FG_TRACKER_URL\`;
|
|
110
|
+
- registrar \`tracker.express()\` como PRIMEIRO middleware (Express/Nest), \`wrapNextRoute\` nos route handlers (Next) ou o hook \`onRequest\` (Fastify);
|
|
111
|
+
- aplicar o adapter retornado por \`track_detect_databases\` ao cliente real antes de passá-lo ao ORM; para drivers desconhecidos envolver a conclusão da operação com \`traceDatabase\` ou \`traceDatabaseSync\`;
|
|
112
|
+
- \`tracker.wrapFetch()\` para chamadas HTTP de saída relevantes;
|
|
113
|
+
- transport de logs (pino/winston/nest) com \`createLogShipper\`;
|
|
114
|
+
- \`tracker.shutdown()\` no encerramento (SIGTERM / \`onApplicationShutdown\` / \`onClose\`).
|
|
115
|
+
|
|
116
|
+
7. **Variáveis de ambiente.** Adicione \`FG_TRACKER_KEY=<apiKey>\` e \`FG_TRACKER_URL=${endpoint}\` ao \`.env\` local (e os nomes ao \`.env.example\`).
|
|
117
|
+
|
|
118
|
+
8. **Rodar e gerar tráfego.** Inicie o app, faça algumas requisições reais (curl nas rotas principais, inclusive uma que consulte o banco) e aguarde ~3 s.
|
|
119
|
+
|
|
120
|
+
9. **Verificar.** Chame \`track_verify_ingest { projectId }\`. Se chegaram spans (e logs, quando configurados), mostre um resumo com \`track_get_overview { projectId, range: "15m" }\` e \`track_list_issues\`.
|
|
121
|
+
|
|
122
|
+
10. **Corrigir.** Se nada chegou: confira a chave (o SDK loga "4xx" uma vez quando ela é inválida), a ordem do middleware, se o tracker foi criado antes do app subir, se o processo consegue alcançar ${endpoint} (\`curl ${endpoint}/v1/health\`) e se há \`enabled: false\`. Ajuste e repita o passo 8.
|
|
123
|
+
|
|
124
|
+
Ao final, liste os arquivos alterados, as variáveis adicionadas e o resultado de \`track_verify_ingest\`.`;
|
|
125
|
+
}
|
|
126
|
+
// Database driver detection must precede selection of an integration adapter.
|
|
127
|
+
//# sourceMappingURL=docs.js.map
|
package/dist/docs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,8BAA8B,CAAC;AAC7D,iGAAiG;AACjG,MAAM,CAAC,MAAM,qBAAqB,GAAG,gCAAgC,CAAC;AAEtE,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO;;gMAEuL,QAAQ,oBAAoB,QAAQ;;;;;;;;;;oDAUhL,QAAQ;;;;;;;;;;;;;;;;;;;;;wDAqBJ,QAAQ;;;;;;;;;eASjD,QAAQ;;;;;;;;eAQR,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;CAwBtB,CAAC;AACF,CAAC;AAOD,MAAM,UAAU,uBAAuB,CAAC,IAA0B,EAAE,QAAgB;IAClF,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,mCAAmC,IAAI,CAAC,SAAS,8CAA8C,CAAC,CAAC,CAAC,2CAA2C,CAAC;IAC1K,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW;QAC3B,CAAC,CAAC,qCAAqC,IAAI,CAAC,WAAW,mBAAmB;QAC1E,CAAC,CAAC,0GAA0G,CAAC;IAE/G,OAAO,qEAAqE,QAAQ;;EAEpF,EAAE,IAAI,IAAI;;;;;;;;;;;;;;;;;;;;;;;;wFAwB4E,QAAQ;;;;;;yMAMyG,QAAQ,YAAY,QAAQ;;0GAE3H,CAAC;AAC3G,CAAC;AAED,8EAA8E"}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface ToolText {
|
|
2
|
+
[x: string]: unknown;
|
|
3
|
+
content: Array<{
|
|
4
|
+
type: 'text';
|
|
5
|
+
text: string;
|
|
6
|
+
}>;
|
|
7
|
+
isError?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const MAX_SERIES_POINTS = 48;
|
|
10
|
+
export declare const MAX_LIST_ITEMS = 25;
|
|
11
|
+
export declare const MAX_TRACE_SPANS = 80;
|
|
12
|
+
export declare function text(value: string): ToolText;
|
|
13
|
+
export declare function json(value: unknown, preface?: string): ToolText;
|
|
14
|
+
export declare function errorResult(err: unknown): ToolText;
|
|
15
|
+
/** Executa `fn` e converte qualquer exceção em resultado `isError`. */
|
|
16
|
+
export declare function guard(fn: () => Promise<ToolText>): Promise<ToolText>;
|
|
17
|
+
/** Reduz uma série mantendo a distribuição (amostragem uniforme). */
|
|
18
|
+
export declare function sampleSeries<T>(series: T[], max?: number): T[];
|
|
19
|
+
export declare function truncateList<T>(list: T[], max?: number): {
|
|
20
|
+
items: T[];
|
|
21
|
+
truncated: number;
|
|
22
|
+
};
|
|
23
|
+
/** Compacta recursivamente: `series` viram amostras, arrays longos são cortados. */
|
|
24
|
+
export declare function compact(value: unknown, depth?: number): unknown;
|
|
25
|
+
export declare function ms(value: number | null | undefined): string;
|
|
26
|
+
export declare function pct(value: number | null | undefined): string;
|
|
27
|
+
export declare function ago(iso: string, now?: number): string;
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers de saída: compactação de payloads grandes (mesma regra do §7 do
|
|
3
|
+
* contrato — séries ≤ 48 pontos, listas ≤ 25 itens, traces ≤ 80 spans) e
|
|
4
|
+
* conversão para o formato de resultado do MCP.
|
|
5
|
+
*/
|
|
6
|
+
import { TrackApiError } from './client.js';
|
|
7
|
+
export const MAX_SERIES_POINTS = 48;
|
|
8
|
+
export const MAX_LIST_ITEMS = 25;
|
|
9
|
+
export const MAX_TRACE_SPANS = 80;
|
|
10
|
+
export function text(value) {
|
|
11
|
+
return { content: [{ type: 'text', text: value }] };
|
|
12
|
+
}
|
|
13
|
+
export function json(value, preface) {
|
|
14
|
+
const body = JSON.stringify(value, null, 2);
|
|
15
|
+
return text(preface ? `${preface}\n\n${body}` : body);
|
|
16
|
+
}
|
|
17
|
+
export function errorResult(err) {
|
|
18
|
+
const message = err instanceof TrackApiError ? err.describe() : err instanceof Error ? err.message : String(err);
|
|
19
|
+
return { content: [{ type: 'text', text: message }], isError: true };
|
|
20
|
+
}
|
|
21
|
+
/** Executa `fn` e converte qualquer exceção em resultado `isError`. */
|
|
22
|
+
export async function guard(fn) {
|
|
23
|
+
try {
|
|
24
|
+
return await fn();
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
return errorResult(err);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Reduz uma série mantendo a distribuição (amostragem uniforme). */
|
|
31
|
+
export function sampleSeries(series, max = MAX_SERIES_POINTS) {
|
|
32
|
+
if (series.length <= max)
|
|
33
|
+
return series;
|
|
34
|
+
const step = series.length / max;
|
|
35
|
+
const out = [];
|
|
36
|
+
for (let i = 0; i < max; i++) {
|
|
37
|
+
const item = series[Math.floor(i * step)];
|
|
38
|
+
if (item !== undefined)
|
|
39
|
+
out.push(item);
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
export function truncateList(list, max = MAX_LIST_ITEMS) {
|
|
44
|
+
if (list.length <= max)
|
|
45
|
+
return { items: list, truncated: 0 };
|
|
46
|
+
return { items: list.slice(0, max), truncated: list.length - max };
|
|
47
|
+
}
|
|
48
|
+
/** Compacta recursivamente: `series` viram amostras, arrays longos são cortados. */
|
|
49
|
+
export function compact(value, depth = 0) {
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
const { items, truncated } = truncateList(value);
|
|
52
|
+
const out = items.map((v) => compact(v, depth + 1));
|
|
53
|
+
return truncated > 0 ? [...out, `… +${truncated} itens omitidos`] : out;
|
|
54
|
+
}
|
|
55
|
+
if (value && typeof value === 'object') {
|
|
56
|
+
const out = {};
|
|
57
|
+
for (const [k, v] of Object.entries(value)) {
|
|
58
|
+
if ((k === 'series' || k === 'seriesQueriesPerMin' || k === 'histogram') && Array.isArray(v)) {
|
|
59
|
+
out[k] = sampleSeries(v);
|
|
60
|
+
if (v.length > MAX_SERIES_POINTS)
|
|
61
|
+
out[`${k}Points`] = `${v.length} pontos, amostrados para ${MAX_SERIES_POINTS}`;
|
|
62
|
+
}
|
|
63
|
+
else if (k === 'spans' && Array.isArray(v)) {
|
|
64
|
+
const { items, truncated } = truncateList(v, MAX_TRACE_SPANS);
|
|
65
|
+
out[k] = items;
|
|
66
|
+
if (truncated > 0)
|
|
67
|
+
out.spansOmitted = truncated;
|
|
68
|
+
}
|
|
69
|
+
else if (k === 'sparkline' && Array.isArray(v)) {
|
|
70
|
+
out[k] = v; // 24 pontos, já pequeno
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
out[k] = compact(v, depth + 1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
export function ms(value) {
|
|
81
|
+
if (value === null || value === undefined || Number.isNaN(value))
|
|
82
|
+
return '—';
|
|
83
|
+
return `${Math.round(value)} ms`;
|
|
84
|
+
}
|
|
85
|
+
export function pct(value) {
|
|
86
|
+
if (value === null || value === undefined || Number.isNaN(value))
|
|
87
|
+
return '—';
|
|
88
|
+
return `${(value * 100).toFixed(2)}%`;
|
|
89
|
+
}
|
|
90
|
+
export function ago(iso, now = Date.now()) {
|
|
91
|
+
const t = Date.parse(iso);
|
|
92
|
+
if (Number.isNaN(t))
|
|
93
|
+
return iso;
|
|
94
|
+
const s = Math.max(0, Math.round((now - t) / 1000));
|
|
95
|
+
if (s < 60)
|
|
96
|
+
return `há ${s} s`;
|
|
97
|
+
if (s < 3600)
|
|
98
|
+
return `há ${Math.round(s / 60)} min`;
|
|
99
|
+
if (s < 86400)
|
|
100
|
+
return `há ${(s / 3600).toFixed(1)} h`;
|
|
101
|
+
return `há ${(s / 86400).toFixed(1)} d`;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
|
package/dist/guide.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guia de instrumentação: passos + código copiável por framework/logger,
|
|
3
|
+
* usando a chave real do projeto quando disponível. Segue o SDK atual
|
|
4
|
+
* (packages/sdk/README.md) e os transports de logs do §11 do contrato.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FRAMEWORKS: readonly ["express", "nestjs", "nextjs", "fastify", "pino", "winston"];
|
|
7
|
+
export type Framework = (typeof FRAMEWORKS)[number];
|
|
8
|
+
export interface GuideInput {
|
|
9
|
+
framework: Framework;
|
|
10
|
+
databaseDriver?: string;
|
|
11
|
+
/** URL base da API do FG Tracker (endpoint do SDK). */
|
|
12
|
+
endpoint: string;
|
|
13
|
+
/** Chave do projeto; sem ela usa placeholder. */
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
projectName?: string;
|
|
16
|
+
projectId?: string;
|
|
17
|
+
serviceName?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function buildGuide(input: GuideInput): string;
|