@farming-labs/docs 0.1.65 → 0.1.67

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.
@@ -80,7 +80,7 @@ async function main() {
80
80
  const { init } = await import("../init-BFhnsS7P.mjs");
81
81
  await init(initOptions);
82
82
  } else if (parsedCommand.command === "dev") {
83
- const { dev } = await import("../dev-Cj7kSQsB.mjs");
83
+ const { dev } = await import("../dev-DkMu-1UW.mjs");
84
84
  await dev(devOptions);
85
85
  } else if (parsedCommand.command === "mcp") {
86
86
  const { runMcp } = await import("../mcp-BANLcwQ0.mjs");
@@ -201,7 +201,18 @@ const managedConfigSchema = z.object({
201
201
  description: z.string().optional()
202
202
  }).passthrough().optional(),
203
203
  theme: z.object({ preset: z.string().optional() }).passthrough().optional(),
204
- cloud: z.object({ enabled: z.boolean().optional() }).passthrough().optional()
204
+ cloud: z.object({
205
+ enabled: z.boolean().optional(),
206
+ analytics: z.union([z.boolean(), z.object({
207
+ enabled: z.boolean().optional(),
208
+ console: z.union([z.boolean(), z.enum([
209
+ "log",
210
+ "info",
211
+ "debug"
212
+ ])]).optional(),
213
+ includeInputs: z.boolean().optional()
214
+ }).passthrough()]).optional()
215
+ }).passthrough().optional()
205
216
  }).passthrough();
206
217
  function toPosixPath(value) {
207
218
  return value.replace(/\\/g, "/");
@@ -481,7 +492,8 @@ function readManagedDocsProject(projectRoot) {
481
492
  siteName,
482
493
  titleTemplate: parsed.data.site?.titleTemplate ?? `%s | ${siteName}`,
483
494
  description: parsed.data.site?.description ?? `Documentation for ${siteName}.`,
484
- theme
495
+ theme,
496
+ analytics: parsed.data.cloud?.analytics
485
497
  };
486
498
  }
487
499
  function resolveLocalPackageSpec(projectRoot, runtimeDir) {
@@ -581,6 +593,7 @@ function renderDocsConfigFile(options) {
581
593
  specUrl: ${JSON.stringify(options.apiReference.specUrl)},
582
594
  },
583
595
  ` : "";
596
+ const analyticsBlock = renderManagedAnalyticsBlock(options.analytics);
584
597
  return `import { defineDocs } from "@farming-labs/docs";
585
598
  import { ${options.theme.factory} } from "${options.theme.importPath}";
586
599
 
@@ -598,9 +611,19 @@ export default defineDocs({
598
611
  titleTemplate: ${JSON.stringify(options.titleTemplate)},
599
612
  description: ${JSON.stringify(options.description)},
600
613
  },
601
- ${apiReferenceBlock}});
614
+ ${analyticsBlock}${apiReferenceBlock}});
602
615
  `;
603
616
  }
617
+ function renderManagedAnalyticsBlock(analytics) {
618
+ if (typeof analytics === "undefined") return "";
619
+ if (typeof analytics === "boolean") return ` analytics: ${analytics},\n`;
620
+ const properties = [];
621
+ if (typeof analytics.enabled === "boolean") properties.push(` enabled: ${analytics.enabled},`);
622
+ if (typeof analytics.console !== "undefined") properties.push(` console: ${JSON.stringify(analytics.console)},`);
623
+ if (typeof analytics.includeInputs === "boolean") properties.push(` includeInputs: ${analytics.includeInputs},`);
624
+ if (properties.length === 0) return " analytics: {},\n";
625
+ return ` analytics: {\n${properties.join("\n")}\n },\n`;
626
+ }
604
627
  function renderManagedApiReferenceLayout() {
605
628
  return `import docsConfig from "@/docs.config";
606
629
  import { createNextApiReferenceLayout } from "@farming-labs/next/api-reference";
@@ -951,6 +974,7 @@ function materializeManagedRuntime(projectRoot) {
951
974
  titleTemplate: project.titleTemplate,
952
975
  description: project.description,
953
976
  theme: project.theme,
977
+ analytics: project.analytics,
954
978
  apiReference: project.apiReferenceSpec ? {
955
979
  path: apiReferenceRoute,
956
980
  specUrl: project.apiReferenceSpec.specUrl
@@ -963,7 +987,8 @@ function materializeManagedRuntime(projectRoot) {
963
987
  siteName: project.siteName,
964
988
  titleTemplate: project.titleTemplate,
965
989
  description: project.description,
966
- theme: project.theme
990
+ theme: project.theme,
991
+ analytics: project.analytics
967
992
  }));
968
993
  else fs.rmSync(path.join(project.runtimeDir, "api-reference.config.ts"), { force: true });
969
994
  writeFileIfChanged(path.join(appDir, "layout.tsx"), rootLayoutTemplate(templateConfig, "app/global.css"));
package/dist/mcp.mjs CHANGED
@@ -279,13 +279,21 @@ async function createDocsMcpServer(options) {
279
279
  return server;
280
280
  }
