stitchkit 0.53.2 → 0.55.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 (125) hide show
  1. package/README.md +4 -1
  2. package/dist/browser/socket-io.d.ts +11 -1
  3. package/dist/browser/socket-io.d.ts.map +1 -1
  4. package/dist/cli.d.ts +2 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +15 -8
  7. package/dist/contract/define.d.ts +27 -0
  8. package/dist/contract/define.d.ts.map +1 -1
  9. package/dist/contract/file-ref.d.ts +13 -0
  10. package/dist/contract/file-ref.d.ts.map +1 -0
  11. package/dist/contract/index.d.ts +2 -1
  12. package/dist/contract/index.d.ts.map +1 -1
  13. package/dist/contract/index.js +21 -17
  14. package/dist/files/boundary.d.ts +52 -0
  15. package/dist/files/boundary.d.ts.map +1 -0
  16. package/dist/files.d.ts +3 -0
  17. package/dist/files.d.ts.map +1 -0
  18. package/dist/files.js +16 -0
  19. package/dist/{index-c78w2y09.js → index-0gv7k0ra.js} +515 -156
  20. package/dist/index-1bx83sw4.js +4 -0
  21. package/dist/index-1k16zv57.js +269 -0
  22. package/dist/index-6k1937bx.js +20 -0
  23. package/dist/{index-bmnhqtya.js → index-7eq9va6e.js} +1 -4
  24. package/dist/{index-yxpe3phd.js → index-cby4ar3v.js} +1 -18
  25. package/dist/index-h60df7rj.js +110 -0
  26. package/dist/{index-yez419px.js → index-js7yexng.js} +19 -6
  27. package/dist/index-k4dftwf7.js +66 -0
  28. package/dist/{index-pdv1mjjr.js → index-npye5kt7.js} +30 -59
  29. package/dist/{index-yydqk4fh.js → index-pzc32v75.js} +90 -3
  30. package/dist/{index-e1es808r.js → index-qh4xevf5.js} +1 -1
  31. package/dist/{index-gvha32jh.js → index-qx84bqzk.js} +2 -2
  32. package/dist/{index-pfqjb5xy.js → index-rgd18hx3.js} +23 -5
  33. package/dist/index-sbdmyz75.js +18 -0
  34. package/dist/{index-173tvqcp.js → index-v4bbq3p4.js} +9 -114
  35. package/dist/index.js +162 -35
  36. package/dist/node.js +30 -27
  37. package/dist/observability/event.d.ts +2 -16
  38. package/dist/observability/event.d.ts.map +1 -1
  39. package/dist/observability/index.js +28 -25
  40. package/dist/react.js +2 -2
  41. package/dist/realtime/contract.d.ts +9 -0
  42. package/dist/realtime/contract.d.ts.map +1 -1
  43. package/dist/realtime/index.d.ts +2 -1
  44. package/dist/realtime/index.d.ts.map +1 -1
  45. package/dist/realtime/request.d.ts +21 -0
  46. package/dist/realtime/request.d.ts.map +1 -0
  47. package/dist/realtime/socket.d.ts +3 -0
  48. package/dist/realtime/socket.d.ts.map +1 -1
  49. package/dist/remote.d.ts +9 -0
  50. package/dist/remote.d.ts.map +1 -0
  51. package/dist/remote.js +79 -0
  52. package/dist/server/context-contribution.d.ts +10 -0
  53. package/dist/server/context-contribution.d.ts.map +1 -0
  54. package/dist/server/context.d.ts.map +1 -1
  55. package/dist/server/index.d.ts +2 -1
  56. package/dist/server/index.d.ts.map +1 -1
  57. package/dist/server/index.js +133 -88
  58. package/dist/server/lifecycle.d.ts +4 -0
  59. package/dist/server/lifecycle.d.ts.map +1 -0
  60. package/dist/server/middleware/auth.d.ts +35 -7
  61. package/dist/server/middleware/auth.d.ts.map +1 -1
  62. package/dist/server/process-signal-common.d.ts +6 -0
  63. package/dist/server/process-signal-common.d.ts.map +1 -0
  64. package/dist/server/process-signals.d.ts.map +1 -1
  65. package/dist/server/types.d.ts +1 -1
  66. package/dist/server/types.d.ts.map +1 -1
  67. package/dist/testing/surface-conformance.d.ts +47 -0
  68. package/dist/testing/surface-conformance.d.ts.map +1 -0
  69. package/dist/testing/surface-manifest.d.ts +156 -0
  70. package/dist/testing/surface-manifest.d.ts.map +1 -0
  71. package/dist/testing.d.ts +2 -0
  72. package/dist/testing.d.ts.map +1 -1
  73. package/dist/testing.js +366 -3
  74. package/dist/tools/agent.d.ts.map +1 -1
  75. package/dist/tools/async-operation.d.ts +168 -0
  76. package/dist/tools/async-operation.d.ts.map +1 -0
  77. package/dist/tools/cli-args.d.ts +1 -1
  78. package/dist/tools/cli-args.d.ts.map +1 -1
  79. package/dist/tools/cli-command.d.ts +29 -0
  80. package/dist/tools/cli-command.d.ts.map +1 -0
  81. package/dist/tools/cli-format.d.ts +2 -2
  82. package/dist/tools/cli-format.d.ts.map +1 -1
  83. package/dist/tools/cli-wait.d.ts +11 -2
  84. package/dist/tools/cli-wait.d.ts.map +1 -1
  85. package/dist/tools/cli.d.ts +13 -6
  86. package/dist/tools/cli.d.ts.map +1 -1
  87. package/dist/tools/define-download-tool.d.ts +18 -0
  88. package/dist/tools/define-download-tool.d.ts.map +1 -0
  89. package/dist/tools/define-upload-tool.d.ts +16 -0
  90. package/dist/tools/define-upload-tool.d.ts.map +1 -0
  91. package/dist/tools/define-view-file-tool.d.ts +10 -0
  92. package/dist/tools/define-view-file-tool.d.ts.map +1 -0
  93. package/dist/tools/define-wait-tool.d.ts +22 -0
  94. package/dist/tools/define-wait-tool.d.ts.map +1 -0
  95. package/dist/tools/download-core.d.ts +20 -0
  96. package/dist/tools/download-core.d.ts.map +1 -0
  97. package/dist/tools/execute.d.ts +3 -1
  98. package/dist/tools/execute.d.ts.map +1 -1
  99. package/dist/tools/lifecycle.d.ts +4 -0
  100. package/dist/tools/lifecycle.d.ts.map +1 -0
  101. package/dist/tools/mcp-round.d.ts +0 -1
  102. package/dist/tools/mcp-round.d.ts.map +1 -1
  103. package/dist/tools/mcp-stdio-signals.d.ts +33 -0
  104. package/dist/tools/mcp-stdio-signals.d.ts.map +1 -0
  105. package/dist/tools/mount-download.d.ts +10 -4
  106. package/dist/tools/mount-download.d.ts.map +1 -1
  107. package/dist/tools/mount-upload.d.ts +4 -2
  108. package/dist/tools/mount-upload.d.ts.map +1 -1
  109. package/dist/tools/mount-wait.d.ts.map +1 -1
  110. package/dist/tools/native-definition.d.ts +15 -0
  111. package/dist/tools/native-definition.d.ts.map +1 -0
  112. package/dist/tools/runtime-tool.d.ts +5 -4
  113. package/dist/tools/runtime-tool.d.ts.map +1 -1
  114. package/dist/tools/surface.d.ts.map +1 -1
  115. package/dist/tools/upload-core.d.ts +4 -0
  116. package/dist/tools/upload-core.d.ts.map +1 -0
  117. package/dist/tools/view-file.d.ts +84 -23
  118. package/dist/tools/view-file.d.ts.map +1 -1
  119. package/dist/tools/wait-core.d.ts +16 -2
  120. package/dist/tools/wait-core.d.ts.map +1 -1
  121. package/dist/tools.d.ts +12 -3
  122. package/dist/tools.d.ts.map +1 -1
  123. package/dist/tools.js +827 -495
  124. package/llms-full.txt +720 -53
  125. package/package.json +10 -2
