stitchkit 0.45.0 → 0.47.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 (122) hide show
  1. package/README.md +5 -4
  2. package/dist/browser/cancellation.d.ts +14 -0
  3. package/dist/browser/cancellation.d.ts.map +1 -0
  4. package/dist/browser/client-multipart.d.ts +3 -1
  5. package/dist/browser/client-multipart.d.ts.map +1 -1
  6. package/dist/browser/client.d.ts +1 -0
  7. package/dist/browser/client.d.ts.map +1 -1
  8. package/dist/browser/http.d.ts +1 -0
  9. package/dist/browser/http.d.ts.map +1 -1
  10. package/dist/browser/socket-io.d.ts +3 -1
  11. package/dist/browser/socket-io.d.ts.map +1 -1
  12. package/dist/cli.js +3 -4
  13. package/dist/contract/define.d.ts +59 -15
  14. package/dist/contract/define.d.ts.map +1 -1
  15. package/dist/contract/errors.d.ts +1 -0
  16. package/dist/contract/errors.d.ts.map +1 -1
  17. package/dist/contract/index.d.ts +1 -1
  18. package/dist/contract/index.d.ts.map +1 -1
  19. package/dist/contract/index.js +2 -2
  20. package/dist/{index-w0mec79h.js → index-44xysy8r.js} +697 -301
  21. package/dist/{index-r6czv7yt.js → index-45dz4m51.js} +50 -3
  22. package/dist/index-8ekq6res.js +181 -0
  23. package/dist/{index-yh0p5ddn.js → index-ee621cmy.js} +39 -19
  24. package/dist/{index-mvjyq9h9.js → index-kp8xamqp.js} +309 -144
  25. package/dist/{index-36f1xkdb.js → index-nrytvb30.js} +5 -4
  26. package/dist/{index-6jypn22c.js → index-r1qp4rve.js} +9 -1
  27. package/dist/{index-s4qsmgwe.js → index-tss6bk5c.js} +4 -1
  28. package/dist/index-yxpe3phd.js +63 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +315 -134
  32. package/dist/internal/errors.d.ts.map +1 -1
  33. package/dist/internal/secure-fetch.d.ts +23 -3
  34. package/dist/internal/secure-fetch.d.ts.map +1 -1
  35. package/dist/internal/typed.d.ts +7 -0
  36. package/dist/internal/typed.d.ts.map +1 -1
  37. package/dist/internal/within-dir.d.ts +6 -0
  38. package/dist/internal/within-dir.d.ts.map +1 -1
  39. package/dist/logger.d.ts +8 -0
  40. package/dist/logger.d.ts.map +1 -0
  41. package/dist/node.js +3 -4
  42. package/dist/observability/audit.d.ts +22 -3
  43. package/dist/observability/audit.d.ts.map +1 -1
  44. package/dist/observability/event.d.ts +7 -0
  45. package/dist/observability/event.d.ts.map +1 -1
  46. package/dist/observability/index.d.ts +1 -1
  47. package/dist/observability/index.d.ts.map +1 -1
  48. package/dist/observability/index.js +130 -134
  49. package/dist/observability/sanitize.d.ts +8 -1
  50. package/dist/observability/sanitize.d.ts.map +1 -1
  51. package/dist/observability/trace.d.ts +3 -1
  52. package/dist/observability/trace.d.ts.map +1 -1
  53. package/dist/react/cache-bridge.d.ts +4 -0
  54. package/dist/react/cache-bridge.d.ts.map +1 -1
  55. package/dist/react.js +46 -5
  56. package/dist/realtime/contract.d.ts +4 -1
  57. package/dist/realtime/contract.d.ts.map +1 -1
  58. package/dist/realtime/rejection.d.ts +10 -0
  59. package/dist/realtime/rejection.d.ts.map +1 -0
  60. package/dist/realtime/socket.d.ts +14 -1
  61. package/dist/realtime/socket.d.ts.map +1 -1
  62. package/dist/server/cache.d.ts +5 -1
  63. package/dist/server/cache.d.ts.map +1 -1
  64. package/dist/server/context.d.ts +8 -5
  65. package/dist/server/context.d.ts.map +1 -1
  66. package/dist/server/create.d.ts.map +1 -1
  67. package/dist/server/error-hook.d.ts +1 -0
  68. package/dist/server/error-hook.d.ts.map +1 -1
  69. package/dist/server/file.d.ts +6 -0
  70. package/dist/server/file.d.ts.map +1 -1
  71. package/dist/server/implement.d.ts +33 -2
  72. package/dist/server/implement.d.ts.map +1 -1
  73. package/dist/server/index.d.ts +5 -6
  74. package/dist/server/index.d.ts.map +1 -1
  75. package/dist/server/index.js +133 -14
  76. package/dist/server/middleware/auth.d.ts +7 -4
  77. package/dist/server/middleware/auth.d.ts.map +1 -1
  78. package/dist/server/middleware/cors.d.ts.map +1 -1
  79. package/dist/server/multipart.d.ts +13 -18
  80. package/dist/server/multipart.d.ts.map +1 -1
  81. package/dist/server/openapi.d.ts.map +1 -1
  82. package/dist/server/realtime.d.ts +2 -0
  83. package/dist/server/realtime.d.ts.map +1 -1
  84. package/dist/server/router.d.ts +0 -8
  85. package/dist/server/router.d.ts.map +1 -1
  86. package/dist/server/stream.d.ts.map +1 -1
  87. package/dist/server/types.d.ts +50 -22
  88. package/dist/server/types.d.ts.map +1 -1
  89. package/dist/tools/cli-args.d.ts +11 -3
  90. package/dist/tools/cli-args.d.ts.map +1 -1
  91. package/dist/tools/cli.d.ts +5 -0
  92. package/dist/tools/cli.d.ts.map +1 -1
  93. package/dist/tools/coerce.d.ts.map +1 -1
  94. package/dist/tools/json-schema.d.ts.map +1 -1
  95. package/dist/tools/mcp-handler.d.ts +4 -3
  96. package/dist/tools/mcp-handler.d.ts.map +1 -1
  97. package/dist/tools/mcp-prepare.d.ts +95 -0
  98. package/dist/tools/mcp-prepare.d.ts.map +1 -0
  99. package/dist/tools/mcp-round.d.ts +4 -0
  100. package/dist/tools/mcp-round.d.ts.map +1 -1
  101. package/dist/tools/mcp-stdio.d.ts +2 -1
  102. package/dist/tools/mcp-stdio.d.ts.map +1 -1
  103. package/dist/tools/mcp.d.ts +2 -78
  104. package/dist/tools/mcp.d.ts.map +1 -1
  105. package/dist/tools/mount-download.d.ts +5 -0
  106. package/dist/tools/mount-download.d.ts.map +1 -1
  107. package/dist/tools/native-mcp.d.ts +1 -1
  108. package/dist/tools/native-mcp.d.ts.map +1 -1
  109. package/dist/tools/oauth-provider.d.ts +20 -1
  110. package/dist/tools/oauth-provider.d.ts.map +1 -1
  111. package/dist/tools/tool-logger.d.ts +1 -1
  112. package/dist/tools/tool-logger.d.ts.map +1 -1
  113. package/dist/tools/view-file.d.ts +9 -0
  114. package/dist/tools/view-file.d.ts.map +1 -1
  115. package/dist/tools.d.ts +2 -1
  116. package/dist/tools.d.ts.map +1 -1
  117. package/dist/tools.js +505 -278
  118. package/llms-full.txt +473 -85
  119. package/llms.txt +1 -1
  120. package/package.json +2 -2
  121. package/dist/index-frfyw9fa.js +0 -33
  122. package/dist/index-x3fcszf8.js +0 -8
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapObjectTypeBoundary
3
- } from "./index-s4qsmgwe.js";
3
+ } from "./index-tss6bk5c.js";
4
4
 
