stitchkit 0.28.0 → 0.29.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.
@@ -397,7 +397,12 @@ var METHOD_COLOR = {
397
397
  DELETE: c.red,
398
398
  OPTIONS: c.gray
399
399
  };
400
- var isProd = false;
400
+ var runtimeEnv = process.env;
401
+ function resolveLogFormat(preference) {
402
+ if (preference)
403
+ return preference;
404
+ return runtimeEnv.NODE_ENV === "production" ? "json" : "pretty";
405
+ }
401
406
  function timestamp() {
402
407
  const now = new Date;
403
408
  const t = now.toLocaleTimeString("en-US", {
@@ -464,9 +469,9 @@ function shouldLog(pathname, method) {
464
469
  return false;
465
470
  return !SKIP_PREFIXES.some((prefix) => pathname.startsWith(prefix));
466
471
  }
467
- function logIncoming(req, pathname, traceId, ipAddress) {
472
+ function logIncoming(req, pathname, traceId, format, ipAddress) {
468
473
  const log = { traceId, startTime: performance.now() };
469
- if (!isProd) {
474
+ if (format === "pretty") {
470
475
  const mc = METHOD_COLOR[req.method] ?? c.dim;
471
476
  console.log(`${c.gray}[${timestamp()}]${c.reset} ${mc}${req.method}${c.reset} ${c.dim}${traceId}${c.reset} ${c.cyan}→${c.reset} ${safePath(pathname)} ${ipLabel(ipAddress ?? "")}`);
472
477
  }
@@ -480,9 +485,9 @@ function structuredLine(own, extra) {
480
485
  }
481
486
  }
482
487
  function logOutgoing(entry) {
483
- const { req, pathname, status, log, ipAddress, errorCode: errorCode2, durationMs, extra } = entry;
488
+ const { req, pathname, status, log, ipAddress, errorCode: errorCode2, durationMs, format, extra } = entry;
484
489
  const ms = elapsedMs(log.startTime);
485
- if (isProd) {
490
+ if (format === "json") {
486
491
  const own = {
487
492
  ts: new Date().toISOString(),
488
493
  level: levelForStatus(status),
@@ -557,22 +562,42 @@ function createHandler(config) {
557
562
  const customLogger = logConfig?.logger ?? null;
558
563
  const useDefaultLog = logConfig !== null && !logConfig.logger;
559
564
  const customTraceId = config.traceId;
565
+ const warn = (line) => {
566
+ try {
567
+ if (customLogger)
568
+ customLogger.warn(line);
569
+ else
570
+ console.warn(line);
571
+ } catch {}
572
+ };
573
+ let traceResolverBroken = false;
574
+ const resolveId = (req) => {
575
+ if (!customTraceId)
576
+ return resolveTraceId(req);
577
+ try {
578
+ return customTraceId(req) ?? resolveTraceId(req);
579
+ } catch (err) {
580
+ if (!traceResolverBroken) {
581
+ traceResolverBroken = true;
582
+ warn("[stitchkit] `traceId` resolver threw — falling back to the framework resolver. " + "Ids will not match your observability context until it is fixed: " + `${err instanceof Error ? err.message : String(err)}`);
583
+ }
584
+ return resolveTraceId(req);
585
+ }
586
+ };
560
587
  const routeMap = buildRouteMap(normalizeGroups(config));
561
588
  validateRoutes(routeMap);
562
589
  for (const shadow of findShadowedRoutes(routeMap, config.rawRoutes)) {
563
590
  const gate = shadow.scope && shadow.scope !== "public" ? ` (scope "${shadow.scope}")` : "";
564
591
  const line = `[stitchkit] raw route ${shadow.rawRoute} shadows contract route ${shadow.pattern}` + ` → ${shadow.endpoint}${gate} will never run, and its hooks never apply`;
565
- if (customLogger)
566
- customLogger.warn(line);
567
- else
568
- console.warn(line);
592
+ warn(line);
569
593
  }
570
594
  async function dispatch(req, url, traceId, server, clientIp) {
571
595
  const shouldLogRequest = logConfig !== null && shouldLog(url.pathname, req.method) && !shouldSkipLog(logConfig, req, url);
572
596
  const ipAddress = extractIp(req, clientIp) || undefined;
597
+ const logFormat = resolveLogFormat(logConfig?.format);
573
598
  let reqLog;
574
599
  if (shouldLogRequest && useDefaultLog) {
575
- reqLog = logIncoming(req, url.pathname, traceId, ipAddress);
600
+ reqLog = logIncoming(req, url.pathname, traceId, logFormat, ipAddress);
576
601
  }
577
602
  if (shouldLogRequest && customLogger) {
578
603
  reqLog = { traceId, startTime: performance.now() };
@@ -606,6 +631,7 @@ function createHandler(config) {
606
631
  ipAddress,
607
632
  errorCode: errorCode2,
608
633
  durationMs,
634
+ format: logFormat,
609
635
  extra
610
636
  });
611
637
  }
@@ -637,13 +663,17 @@ function createHandler(config) {
637
663
  if (cors && req.method === "OPTIONS") {
638
664
  return corsPreflightResponse(cors, req);
639
665
  }
640
- if (hooks?.onRequest) {
641
- const earlyResponse = await hooks.onRequest(req);
642
- if (earlyResponse instanceof Response) {
643
- const withCors = applyCors(earlyResponse, cors, req);
644
- logDone(withCors.status);
645
- return withCors;
666
+ try {
667
+ if (hooks?.onRequest) {
668
+ const earlyResponse = await hooks.onRequest(req);
669
+ if (earlyResponse instanceof Response) {
670
+ const withCors = applyCors(earlyResponse, cors, req);
671
+ logDone(withCors.status);
672
+ return withCors;
673
+ }
646
674
  }
675
+ } catch (err) {
676
+ return respondError(err);
647
677
  }
648
678
  if (config.rawRoutes) {
649
679
  const rawMatch = matchRawRoute(config.rawRoutes, req.method, url.pathname);
@@ -707,13 +737,7 @@ function createHandler(config) {
707
737
  }
708
738
  if (method.outputSchema) {
709
739
  const checked = validateHandlerOutput(method.outputSchema, result, config.warnOnOutputStrip ? (paths) => {
710
- const line = `[stitchkit] output strip ${method.serviceName}.${method.key}: ${paths.join(", ")}`;
711
- try {
712
- if (customLogger)
713
- customLogger.warn(line);
714
- else
715
- console.warn(line);
716
- } catch {}
740
+ warn(`[stitchkit] output strip ${method.serviceName}.${method.key}: ${paths.join(", ")}`);
717
741
  } : undefined);
718
742
  if (!checked.ok) {
719
743
  throw new AppError("INTERNAL_SERVER_ERROR", checked.message, 500);
@@ -734,7 +758,7 @@ function createHandler(config) {
734
758
  }
735
759
  return async (req, server) => {
736
760
  const url = new URL(req.url, "http://localhost");
737
- const traceId = customTraceId?.(req) ?? resolveTraceId(req);
761
+ const traceId = resolveId(req);
738
762
  const clientIp = {
739
763
  trustProxy,
740
764
  socketIp: resolveSocketIp(req, server)
package/dist/node.d.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  export { AppError, appError, badRequest, conflict, forbidden, notFound, rateLimited, unauthorized, } from './contract';
8
8
  export { createHandler } from './server/create';
9
9
  export { createImplement, implement } from './server/implement';
10
+ export type { LogFormat } from './server/logger';
10
11
  export { type NodeServerConfig, type NodeServerHandle, serveNode } from './server/node';
11
12
  export { createSocketIOServer, type SocketIOServerConfig, type SocketIOServerHandle, } from './server/socket-io';
12
13
  export type { FetchComposition, FetchHandler, HandlerConfig, LoggingConfig, LogOutcome, RawRoute, RawRouteContext, ServiceDef, } from './server/types';
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACxF,OAAO,EACL,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,UAAU,EACV,QAAQ,EACR,eAAe,EACf,UAAU,GACX,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACxF,OAAO,EACL,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,UAAU,EACV,QAAQ,EACR,eAAe,EACf,UAAU,GACX,MAAM,gBAAgB,CAAC"}
package/dist/node.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createImplement,
4
4
  createSocketIOServer,
5
5
  implement
6
- } from "./index-17jpjnhd.js";
6
+ } from "./index-3hsagjqf.js";
7
7
  import"./index-czmqks7r.js";
8
8
  import {
9
9
  AppError,
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAEV,eAAe,EACf,YAAY,EACZ,aAAa,EAGd,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,CAoVjE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,uBAuBnD"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAEV,eAAe,EACf,YAAY,EACZ,aAAa,EAGd,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,CA6XjE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,uBAuBnD"}
@@ -7,6 +7,7 @@ export { createErrorHook, type ErrorHookConfig, type ResolvedError, } from './er
7
7
  export { createEventBus, type EventBus } from './event-bus';
8
8
  export { type ByteRange, parseByteRange, type ServeFileOptions, serveFile, weakETag, } from './file';
9
9
  export { createImplement, implement } from './implement';
10
+ export type { LogFormat } from './logger';
10
11
  export { type AuthHook, type AuthHookConfig, type AuthRule, type BearerResolverConfig, createAuthHook, createBearerResolver, extractToken, type JwtPayload, type SignJwtOptions, signJwt, verifyJwt, } from './middleware/auth';
11
12
  export { type CookieDef, type CookieOptions, defineCookie, parseCookies, serializeCookie, } from './middleware/cookies';
12
13
  export { type CorsConfig, corsHeaders, corsPreflightResponse, DEFAULT_CORS_ALLOW_HEADERS, DEFAULT_CORS_EXPOSE_HEADERS, } from './middleware/cors';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,EACpB,YAAY,GACb,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,SAAS,EACT,cAAc,EACd,cAAc,EACd,KAAK,eAAe,EACpB,SAAS,GACV,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EACL,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,KAAK,SAAS,EACd,cAAc,EACd,KAAK,gBAAgB,EACrB,SAAS,EACT,QAAQ,GACT,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,OAAO,EACP,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EACL,KAAK,eAAe,EACpB,SAAS,EACT,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrE,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,cAAc,EACd,aAAa,EACb,UAAU,EACV,SAAS,EACT,QAAQ,EACR,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,YAAY,EACjB,wBAAwB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ import {
10
10
  socketIoLane,
11
11
  staticRoute,
12
12
  webSocketLane
13
- } from "../index-17jpjnhd.js";
13
+ } from "../index-3hsagjqf.js";
14
14
  import {
15
15
  createAuthHook,
16
16
  createBearerResolver,
@@ -1,3 +1,10 @@
1
+ /** How a completed request is written. */
2
+ export type LogFormat = 'pretty' | 'json';
3
+ /**
4
+ * The format to use: the caller's choice, else derived from `NODE_ENV` at the
5
+ * moment of the call.
6
+ */
7
+ export declare function resolveLogFormat(preference?: LogFormat): LogFormat;
1
8
  /** Elapsed milliseconds since a `performance.now()` mark. */
2
9
  export declare function elapsedMs(startTime: number): number;
3
10
  /** Map an HTTP status to a log level. */
@@ -21,8 +28,12 @@ export interface RequestLog {
21
28
  startTime: number;
22
29
  }
23
30
  export declare function shouldLog(pathname: string, method: string): boolean;
24
- /** Open the timing window for a request. Development prints a `→` line. */
25
- export declare function logIncoming(req: Request, pathname: string, traceId: string, ipAddress?: string): RequestLog;
31
+ /**
32
+ * Open the timing window for a request. The `pretty` format prints a `→` line
33
+ * so a hanging request is visible before it finishes; `json` does not — a
34
+ * record store wants one row per completed request, not a half of one.
35
+ */
36
+ export declare function logIncoming(req: Request, pathname: string, traceId: string, format: LogFormat, ipAddress?: string): RequestLog;
26
37
  /**
27
38
  * Serialise one structured line: consumer fields under the framework's own. A
28
39
  * value `JSON.stringify` refuses (a cycle, a `BigInt`) costs the consumer
@@ -39,6 +50,8 @@ export interface CompletedRequest {
39
50
  errorCode?: string;
40
51
  /** Duration the caller already measured — the one `enrich` was shown. */
41
52
  durationMs: number;
53
+ /** Which of the two lines to write. */
54
+ format: LogFormat;
42
55
  /**
43
56
  * Consumer-supplied fields for the structured line — request-context
44
57
  * identity and whatever `enrich` returned. Spread *first* so the framework's
@@ -47,9 +60,9 @@ export interface CompletedRequest {
47
60
  extra?: Record<string, unknown>;
48
61
  }
49
62
  /**
50
- * Close a request. Development: `←` line deliberately unchanged by `extra`,
51
- * it is a line to read, not a record to query. Production: one structured JSON
52
- * line, enriched.
63
+ * Close a request. `json` writes one structured record, carrying `extra`.
64
+ * `pretty` writes a `←` line to read deliberately without `extra`: a line
65
+ * sized for a terminal is not a record to query.
53
66
  */
54
67
  export declare function logOutgoing(entry: CompletedRequest): void;
55
68
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAwCA,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnD;AAoBD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAIxE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAEA;AA0BD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnE;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,CASZ;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAMR;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,UAAU,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAwBzD"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAqCA,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAGlE;AAaD,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnD;AAoBD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAIxE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAEA;AA0BD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,CASZ;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAMR;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,UAAU,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAyBzD"}
@@ -1,5 +1,6 @@
1
1
  import type { ZodType } from 'zod';
2
2
  import type { EndpointDef, EndpointToolAnnotations, EndpointUiMeta, HandlerContext, HttpMethod, RuntimeContext, Transport } from '../contract';
3
+ import type { LogFormat } from './logger';
3
4
  import type { CorsConfig } from './middleware/cors';
4
5
  type Prop<T, K extends string> = K extends keyof T ? T[K] : undefined;
5
6
  type InferParams<E> = Prop<E, 'params'> extends ZodType<infer P> ? P : undefined;
@@ -168,6 +169,24 @@ export interface LogOutcome {
168
169
  export interface LoggingConfig {
169
170
  /** Send lines here instead of to the built-in formatter. */
170
171
  logger?: StitchLogger;
172
+ /**
173
+ * What the **built-in** formatter writes.
174
+ *
175
+ * - `'pretty'` — two coloured lines per request (`→` on arrival, `←` on
176
+ * completion), sized for a terminal. Carries no extra fields: a line to
177
+ * read is not a record to query.
178
+ * - `'json'` — one structured line per completed request, carrying the
179
+ * request-context identity and whatever `enrich` returned.
180
+ *
181
+ * Unset, it follows `NODE_ENV`: `'json'` under `production`, `'pretty'`
182
+ * otherwise — read **per request**, never at import or at build time, so the
183
+ * environment that matters is the one the app runs in. Set it and the
184
+ * environment stops being consulted at all.
185
+ *
186
+ * Irrelevant when `logger` is set: a sink always receives the structured
187
+ * object, in every environment.
188
+ */
189
+ format?: LogFormat;
171
190
  /**
172
191
  * Silence a request. Consulted *after* the built-in noise filter (framework
173
192
  * assets, `favicon`, preflights), so it can only quieten more, never restore
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
package/llms-full.txt CHANGED
@@ -635,6 +635,8 @@ on**, and the fields tune it:
635
635
  createServer({
636
636
  services,
637
637
  logging: {
638
+ // What the built-in formatter writes. Omit it and it follows NODE_ENV.
639
+ format: 'json',
638
640
  // Route lines into your stack instead of the built-in formatter.
639
641
  logger: myLogger,
640
642
  // Silence noise. Runs after the built-in filter (framework assets,
@@ -649,16 +651,33 @@ createServer({
649
651
  })
650
652
  ```
651
653
 
652
- Three things worth knowing about `enrich`: it reaches the **structured** output
653
- only (the production JSON line and a custom logger's `data`) — the development
654
- `←` line stays human-readable, so enriched fields are invisible in dev; it runs
655
- at close, when the request body is already consumed; and framework fields
656
- (`traceId`, `status`, `path`, …) always win a key collision. A throw in `skip`
657
- or `enrich` is swallowed — neither can fail a request.
654
+ ### Two formats, and who chooses
658
655
 
659
- With an observability context active, the line also carries `userId`,
660
- `serviceName`, `action` and `dimensions` for free — and, like `enrich`'s fields,
661
- only in the structured output, never on the development `←` line. See
656
+ | `format` | What it writes | Carries `enrich` / context identity |
657
+ |---|---|---|
658
+ | `'pretty'` | two coloured lines per request — `→` on arrival, `←` on completion | no — a line sized for a terminal is not a record |
659
+ | `'json'` | one structured line per completed request | yes |
660
+
661
+ Unset, `format` follows `NODE_ENV`: `json` under `production`, `pretty`
662
+ otherwise. That default is read **per request** — not at import, not when this
663
+ package was built — so it reflects the environment your app actually runs in.
664
+ Set `format` and the environment stops being consulted at all.
665
+
666
+ `format` applies to the **built-in** formatter only. With `logger` set, your
667
+ sink always receives the structured object, in every environment — the format
668
+ is not involved.
669
+
670
+ **Want the structured line in development?** Set `format: 'json'`. That is the
671
+ way to see what `enrich` and the request context actually put on the record;
672
+ changing `NODE_ENV` is not needed, and neither is deploying.
673
+
674
+ Three more things about `enrich`: it runs at close, when the request body is
675
+ already consumed; framework fields (`traceId`, `status`, `path`, …) always win a
676
+ key collision; and a throw in `skip` or `enrich` is swallowed — neither can fail
677
+ a request.
678
+
679
+ With an observability context active, the structured line also carries `userId`,
680
+ `serviceName`, `action` and `dimensions` for free. See
662
681
  [Observability](./observability.md).
663
682
 
664
683
  ## Route groups
@@ -2888,11 +2907,11 @@ The **request log picks the context up on its own**: with a context active, each
2888
2907
  completion line carries `userId`, `serviceName`, `action` and `dimensions`
2889
2908
  without any configuration.
2890
2909
 
2891
- ⚠️ In the **structured** output only — the production JSON line and a custom
2892
- `logger`'s `data`. The development `←` line is a line to read, not a record to
2893
- query, and never carries them (nor `enrich`'s fields). On `logging: true` in
2894
- development you will see no difference; check with `NODE_ENV=production` or a
2895
- custom `logger`.
2910
+ ⚠️ In the **structured** output only — the `json` line and a custom `logger`'s
2911
+ `data`. The `pretty` `←` line is a line to read, not a record to query, and
2912
+ never carries them (nor `enrich`'s fields). Set
2913
+ [`logging.format: 'json'`](./server.md#two-formats-and-who-chooses) to see them
2914
+ locally; you do not need to change `NODE_ENV` or deploy.
2896
2915
 
2897
2916
  ### Correlating with a reverse proxy
2898
2917
 
@@ -3604,7 +3623,8 @@ Also re-exports the error helpers from `stitchkit/contract`.
3604
3623
  | `BunServer` | _type_ | the `Bun.serve` instance type |
3605
3624
  | `ServerPassthrough` | _type_ | extra `Bun.serve` options |
3606
3625
  | `StitchLogger` | _type_ | the custom-logger interface |
3607
- | `LoggingConfig` | _type_ | the `logging` object — `logger` / `skip` / `enrich` |
3626
+ | `LoggingConfig` | _type_ | the `logging` object — `logger` / `format` / `skip` / `enrich` |
3627
+ | `LogFormat` | _type_ | `'pretty'` or `'json'` — what the built-in formatter writes |
3608
3628
  | `LogOutcome` | _type_ | how a request finished, as `enrich` sees it |
3609
3629
  | `FetchHandler` | _type_ | what `createHandler` returns |
3610
3630
  | `FetchComposition` | _type_ | the `wrapFetch` seam shared by the servers |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -86,7 +86,7 @@
86
86
  "build:server": "bun build src/server/index.ts src/node.ts src/tools.ts src/cli.ts src/observability/index.ts --outdir dist --target node --packages external --splitting --root src",
87
87
  "build:js": "bun run build:browser && bun run build:server",
88
88
  "build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly",
89
- "build": "rm -rf dist && bun run build:js && bun run build:types && bun scripts/check-browser-clean.mjs",
89
+ "build": "rm -rf dist && bun run build:js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-env-live.mjs",
90
90
  "dev": "bun run build:js -- --watch",
91
91
  "prepublishOnly": "cp ../../README.md ./README.md && bun ../../scripts/gen-llms.ts && bun run build",
92
92
  "test": "bun test",