@@ -1,35 +1,44 @@
1
1
  import {
2
+ DEFAULT_PROCESS_SIGNALS,
3
+ RUNTIME_CONTEXT_RESERVED_KEYS,
2
4
  assertCorsConfig,
3
5
  corsHeaders,
4
- corsPreflightResponse
5
- } from "./index-yydqk4fh.js";
6
+ corsPreflightResponse,
7
+ defaultSignalSource,
8
+ guardSignalCallback,
9
+ reportSignalError
10
+ } from "./index-pzc32v75.js";
6
11
  import {
7
- AppError,
8
- badRequest,
9
12
  errorCode,
10
13
  extractIp,
11
14
  getClientInfo,
12
15
  getRequestContext,
13
- isUnsafeKey,
14
16
  normalizeError,
15
17
  parseQueryParams,
16
18
  recordedErrorMessage,
17
19
  resolveSocketIp,
18
20
  resolveTraceId,
19
21
  runWithRequestContext,
20
- safeJsonParse,
21
22
  setRequestEndpoint,
22
23
  setRequestError,
23
24
  validateDeclaredOutput,
24
25
  zodIssues
25
- } from "./index-173tvqcp.js";
26
+ } from "./index-v4bbq3p4.js";
27
+ import {
28
+ AppError,
29
+ badRequest,
30
+ isUnsafeKey,
31
+ safeJsonParse
32
+ } from "./index-h60df7rj.js";
26
33
  import {
27
- __require,
28
34
  isRecord,
29
35
  parseTrailingWildcard,
30
36
  resolveTraceContext,
31
37
  transportResult
32
- } from "./index-bmnhqtya.js";
38
+ } from "./index-7eq9va6e.js";
39
+ import {
40
+ __require
41
+ } from "./index-1bx83sw4.js";
33
42
 