5
5
  // src/contract/define.ts
6
6
  import { z } from "zod";
@@ -47,6 +47,11 @@ function parseTrailingWildcard(path) {
47
47
  return wildcard;
48
48
  }
49
49
 
50
+ // src/internal/safe-json.ts
51
+ function isUnsafeKey(key) {
52
+ return key === "__proto__";
53
+ }
54
+
50
55
  // src/contract/define.ts
51
56
  var ALL_TRANSPORTS = ["HTTP", "MCP", "AGENT", "CLI"];
52
57
  function defineContract(meta, endpoints) {
@@ -68,6 +73,8 @@ function defineContract(meta, endpoints) {
68
73
  if (ep.maxJsonBodyBytes !== undefined && (!Number.isSafeInteger(ep.maxJsonBodyBytes) || ep.maxJsonBodyBytes <= 0)) {
69
74
  throw new Error(`Contract "${meta.prefix}": endpoint "${key}" maxJsonBodyBytes must be a positive safe integer, received ${ep.maxJsonBodyBytes}`);
70
75
  }
76
+ if (ep.multipart)
77
+ assertMultipartEndpoint(meta.prefix, key, ep);
71
78
  if (ep.rawResponse)
72
79
  assertRawEndpoint(meta.prefix, key, ep);
73
80
  if (ep.method === "HEAD")
@@ -96,6 +103,45 @@ function defineContract(meta, endpoints) {
96
103
  }
97
104
  return { meta, endpoints };
98
105
  }
106
+ function assertPositiveLimit(where, name, value) {
107
+ if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {
108
+ throw new Error(`${where} ${name} must be a positive safe integer, received ${value}`);
109
+ }
110
+ }
111
+ function assertMultipartEndpoint(prefix, key, ep) {
112
+ const where = `Contract "${prefix}": multipart endpoint "${key}"`;
113
+ if (ep.method !== "POST" && ep.method !== "PUT" && ep.method !== "PATCH") {
114
+ throw new Error(`${where} must use POST, PUT or PATCH`);
115
+ }
116
+ const multipart = ep.multipart;
117
+ if (!multipart || typeof multipart !== "object") {
118
+ throw new Error(`${where} must declare a multipart descriptor`);
119
+ }
120
+ assertPositiveLimit(where, "maxRequestBytes", multipart.maxRequestBytes);
121
+ assertPositiveLimit(where, "maxFieldBytes", multipart.maxFieldBytes);
122
+ const entries = Object.entries(multipart.files);
123
+ if (entries.length === 0)
124
+ throw new Error(`${where} must declare at least one file field`);
125
+ for (const [field, policy] of entries) {
126
+ if (!field || isUnsafeKey(field))
127
+ throw new Error(`${where} has an invalid file field name`);
128
+ assertPositiveLimit(`${where} field "${field}"`, "maxBytes", policy.maxBytes);
129
+ assertPositiveLimit(`${where} field "${field}"`, "maxFiles", policy.maxFiles);
130
+ if (policy.multiple !== true && policy.maxFiles !== undefined) {
131
+ throw new Error(`${where} field "${field}" may set maxFiles only with multiple: true`);
132
+ }
133
+ if (policy.contentTypes) {
134
+ if (policy.contentTypes.length === 0) {
135
+ throw new Error(`${where} field "${field}" contentTypes cannot be empty`);
136
+ }
137
+ for (const contentType of policy.contentTypes) {
138
+ if (!/^[a-z0-9!#$&^_.+-]+\/(?:[a-z0-9!#$&^_.+-]+|\*)$/i.test(contentType)) {
139
+ throw new Error(`${where} field "${field}" has invalid content type policy "${contentType}"`);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
99
145
  function assertRawEndpoint(prefix, key, ep) {
100
146
  const where = `Contract "${prefix}": raw endpoint "${key}"`;
101
147
  if (ep.output)
@@ -228,10 +274,11 @@ var STITCH_ERROR_STATUS = {
228
274
  CONFLICT: 409,
229
275
  RATE_LIMITED: 429,
230
276
  VALIDATION_ERROR: 400,
277
+ REALTIME_CONTRACT_VIOLATION: 500,
231
278
  INTERNAL_SERVER_ERROR: 500
232
279
  };
233
280
  function isStitchErrorCode(code) {
234
- return code in STITCH_ERROR_STATUS;
281
+ return Object.hasOwn(STITCH_ERROR_STATUS, code);
235
282
  }
236
283
  function appError(code, message, details) {
237
284
  throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
@@ -342,4 +389,4 @@ function decodeCursor(cursor, schema) {
342
389
  return null;
343
390
  }
344
391
  }
345
- export { parseTrailingWildcard, ALL_TRANSPORTS, defineContract, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, defineErrors, createContractFactory, paginatedSchema, encodeCursor, decodeCursor };
392
+ export { parseTrailingWildcard, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, ALL_TRANSPORTS, defineContract, defineErrors, createContractFactory, paginatedSchema, encodeCursor, decodeCursor };
@@ -0,0 +1,181 @@
1
+ import {
2
+ isRecord,
3
+ isUnsafeKey
4
+ } from "./index-ee621cmy.js";
5
+
6
+ // src/observability/sanitize.ts
7
+ var SENSITIVE_WORDS = new Set([
8
+ "password",
9
+ "passwords",
10
+ "passwd",
11
+ "pwd",
12
+ "secret",
13
+ "secrets",
14
+ "token",
15
+ "tokens",
16
+ "apikey",
17
+ "auth",
18
+ "authorization",
19
+ "bearer",
20
+ "cookie",
21
+ "cookies",
22
+ "credential",
23
+ "credentials"
24
+ ]);
25
+ var SENSITIVE_WORD_PAIRS = new Set([
26
+ "apikey",
27
+ "privatekey",
28
+ "initdata",
29
+ "sessionid",
30
+ "sessionkey"
31
+ ]);
32
+ var SENSITIVE_EXACT = new Set(["session"]);
33
+ function splitKeyWords(key) {
34
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 0);
35
+ }
36
+ function isSensitiveKeyDefault(key) {
37
+ const words = splitKeyWords(key);
38
+ if (words.length === 1 && SENSITIVE_EXACT.has(words[0] ?? ""))
39
+ return true;
40
+ for (let index = 0;index < words.length; index += 1) {
41
+ const word = words[index] ?? "";
42
+ if (SENSITIVE_WORDS.has(word))
43
+ return true;
44
+ const next = words[index + 1];
45
+ if (next !== undefined && SENSITIVE_WORD_PAIRS.has(word + next))
46
+ return true;
47
+ }
48
+ return false;
49
+ }
50
+ var DEFAULT_MAX_BYTES = 16000;
51
+ var DEFAULT_MAX_DEPTH = 20;
52
+ var MASK = "[redacted]";
53
+ function redact(value, options = {}) {
54
+ const custom = options.sensitiveKeys;
55
+ const isSensitive = custom === undefined ? isSensitiveKeyDefault : (key) => {
56
+ custom.lastIndex = 0;
57
+ return custom.test(key);
58
+ };
59
+ const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
60
+ const ancestors = new Set;
61
+ const walk = (input, depth) => {
62
+ if (depth > maxDepth)
63
+ return "[max depth]";
64
+ if (input === null || input === undefined)
65
+ return null;
66
+ if (typeof input === "string" || typeof input === "number" || typeof input === "boolean") {
67
+ return input;
68
+ }
69
+ if (input instanceof Uint8Array || input instanceof ArrayBuffer) {
70
+ return { _type: "binary", size: input.byteLength };
71
+ }
72
+ if (input instanceof Blob) {
73
+ return { _type: "blob", size: input.size, mime: input.type };
74
+ }
75
+ if (typeof FormData !== "undefined" && input instanceof FormData) {
76
+ return { _type: "formdata", keys: [...input.keys()] };
77
+ }
78
+ if (input instanceof Map) {
79
+ if (ancestors.has(input))
80
+ return "[circular]";
81
+ ancestors.add(input);
82
+ const result = [...input.entries()].map(([key, value2]) => [
83
+ walk(key, depth + 1),
84
+ walk(value2, depth + 1)
85
+ ]);
86
+ ancestors.delete(input);
87
+ return { _type: "map", entries: result };
88
+ }
89
+ if (input instanceof Set) {
90
+ if (ancestors.has(input))
91
+ return "[circular]";
92
+ ancestors.add(input);
93
+ const values = [...input].map((item) => walk(item, depth + 1));
94
+ ancestors.delete(input);
95
+ return { _type: "set", values };
96
+ }
97
+ if (input instanceof Error) {
98
+ return {
99
+ _type: "error",
100
+ name: input.name,
101
+ message: input.message,
102
+ ...input.stack !== undefined && { stack: input.stack }
103
+ };
104
+ }
105
+ if (Array.isArray(input)) {
106
+ if (ancestors.has(input))
107
+ return "[circular]";
108
+ ancestors.add(input);
109
+ const result = input.map((item) => walk(item, depth + 1));
110
+ ancestors.delete(input);
111
+ return result;
112
+ }
113
+ if (isRecord(input)) {
114
+ if (ancestors.has(input))
115
+ return "[circular]";
116
+ ancestors.add(input);
117
+ const out = {};
118
+ for (const key of Object.keys(input)) {
119
+ if (isUnsafeKey(key))
120
+ continue;
121
+ if (isSensitive(key)) {
122
+ out[key] = MASK;
123
+ continue;
124
+ }
125
+ try {
126
+ out[key] = walk(Reflect.get(input, key), depth + 1);
127
+ } catch {
128
+ out[key] = "[unreadable]";
129
+ }
130
+ }
131
+ ancestors.delete(input);
132
+ return out;
133
+ }
134
+ return String(input);
135
+ };
136
+ return walk(value, 0);
137
+ }
138
+ function truncatePreview(value, maxBytes = DEFAULT_MAX_BYTES) {
139
+ const json = JSON.stringify(value);
140
+ const bytes = new TextEncoder().encode(json);
141
+ if (bytes.byteLength <= maxBytes)
142
+ return value;
143
+ let end = Math.max(0, maxBytes);
144
+ while (end > 0 && ((bytes[end] ?? 0) & 192) === 128)
145
+ end -= 1;
146
+ const preview = new TextDecoder().decode(bytes.subarray(0, end));
147
+ return {
148
+ _truncated: true,
149
+ _originalBytes: bytes.byteLength,
150
+ preview: `${preview}…`
151
+ };
152
+ }
153
+ function sanitizePayload(value, options = {}) {
154
+ if (value === undefined || value === null)
155
+ return null;
156
+ try {
157
+ return truncatePreview(redact(value, options), options.maxBytes ?? DEFAULT_MAX_BYTES);
158
+ } catch {
159
+ return "[unserializable]";
160
+ }
161
+ }
162
+ function measureSize(value) {
163
+ if (value === undefined || value === null) {
164
+ return { resultSize: null, responseBytes: 0 };
165
+ }
166
+ let responseBytes = 0;
167
+ try {
168
+ responseBytes = new TextEncoder().encode(JSON.stringify(value)).byteLength;
169
+ } catch {
170
+ return { resultSize: null, responseBytes: 0, unserializable: true };
171
+ }
172
+ if (Array.isArray(value)) {
173
+ return { resultSize: value.length, responseBytes };
174
+ }
175
+ if (isRecord(value) && Array.isArray(value.items) && "nextCursor" in value) {
176
+ return { resultSize: value.items.length, responseBytes };
177
+ }
178
+ return { resultSize: null, responseBytes };
179
+ }
180
+
181
+ export { redact, truncatePreview, sanitizePayload, measureSize };
@@ -59,10 +59,11 @@ var STITCH_ERROR_STATUS = {
59
59
  CONFLICT: 409,
60
60
  RATE_LIMITED: 429,
61
61
  VALIDATION_ERROR: 400,
62
+ REALTIME_CONTRACT_VIOLATION: 500,
62
63
  INTERNAL_SERVER_ERROR: 500
63
64
  };
64
65
  function isStitchErrorCode(code) {
65
- return code in STITCH_ERROR_STATUS;
66
+ return Object.hasOwn(STITCH_ERROR_STATUS, code);
66
67
  }
67
68
  function appError(code, message, details) {
68
69
  throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
@@ -113,6 +114,14 @@ function parseTrailingWildcard(path) {
113
114
  return wildcard;
114
115
  }
115
116
 
117
+ // src/internal/safe-json.ts
118
+ function isUnsafeKey(key) {
119
+ return key === "__proto__";
120
+ }
121
+ function safeJsonParse(text) {
122
+ return JSON.parse(text, (key, value) => isUnsafeKey(key) ? undefined : value);
123
+ }
124
+
116
125
  // src/contract/define.ts
117
126
  function mergeMeta(contractMeta, endpointMeta) {
118
127
  if (!contractMeta)
@@ -131,6 +140,12 @@ function typedEntries(value) {
131
140
  function isRecord(value) {
132
141
  return typeof value === "object" && value !== null && !Array.isArray(value);
133
142
  }
143
+ function callRuntimeHandler(handler, context) {
144
+ if (typeof handler !== "function") {
145
+ throw new TypeError("Runtime handler must be a function");
146
+ }
147
+ return Reflect.apply(handler, undefined, [context]);
148
+ }
134
149
  // src/contract/pagination.ts
135
150
  import { z as z3 } from "zod";
136
151
 
@@ -178,7 +193,7 @@ function errorCode(err) {
178
193
  return;
179
194
  }
180
195
  function recordedErrorMessage(code, envelopeMessage, thrown) {
181
- if (code === "INTERNAL_SERVER_ERROR" && thrown !== undefined) {
196
+ if ((code === "INTERNAL_SERVER_ERROR" || code === "REALTIME_CONTRACT_VIOLATION") && thrown !== undefined) {
182
197
  if (thrown instanceof Error)
183
198
  return thrown.message;
184
199
  if (typeof thrown === "string")
@@ -187,8 +202,12 @@ function recordedErrorMessage(code, envelopeMessage, thrown) {
187
202
  return envelopeMessage;
188
203
  }
189
204
  function normalizeError(err) {
190
- if (AppError.is(err))
205
+ if (AppError.is(err)) {
206
+ if (err.code === "REALTIME_CONTRACT_VIOLATION") {
207
+ return new AppError("REALTIME_CONTRACT_VIOLATION", "Realtime contract violation", 500);
208
+ }
191
209
  return err;
210
+ }
192
211
  if (err instanceof z4.ZodError) {
193
212
  return new AppError("VALIDATION_ERROR", formatZodError(err), 400, {
194
213
  issues: zodIssues(err).slice(0, MAX_DETAIL_ISSUES)
@@ -249,14 +268,6 @@ function validateDeclaredOutput(schema, data, onStripped) {
249
268
  return validateHandlerOutput(schema, data, onStripped);
250
269
  }
251
270
 
252
- // src/internal/safe-json.ts
253
- function isUnsafeKey(key) {
254
- return key === "__proto__";
255
- }
256
- function safeJsonParse(text) {
257
- return JSON.parse(text, (key, value) => isUnsafeKey(key) ? undefined : value);
258
- }
259
-
260
271
  // src/server/request.ts
261
272
  function generateTraceId() {
262
273
  return `${Date.now().toString(36)}-${crypto.randomUUID().slice(0, 8)}`;
@@ -310,7 +321,7 @@ function parseQueryParams(url) {
310
321
  }
311
322
 
312
323
  // src/observability/trace.ts
313
- var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-[0-9a-f]{2}$/i;
324
+ var TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(.*)$/i;
314
325
  function randomHex(bytes) {
315
326
  const arr = new Uint8Array(bytes);
316
327
  crypto.getRandomValues(arr);
@@ -326,16 +337,24 @@ function parseTraceparent(header) {
326
337
  if (!header)
327
338
  return null;
328
339
  const match = TRACEPARENT_RE.exec(header.trim());
329
- if (!match?.[1] || !match[2])
340
+ if (!match?.[1] || !match[2] || !match[3] || !match[4] || match[5] === undefined)
330
341
  return null;
331
- const traceId = match[1].toLowerCase();
332
- const parentSpanId = match[2].toLowerCase();
342
+ const version = match[1].toLowerCase();
343
+ if (version === "ff")
344
+ return null;
345
+ const suffix = match[5];
346
+ if (version === "00" ? suffix !== "" : suffix !== "" && !/^(?:-[0-9a-f]{2,})+$/i.test(suffix)) {
347
+ return null;
348
+ }
349
+ const traceId = match[2].toLowerCase();
350
+ const parentSpanId = match[3].toLowerCase();
351
+ const traceFlags = match[4].toLowerCase();
333
352
  if (/^0+$/.test(traceId) || /^0+$/.test(parentSpanId))
334
353
  return null;
335
- return { traceId, spanId: randomHex(8), parentSpanId };
354
+ return { traceId, spanId: randomHex(8), parentSpanId, traceFlags };
336
355
  }
337
356
  function formatTraceparent(ctx) {
338
- return `00-${ctx.traceId}-${ctx.spanId}-01`;
357
+ return `00-${ctx.traceId}-${ctx.spanId}-${ctx.traceFlags ?? "01"}`;
339
358
  }
340
359
  function resolveTraceContext(req) {
341
360
  return parseTraceparent(req.headers.get("traceparent")) ?? createTraceContext();
@@ -346,7 +365,8 @@ function childSpan(parent) {
346
365
  spanId: randomHex(8),
347
366
  parentSpanId: parent.spanId,
348
367
  ...parent.tracestate !== undefined && { tracestate: parent.tracestate },
349
- ...parent.baggage !== undefined && { baggage: parent.baggage }
368
+ ...parent.baggage !== undefined && { baggage: parent.baggage },
369
+ ...parent.traceFlags !== undefined && { traceFlags: parent.traceFlags }
350
370
  };
351
371
  }
352
372
  var encoder = new TextEncoder;
@@ -434,4 +454,4 @@ function wrapInRequestContext(handler, options = {}) {
434
454
  };
435
455
  }
436
456
 
437
- export { __require, parseTrailingWildcard, mergeMeta, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, typedEntries, isRecord, bytesToBase64Url, base64UrlToBytes, formatZodError, zodIssues, errorCode, recordedErrorMessage, normalizeError, validateDeclaredOutput, isUnsafeKey, safeJsonParse, generateTraceId, resolveTraceId, resolveSocketIp, extractIp, getClientInfo, parseQueryParams, createTraceContext, parseTraceparent, formatTraceparent, resolveTraceContext, childSpan, resolvePropagationContext, runWithRequestContext, getRequestContext, getTraceId, getUserId, setRequestUser, setRequestEndpoint, setRequestDimensions, setRequestError, wrapInRequestContext };
457
+ export { __require, parseTrailingWildcard, isUnsafeKey, safeJsonParse, mergeMeta, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, typedEntries, isRecord, callRuntimeHandler, bytesToBase64Url, base64UrlToBytes, formatZodError, zodIssues, errorCode, recordedErrorMessage, normalizeError, validateDeclaredOutput, generateTraceId, resolveTraceId, resolveSocketIp, extractIp, getClientInfo, parseQueryParams, createTraceContext, parseTraceparent, formatTraceparent, resolveTraceContext, childSpan, resolvePropagationContext, runWithRequestContext, getRequestContext, getTraceId, getUserId, setRequestUser, setRequestEndpoint, setRequestDimensions, setRequestError, wrapInRequestContext };