281
281
  function createDocsMcpHttpHandler(options) {
282
- if (!resolveDocsMcpConfig(options.mcp, {
282
+ const resolved = resolveDocsMcpConfig(options.mcp, {
283
283
  defaultName: options.defaultName ?? options.source.siteTitle ?? DEFAULT_MCP_NAME,
284
284
  defaultVersion: options.defaultVersion
285
- }).enabled) return {
286
- GET: async () => createJsonErrorResponse(404, "MCP is disabled. Remove `mcp: false` or set `mcp: { enabled: true }` in docs.config to enable it again."),
287
- POST: async () => createJsonErrorResponse(404, "MCP is disabled. Remove `mcp: false` or set `mcp: { enabled: true }` in docs.config to enable it again."),
288
- DELETE: async () => createJsonErrorResponse(404, "MCP is disabled. Remove `mcp: false` or set `mcp: { enabled: true }` in docs.config to enable it again.")
285
+ });
286
+ const disabledMessage = "MCP is disabled. Remove `mcp: false` or set `mcp: { enabled: true }` in docs.config to enable it again.";
287
+ if (!resolved.enabled) return {
288
+ GET: async () => createJsonErrorResponse(404, disabledMessage),
289
+ POST: async ({ request }) => createJsonRpcErrorResponse({
290
+ status: 404,
291
+ code: -32e3,
292
+ message: disabledMessage,
293
+ id: readJsonRpcId(await parseJsonBody(request)),
294
+ data: { reason: "mcp_disabled" }
295
+ }),
296
+ DELETE: async () => createJsonErrorResponse(404, disabledMessage)
289
297
  };
290
298
  const sessions = /* @__PURE__ */ new Map();
291
299
  async function createSession() {
@@ -316,9 +324,11 @@ function createDocsMcpHttpHandler(options) {
316
324
  const sessionId = request.headers.get("mcp-session-id") ?? request.headers.get("Mcp-Session-Id");
317
325
  const existing = sessionId ? sessions.get(sessionId) : void 0;
318
326
  let parsedBody;
327
+ let bodyParseFailed = false;
319
328
  if (method === "POST") try {
320
329
  parsedBody = await request.clone().json();
321
330
  } catch {
331
+ bodyParseFailed = true;
322
332
  parsedBody = void 0;
323
333
  }
324
334
  const initializeRequest = method === "POST" && parsedBody && isInitializeRequest(parsedBody);
@@ -334,7 +344,18 @@ function createDocsMcpHttpHandler(options) {
334
344
  }
335
345
  });
336
346
  if (!existing) {
337
- if (!initializeRequest) return createJsonErrorResponse(method === "DELETE" ? 404 : 400, "MCP session not initialized. Start with an initialize request against this endpoint.");
347
+ if (method === "POST" && bodyParseFailed) return createJsonRpcErrorResponse({
348
+ status: 400,
349
+ code: -32700,
350
+ message: "Parse error: Invalid JSON"
351
+ });
352
+ if (!initializeRequest) return createJsonRpcErrorResponse({
353
+ status: sessionId || method === "DELETE" ? 404 : 400,
354
+ code: sessionId ? -32001 : -32e3,
355
+ message: sessionId ? "Session not found. Reinitialize the MCP client before calling docs tools." : "MCP session not initialized. Start with an initialize request against this endpoint.",
356
+ id: readJsonRpcId(parsedBody),
357
+ data: { reason: sessionId ? "session_not_found" : "session_not_initialized" }
358
+ });
338
359
  return (await createSession()).transport.handleRequest(request, parsedBody === void 0 ? void 0 : { parsedBody });
339
360
  }
340
361
  return existing.transport.handleRequest(request, parsedBody === void 0 ? void 0 : { parsedBody });
@@ -356,6 +377,35 @@ function createJsonErrorResponse(status, error) {
356
377
  headers: { "Content-Type": "application/json" }
357
378
  });
358
379
  }
380
+ async function parseJsonBody(request) {
381
+ try {
382
+ return await request.clone().json();
383
+ } catch {
384
+ return;
385
+ }
386
+ }
387
+ function readJsonRpcId(value) {
388
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
389
+ const id = value.id;
390
+ return typeof id === "string" || typeof id === "number" ? id : null;
391
+ }
392
+ function createJsonRpcErrorResponse({ status, code, message, id = null, data }) {
393
+ return new Response(JSON.stringify({
394
+ jsonrpc: "2.0",
395
+ id,
396
+ error: data ? {
397
+ code,
398
+ message,
399
+ data
400
+ } : {
401
+ code,
402
+ message
403
+ }
404
+ }), {
405
+ status,
406
+ headers: { "Content-Type": "application/json" }
407
+ });
408
+ }
359
409
  function normalizePathSegment(value) {
360
410
  return value.replace(/^\/+|\/+$/g, "");
361
411
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.1.65",
3
+ "version": "0.1.67",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
5
  "keywords": [
6
6
  "docs",