34
43
  // src/server/multipart.ts
35
44
  var DEFAULT_MAX_REQUEST_BYTES = 25 * 1024 * 1024;
@@ -496,19 +505,6 @@ async function readRequestText(req, maxBytes) {
496
505
  }
497
506
 
498
507
  // src/server/context.ts
499
- var RESERVED_KEYS = new Set([
500
- "params",
501
- "input",
502
- "source",
503
- "req",
504
- "url",
505
- "headers",
506
- "rawBody",
507
- "traceId",
508
- "spanId",
509
- "ipAddress",
510
- "userAgent"
511
- ]);
512
508
  function parseJsonBody(req, text) {
513
509
  if (text.trim() === "")
514
510
  return {};
@@ -524,7 +520,7 @@ function parseJsonBody(req, text) {
524
520
  function buildBaseContext(req, url, pathParams, traceId, clientIp) {
525
521
  const safePathParams = {};
526
522
  for (const [k, v] of Object.entries(pathParams)) {
527
- if (!RESERVED_KEYS.has(k) && !isUnsafeKey(k))
523
+ if (!RUNTIME_CONTEXT_RESERVED_KEYS.has(k) && !isUnsafeKey(k))
528
524
  safePathParams[k] = v;
529
525
  }
530
526
  return {
@@ -534,6 +530,7 @@ function buildBaseContext(req, url, pathParams, traceId, clientIp) {
534
530
  req,
535
531
  url,
536
532
  headers: req.headers,
533
+ signal: req.signal,
537
534
  ...safePathParams,
538
535
  traceId,
539
536
  ...getClientInfo(req, clientIp)
@@ -581,6 +578,7 @@ function buildErrorContext(req, url, traceId, clientIp) {
581
578
  req,
582
579
  url,
583
580
  headers: req.headers,
581
+ signal: req.signal,
584
582
  traceId,
585
583
  ...getClientInfo(req, clientIp)
586
584
  };
@@ -1606,40 +1604,13 @@ function createServerLifecycle(getAdapter) {
1606
1604
  }
1607
1605
 
1608
1606
  // src/server/process-signals.ts
1609
- var DEFAULT_SIGNALS = ["SIGINT", "SIGTERM"];
1610
- var defaultSignalSource = {
1611
- on: (signal, handler) => {
1612
- process.on(signal, handler);
1613
- },
1614
- off: (signal, handler) => {
1615
- process.off(signal, handler);
1616
- },
1617
- raiseDefault: (signal) => {
1618
- if (process.listenerCount(signal) > 0)
1619
- return false;
1620
- process.kill(process.pid, signal);
1621
- return true;
1622
- }
1623
- };
1624
1607
  var bound = new WeakSet;
1625
- function reportError(phase, error, onError) {
1626
- try {
1627
- onError?.(phase, error);
1628
- } catch {}
1629
- }
1630
- function guard(run, phase, onError) {
1631
- try {
1632
- run();
1633
- } catch (error) {
1634
- reportError(phase, error, onError);
1635
- }
1636
- }
1637
1608
  function bindProcessSignals(handle, options = {}) {
1638
1609
  if (bound.has(handle)) {
1639
1610
  throw new Error("[stitchkit] bindProcessSignals: this server is already bound; close the first binding before creating another");
1640
1611
  }
1641
1612
  bound.add(handle);
1642
- const signals = [...new Set(options.signals ?? DEFAULT_SIGNALS)];
1613
+ const signals = [...new Set(options.signals ?? DEFAULT_PROCESS_SIGNALS)];
1643
1614
  const source = options.signalSource ?? defaultSignalSource;
1644
1615
  const budgets = ShutdownOptionsSchema.omit({ signal: true }).parse(options.shutdown ?? {});
1645
1616
  const controller = new AbortController;
@@ -1680,7 +1651,7 @@ function bindProcessSignals(handle, options = {}) {
1680
1651
  try {
1681
1652
  await options.onShutdown?.(signal);
1682
1653
  } catch (error) {
1683
- reportError("prepare", error, options.onError);
1654
+ reportSignalError("prepare", error, options.onError);
1684
1655
  }
1685
1656
  let result;
1686
1657
  try {
@@ -1688,7 +1659,7 @@ function bindProcessSignals(handle, options = {}) {
1688
1659
  } catch (error) {
1689
1660
  settled = true;
1690
1661
  rejectChain(error);
1691
- reportError("shutdown", error, options.onError);
1662
+ reportSignalError("shutdown", error, options.onError);
1692
1663
  removeListeners();
1693
1664
  return;
1694
1665
  }
@@ -1697,7 +1668,7 @@ function bindProcessSignals(handle, options = {}) {
1697
1668
  try {
1698
1669
  await options.onComplete?.(result);
1699
1670
  } catch (error) {
1700
- reportError("complete", error, options.onError);
1671
+ reportSignalError("complete", error, options.onError);
1701
1672
  } finally {
1702
1673
  removeListeners();
1703
1674
  }
@@ -1709,26 +1680,26 @@ function bindProcessSignals(handle, options = {}) {
1709
1680
  queueMicrotask(() => {
1710
1681
  sameTurnAsStart = false;
1711
1682
  });
1712
- run(signal).catch((error) => reportError("shutdown", error, options.onError));
1683
+ run(signal).catch((error) => reportSignalError("shutdown", error, options.onError));
1713
1684
  return;
1714
1685
  }
1715
1686
  if (sameTurnAsStart)
1716
1687
  return;
1717
1688
  if (!settled && !controller.signal.aborted) {
1718
1689
  controller.abort();
1719
- guard(() => options.onRepeatedSignal?.(signal, "force"), "shutdown", options.onError);
1690
+ guardSignalCallback(() => options.onRepeatedSignal?.(signal, "force"), "shutdown", options.onError);
1720
1691
  return;
1721
1692
  }
1722
1693
  removeListeners();
1723
- guard(() => options.onRepeatedSignal?.(signal, "escalate"), "shutdown", options.onError);
1694
+ guardSignalCallback(() => options.onRepeatedSignal?.(signal, "escalate"), "shutdown", options.onError);
1724
1695
  let restored = false;
1725
1696
  try {
1726
1697
  restored = source.raiseDefault(signal);
1727
1698
  } catch (error) {
1728
- reportError("shutdown", error, options.onError);
1699
+ reportSignalError("shutdown", error, options.onError);
1729
1700
  }
1730
1701
  if (!restored) {
1731
- guard(() => options.onEscalationBlocked?.(signal), "shutdown", options.onError);
1702
+ guardSignalCallback(() => options.onEscalationBlocked?.(signal), "shutdown", options.onError);
1732
1703
  }
1733
1704
  };
1734
1705
  for (const signal of signals) {
@@ -1,12 +1,13 @@
1
1
  import {
2
+ isUnsafeKey,
2
3
  mergeMeta
3
- } from "./index-173tvqcp.js";
4
+ } from "./index-h60df7rj.js";
4
5
  import {
5
6
  callRuntimeHandler,
6
7
  isRecord,
7
8
  transportResult,
8
9
  typedEntries
9
- } from "./index-bmnhqtya.js";
10
+ } from "./index-7eq9va6e.js";
10
11
 
11
12
  // src/server/middleware/cors.ts
12
13
  var DEFAULT_CORS_ALLOW_HEADERS = "Content-Type, Authorization, X-Trace-Id, traceparent, tracestate";
@@ -246,4 +247,90 @@ function createImplementRegistry() {
246
247
  return (contracts, handlers) => transportResult(bindRegistry(contracts, handlers));
247
248
  }
248
249
 
249
- export { DEFAULT_CORS_ALLOW_HEADERS, DEFAULT_CORS_EXPOSE_HEADERS, assertCorsConfig, corsHeaders, corsPreflightResponse, defineMultipartStream, createMultipartStream, contractOnlyService, implement, createImplement, createScopedImplement, createScopedImplementRegistry, implementRegistry, createImplementRegistry };
250
+ // src/server/context-contribution.ts
251
+ var RUNTIME_CONTEXT_RESERVED_KEYS = new Set([
252
+ "params",
253
+ "input",
254
+ "files",
255
+ "rawBody",
256
+ "source",
257
+ "req",
258
+ "url",
259
+ "headers",
260
+ "traceId",
261
+ "spanId",
262
+ "ipAddress",
263
+ "userAgent",
264
+ "signal",
265
+ "mcp"
266
+ ]);
267
+ function contributionError(scope, reason) {
268
+ return new TypeError(`[stitchkit] auth: invalid context contribution for scope ${JSON.stringify(scope)}: ${reason}`);
269
+ }
270
+ function mergeContextContribution(ctx, value, scope) {
271
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
272
+ throw contributionError(scope, "expected a plain record");
273
+ }
274
+ let prototype;
275
+ let descriptors;
276
+ let keys;
277
+ try {
278
+ prototype = Object.getPrototypeOf(value);
279
+ descriptors = Object.getOwnPropertyDescriptors(value);
280
+ keys = Reflect.ownKeys(value);
281
+ } catch {
282
+ throw contributionError(scope, "record inspection failed");
283
+ }
284
+ if (prototype !== Object.prototype && prototype !== null) {
285
+ throw contributionError(scope, "expected Object.prototype or null prototype");
286
+ }
287
+ const prepared = Object.create(null);
288
+ for (const key of keys) {
289
+ if (typeof key !== "string") {
290
+ throw contributionError(scope, "symbol keys are not supported");
291
+ }
292
+ if (isUnsafeKey(key)) {
293
+ throw contributionError(scope, `unsafe key ${JSON.stringify(key)}`);
294
+ }
295
+ if (RUNTIME_CONTEXT_RESERVED_KEYS.has(key)) {
296
+ throw contributionError(scope, `reserved key ${JSON.stringify(key)}`);
297
+ }
298
+ const descriptor = descriptors[key];
299
+ if (!descriptor?.enumerable || !("value" in descriptor)) {
300
+ throw contributionError(scope, `key ${JSON.stringify(key)} must be enumerable data`);
301
+ }
302
+ prepared[key] = descriptor.value;
303
+ }
304
+ Object.assign(ctx, prepared);
305
+ }
306
+
307
+ // src/server/process-signal-common.ts
308
+ var DEFAULT_PROCESS_SIGNALS = ["SIGINT", "SIGTERM"];
309
+ var defaultSignalSource = {
310
+ on: (signal, handler) => {
311
+ process.on(signal, handler);
312
+ },
313
+ off: (signal, handler) => {
314
+ process.off(signal, handler);
315
+ },
316
+ raiseDefault: (signal) => {
317
+ if (process.listenerCount(signal) > 0)
318
+ return false;
319
+ process.kill(process.pid, signal);
320
+ return true;
321
+ }
322
+ };
323
+ function reportSignalError(phase, error, onError) {
324
+ try {
325
+ onError?.(phase, error);
326
+ } catch {}
327
+ }
328
+ function guardSignalCallback(run, phase, onError) {
329
+ try {
330
+ run();
331
+ } catch (error) {
332
+ reportSignalError(phase, error, onError);
333
+ }
334
+ }
335
+
336
+ export { RUNTIME_CONTEXT_RESERVED_KEYS, mergeContextContribution, DEFAULT_CORS_ALLOW_HEADERS, DEFAULT_CORS_EXPOSE_HEADERS, assertCorsConfig, corsHeaders, corsPreflightResponse, defineMultipartStream, createMultipartStream, contractOnlyService, implement, createImplement, createScopedImplement, createScopedImplementRegistry, implementRegistry, createImplementRegistry, DEFAULT_PROCESS_SIGNALS, defaultSignalSource, reportSignalError, guardSignalCallback };
@@ -6,7 +6,7 @@ import {
6
6
  mapObject,
7
7
  parseTrailingWildcard,
8
8
  typedEntries
9
- } from "./index-bmnhqtya.js";
9
+ } from "./index-7eq9va6e.js";
10
10
 
11
11
  // src/browser/cancellation.ts
12
12
  class RequestCancellationError extends Error {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  isUnsafeKey
3
- } from "./index-173tvqcp.js";
3
+ } from "./index-h60df7rj.js";
4
4
  import {
5
5
  isRecord
6
- } from "./index-bmnhqtya.js";
6
+ } from "./index-7eq9va6e.js";
7
7
 
8
8
  // src/observability/sanitize.ts
9
9
  var SENSITIVE_WORDS = new Set([
@@ -350,8 +350,26 @@ function createContractFactory(config) {
350
350
  };
351
351
  return { defineContract: explicit };
352
352
  }
353
- // src/contract/pagination.ts
353
+ // src/contract/file-ref.ts
354
354
  import { z as z3 } from "zod";
355
+ function isManagedFilePath(value) {
356
+ if (value.length === 0 || value.includes("\x00") || value.includes("\\"))
357
+ return false;
358
+ if (value.startsWith("/") || value.startsWith("//") || /^[A-Za-z]:/.test(value)) {
359
+ return false;
360
+ }
361
+ const parts = value.split("/");
362
+ return parts.every((part) => part.length > 0 && part !== "." && part !== "..");
363
+ }
364
+ var ManagedFilePathSchema = z3.string().refine(isManagedFilePath, "expected a canonical relative managed-file path");
365
+ var ManagedFileRefSchema = z3.object({
366
+ path: ManagedFilePathSchema,
367
+ size: z3.number().int().nonnegative(),
368
+ mediaType: z3.string().min(1).optional(),
369
+ name: z3.string().min(1).optional()
370
+ });
371
+ // src/contract/pagination.ts
372
+ import { z as z4 } from "zod";
355
373
 
356
374
  // src/internal/base64url.ts
357
375
  function bytesToBase64Url(bytes) {
@@ -371,9 +389,9 @@ function base64UrlToBytes(segment) {
371
389
 
372
390
  // src/contract/pagination.ts
373
391
  function paginatedSchema(itemSchema) {
374
- return z3.object({
375
- items: z3.array(itemSchema),
376
- nextCursor: z3.string().nullable()
392
+ return z4.object({
393
+ items: z4.array(itemSchema),
394
+ nextCursor: z4.string().nullable()
377
395
  });
378
396
  }
379
397
  function toBase64Url(str) {
@@ -395,4 +413,4 @@ function decodeCursor(cursor, schema) {
395
413
  return null;
396
414
  }
397
415
  }
398
- export { parseTrailingWildcard, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, ALL_TRANSPORTS, defineContract, defineErrors, createContractFactory, paginatedSchema, encodeCursor, decodeCursor };
416
+ export { parseTrailingWildcard, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, ALL_TRANSPORTS, defineContract, defineErrors, createContractFactory, ManagedFilePathSchema, ManagedFileRefSchema, paginatedSchema, encodeCursor, decodeCursor };
@@ -0,0 +1,18 @@
1
+ // src/internal/within-dir.ts
2
+ import { realpath } from "node:fs/promises";
3
+ import { sep } from "node:path";
4
+ function isWithinDir(root, target) {
5
+ const base = root.endsWith(sep) ? root.slice(0, -sep.length) : root;
6
+ return target === root || target === base || target.startsWith(base + sep);
7
+ }
8
+ async function realPathWithinDir(root, target) {
9
+ const [realRoot, realTarget] = await Promise.all([
10
+ realpath(root).catch(() => null),
11
+ realpath(target).catch(() => null)
12
+ ]);
13
+ if (realRoot === null || realTarget === null)
14
+ return null;
15
+ return isWithinDir(realRoot, realTarget) ? realTarget : null;
16
+ }
17
+
18
+ export { isWithinDir, realPathWithinDir };
@@ -1,119 +1,14 @@
1
+ import {
2
+ AppError,
3
+ isUnsafeKey
4
+ } from "./index-h60df7rj.js";
1
5
  import {
2
6
  isRecord,
3
7
  resolveTraceContext
4
- } from "./index-bmnhqtya.js";
5
-
6
- // src/contract/errors.ts
7
- var APP_ERROR_BRAND = Symbol.for("stitchkit.AppError");
8
-
9
- class AppError extends Error {
10
- code;
11
- status;
12
- details;
13
- hint;
14
- traceId;
15
- constructor(code, message, status = 500, details, hint, traceId) {
16
- super(message ?? code);
17
- this.code = code;
18
- this.status = status;
19
- this.details = details;
20
- this.hint = hint;
21
- this.traceId = traceId;
22
- this.name = "AppError";
23
- Object.defineProperty(this, APP_ERROR_BRAND, { value: true });
24
- }
25
- static is(err) {
26
- return typeof err === "object" && err !== null && APP_ERROR_BRAND in err;
27
- }
28
- toJSON() {
29
- return {
30
- error: {
31
- code: this.code,
32
- message: this.message,
33
- ...this.details && { details: this.details },
34
- ...this.hint && { hint: this.hint }
35
- }
36
- };
37
- }
38
- }
39
- function notFound(message = "Not found") {
40
- throw new AppError("NOT_FOUND", message, 404);
41
- }
42
- function badRequest(message, details) {
43
- throw new AppError("BAD_REQUEST", message, 400, details);
44
- }
45
- function unauthorized(message = "Unauthorized") {
46
- throw new AppError("UNAUTHORIZED", message, 401);
47
- }
48
- function forbidden(message = "Forbidden") {
49
- throw new AppError("FORBIDDEN", message, 403);
50
- }
51
- function conflict(message = "Conflict", details) {
52
- throw new AppError("CONFLICT", message, 409, details);
53
- }
54
- function rateLimited(message = "Too many requests") {
55
- throw new AppError("RATE_LIMITED", message, 429);
56
- }
57
- var STITCH_ERROR_STATUS = {
58
- BAD_REQUEST: 400,
59
- UNAUTHORIZED: 401,
60
- FORBIDDEN: 403,
61
- NOT_FOUND: 404,
62
- METHOD_NOT_ALLOWED: 405,
63
- CONFLICT: 409,
64
- RATE_LIMITED: 429,
65
- VALIDATION_ERROR: 400,
66
- REALTIME_CONTRACT_VIOLATION: 500,
67
- INTERNAL_SERVER_ERROR: 500
68
- };
69
- function isStitchErrorCode(code) {
70
- return Object.hasOwn(STITCH_ERROR_STATUS, code);
71
- }
72
- function appError(code, message, details) {
73
- throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
74
- }
75
-
76
- // src/contract/define.ts
77
- import { z } from "zod";
78
-
79
- // src/internal/safe-json.ts
80
- function isUnsafeKey(key) {
81
- return key === "__proto__";
82
- }
83
- function safeJsonParse(text) {
84
- return JSON.parse(text, (key, value) => isUnsafeKey(key) ? undefined : value);
85
- }
86
-
87
- // src/contract/define.ts
88
- function mergeMeta(contractMeta, endpointMeta) {
89
- if (!contractMeta)
90
- return endpointMeta;
91
- if (!endpointMeta)
92
- return { ...contractMeta };
93
- return { ...contractMeta, ...endpointMeta };
94
- }
95
- // src/contract/errors-factory.ts
96
- import { z as z2 } from "zod";
97
- // src/contract/pagination.ts
98
- import { z as z3 } from "zod";
8
+ } from "./index-7eq9va6e.js";
99
9
 
100
- // src/internal/base64url.ts
101
- function bytesToBase64Url(bytes) {
102
- let binary = "";
103
- for (const byte of bytes)
104
- binary += String.fromCharCode(byte);
105
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
106
- }
107
- function base64UrlToBytes(segment) {
108
- if (!/^[A-Za-z0-9_-]*$/.test(segment) || segment.length % 4 === 1) {
109
- throw new Error("invalid base64url segment");
110
- }
111
- const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
112
- const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
113
- return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
114
- }
115
10
  // src/internal/errors.ts
116
- import { z as z4 } from "zod";
11
+ import { z } from "zod";
117
12
  function issuePath(path) {
118
13
  return path.length > 0 ? path.map(String).join(".") : "(root)";
119
14
  }
@@ -136,7 +31,7 @@ var MAX_DETAIL_ISSUES = 20;
136
31
  function errorCode(err) {
137
32
  if (AppError.is(err))
138
33
  return err.code;
139
- if (err instanceof z4.ZodError)
34
+ if (err instanceof z.ZodError)
140
35
  return "VALIDATION_ERROR";
141
36
  return;
142
37
  }
@@ -156,7 +51,7 @@ function normalizeError(err) {
156
51
  }
157
52
  return err;
158
53
  }
159
- if (err instanceof z4.ZodError) {
54
+ if (err instanceof z.ZodError) {
160
55
  return new AppError("VALIDATION_ERROR", formatZodError(err), 400, {
161
56
  issues: zodIssues(err).slice(0, MAX_DETAIL_ISSUES)
162
57
  });
@@ -322,4 +217,4 @@ function wrapInRequestContext(handler, options = {}) {
322
217
  };
323
218
  }
324
219
 
325
- export { isUnsafeKey, safeJsonParse, mergeMeta, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, bytesToBase64Url, base64UrlToBytes, formatZodError, zodIssues, errorCode, recordedErrorMessage, normalizeError, validateDeclaredOutput, generateTraceId, resolveTraceId, resolveSocketIp, extractIp, getClientInfo, parseQueryParams, runWithRequestContext, getRequestContext, getTraceId, getUserId, setRequestUser, setRequestEndpoint, setRequestDimensions, setRequestError, wrapInRequestContext };
220
+ export { formatZodError, zodIssues, errorCode, recordedErrorMessage, normalizeError, validateDeclaredOutput, generateTraceId, resolveTraceId, resolveSocketIp, extractIp, getClientInfo, parseQueryParams, runWithRequestContext, getRequestContext, getTraceId, getUserId, setRequestUser, setRequestEndpoint, setRequestDimensions, setRequestError, wrapInRequestContext };