stitchkit 0.59.4 → 0.60.1

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 (110) hide show
  1. package/README.md +7 -3
  2. package/dist/agent-runtime/admission-lanes.d.ts +35 -0
  3. package/dist/agent-runtime/admission-lanes.d.ts.map +1 -0
  4. package/dist/agent-runtime/coordinator.d.ts +46 -2
  5. package/dist/agent-runtime/coordinator.d.ts.map +1 -1
  6. package/dist/agent-runtime/events.d.ts +7 -0
  7. package/dist/agent-runtime/events.d.ts.map +1 -1
  8. package/dist/agent-runtime/history.d.ts +7 -0
  9. package/dist/agent-runtime/history.d.ts.map +1 -1
  10. package/dist/agent-runtime/models.d.ts +2 -3
  11. package/dist/agent-runtime/models.d.ts.map +1 -1
  12. package/dist/agent-runtime/observability.d.ts.map +1 -1
  13. package/dist/agent-runtime/run-execution.d.ts +31 -0
  14. package/dist/agent-runtime/run-execution.d.ts.map +1 -0
  15. package/dist/agent-runtime/runtime-internals.d.ts +25 -0
  16. package/dist/agent-runtime/runtime-internals.d.ts.map +1 -0
  17. package/dist/agent-runtime/runtime-result.d.ts +11 -0
  18. package/dist/agent-runtime/runtime-result.d.ts.map +1 -0
  19. package/dist/agent-runtime/runtime.d.ts +16 -15
  20. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  21. package/dist/agent-runtime/schemas.d.ts.map +1 -1
  22. package/dist/agent-runtime/store-driver.d.ts.map +1 -1
  23. package/dist/agent-runtime/store.d.ts +9 -2
  24. package/dist/agent-runtime/store.d.ts.map +1 -1
  25. package/dist/agent-runtime/terminal-commit.d.ts.map +1 -1
  26. package/dist/agent-runtime/terminal-status.d.ts +13 -0
  27. package/dist/agent-runtime/terminal-status.d.ts.map +1 -0
  28. package/dist/agent-runtime.d.ts +5 -3
  29. package/dist/agent-runtime.d.ts.map +1 -1
  30. package/dist/agent-runtime.js +303 -163
  31. package/dist/application/activity.d.ts +7 -2
  32. package/dist/application/activity.d.ts.map +1 -1
  33. package/dist/application/grammy.d.ts +14 -2
  34. package/dist/application/grammy.d.ts.map +1 -1
  35. package/dist/application/health.d.ts +9 -2
  36. package/dist/application/health.d.ts.map +1 -1
  37. package/dist/application/kernel.d.ts +61 -5
  38. package/dist/application/kernel.d.ts.map +1 -1
  39. package/dist/application/schemas.d.ts +42 -0
  40. package/dist/application/schemas.d.ts.map +1 -1
  41. package/dist/application-grammy.js +5 -3
  42. package/dist/application-opentelemetry.js +2 -2
  43. package/dist/application.d.ts +3 -3
  44. package/dist/application.d.ts.map +1 -1
  45. package/dist/application.js +17 -8
  46. package/dist/cli.js +7 -6
  47. package/dist/contract/errors.d.ts +7 -0
  48. package/dist/contract/errors.d.ts.map +1 -1
  49. package/dist/contract/index.js +1 -1
  50. package/dist/declaration.d.ts +345 -0
  51. package/dist/declaration.d.ts.map +1 -0
  52. package/dist/declaration.js +183 -0
  53. package/dist/{index-3nwng7hs.js → index-1pgeyyee.js} +4 -4
  54. package/dist/{index-s8w2y7kr.js → index-2cgbdckv.js} +26 -18
  55. package/dist/{index-gnvzyw0k.js → index-6taryy00.js} +2 -2
  56. package/dist/{index-5c8n2123.js → index-82e74yfx.js} +69 -33
  57. package/dist/{index-mgf6cdkm.js → index-8eywc9zv.js} +35 -1
  58. package/dist/{index-0nc0cddp.js → index-a59da114.js} +17 -28
  59. package/dist/{index-f6pymtqe.js → index-mfw1pec7.js} +7 -5
  60. package/dist/{index-y2rb7dwx.js → index-pzyt11ch.js} +5 -1
  61. package/dist/{index-mr617n62.js → index-svqhcrrj.js} +1 -1
  62. package/dist/{index-28cqssm3.js → index-t8xrqc9g.js} +7 -0
  63. package/dist/{index-7c0gkyvj.js → index-tvwcrx2d.js} +5 -3
  64. package/dist/{index-1tkyng3g.js → index-vkk06pv1.js} +1 -9
  65. package/dist/{index-ps5pxp3h.js → index-wd8g8z6e.js} +2 -79
  66. package/dist/{index-sa2mbwa7.js → index-wrhf06ak.js} +7 -5
  67. package/dist/{index-2nzpcfbp.js → index-x8v8b7rc.js} +2 -2
  68. package/dist/index-xxye8j3k.js +85 -0
  69. package/dist/{index-41wm56v0.js → index-y91zd0ch.js} +1 -1
  70. package/dist/index.js +1 -1
  71. package/dist/internal/observability-sink.d.ts.map +1 -1
  72. package/dist/internal/route-pattern.d.ts +9 -0
  73. package/dist/internal/route-pattern.d.ts.map +1 -1
  74. package/dist/node.d.ts +1 -1
  75. package/dist/node.d.ts.map +1 -1
  76. package/dist/node.js +8 -7
  77. package/dist/observability/index.js +6 -5
  78. package/dist/observability/sanitize.d.ts +3 -1
  79. package/dist/observability/sanitize.d.ts.map +1 -1
  80. package/dist/remote.js +6 -4
  81. package/dist/server/error-hook.d.ts +10 -3
  82. package/dist/server/error-hook.d.ts.map +1 -1
  83. package/dist/server/index.d.ts +1 -1
  84. package/dist/server/index.d.ts.map +1 -1
  85. package/dist/server/index.js +16 -18
  86. package/dist/server/middleware/cors.d.ts +5 -2
  87. package/dist/server/middleware/cors.d.ts.map +1 -1
  88. package/dist/server/openapi.d.ts.map +1 -1
  89. package/dist/server/router.d.ts.map +1 -1
  90. package/dist/server/socket-io-config.d.ts +68 -3
  91. package/dist/server/socket-io-config.d.ts.map +1 -1
  92. package/dist/server/socket-io-node.d.ts +1 -1
  93. package/dist/server/socket-io-node.d.ts.map +1 -1
  94. package/dist/server/socket-io.d.ts +1 -1
  95. package/dist/server/socket-io.d.ts.map +1 -1
  96. package/dist/testing/surface-manifest.d.ts.map +1 -1
  97. package/dist/testing.js +9 -10
  98. package/dist/tools/flatten-join.d.ts +2 -0
  99. package/dist/tools/flatten-join.d.ts.map +1 -1
  100. package/dist/tools/flatten.d.ts.map +1 -1
  101. package/dist/tools/mcp-prepare.d.ts +0 -2
  102. package/dist/tools/mcp-prepare.d.ts.map +1 -1
  103. package/dist/tools/runtime-tool.d.ts +0 -3
  104. package/dist/tools/runtime-tool.d.ts.map +1 -1
  105. package/dist/tools/schema.d.ts +0 -4
  106. package/dist/tools/schema.d.ts.map +1 -1
  107. package/dist/tools.js +13 -11
  108. package/llms-full.txt +926 -68
  109. package/llms.txt +1 -0
  110. package/package.json +10 -6
@@ -7,7 +7,7 @@ import {
7
7
  defaultSignalSource,
8
8
  guardSignalCallback,
9
9
  reportSignalError
10
- } from "./index-41wm56v0.js";
10
+ } from "./index-y91zd0ch.js";
11
11
  import {
12
12
  ShutdownOptionsSchema
13
13
  } from "./index-dk6e56g0.js";
@@ -26,21 +26,24 @@ import {
26
26
  setRequestError,
27
27
  validateDeclaredOutput,
28
28
  zodIssues
29
- } from "./index-7c0gkyvj.js";
29
+ } from "./index-tvwcrx2d.js";
30
30
  import {
31
- AppError,
32
- badRequest,
33
31
  isUnsafeKey,
34
32
  safeJsonParse
35
- } from "./index-ps5pxp3h.js";
33
+ } from "./index-wd8g8z6e.js";
36
34
  import {
35
+ joinRoutePath,
37
36
  parseTrailingWildcard,
38
37
  resolveTraceContext
39
- } from "./index-y2rb7dwx.js";
38
+ } from "./index-pzyt11ch.js";
40
39
  import {
41
40
  isRecord,
42
41
  transportResult
43
42
  } from "./index-smpbdg6k.js";
43
+ import {
44
+ AppError,
45
+ badRequest
46
+ } from "./index-xxye8j3k.js";
44
47
 
45
48
  // src/server/multipart.ts
46
49
  var DEFAULT_MAX_REQUEST_BYTES = 25 * 1024 * 1024;
@@ -827,10 +830,6 @@ function applyResponseMetadata(target, metadata, endpointIdentity) {
827
830
  }
828
831
 
829
832
  // src/server/router.ts
830
- function joinPath(...parts) {
831
- const joined = parts.filter(Boolean).map((part) => part.replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
832
- return `/${joined}`;
833
- }
834
833
  function routeSegments(path) {
835
834
  return path.split("/").filter(Boolean);
836
835
  }
@@ -914,8 +913,8 @@ function buildRouteMap(groups) {
914
913
  for (const [, method] of Object.entries(service.methods)) {
915
914
  if (method.expose && !method.expose.includes("HTTP"))
916
915
  continue;
917
- const servicePath = joinPath("/", service.prefix, method.path === "/" ? "" : method.path);
918
- const fullPath = prefix ? joinPath(prefix, servicePath) : servicePath;
916
+ const servicePath = joinRoutePath("/", service.prefix, method.path === "/" ? "" : method.path);
917
+ const fullPath = prefix ? joinRoutePath(prefix, servicePath) : servicePath;
919
918
  const segments = routeSegments(fullPath);
920
919
  const entries = map.get(method.method) ?? [];
921
920
  entries.push({ method, pattern: fullPath, segments, groupHooks: hooks });
@@ -1853,16 +1852,19 @@ function isModuleNotFound(err) {
1853
1852
  const message = "message" in err && typeof err.message === "string" ? err.message : "";
1854
1853
  return code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND" || message.includes("Cannot find module") || message.includes("Cannot find package");
1855
1854
  }
1856
- async function importPeer(load, pkg) {
1855
+ async function importPeer(load, pkg, injected) {
1857
1856
  try {
1858
1857
  return await load();
1859
1858
  } catch (err) {
1860
1859
  if (isModuleNotFound(err)) {
1861
- throw new Error(`[stitchkit] createSocketIOServer needs the optional peer "${pkg}" — install it: bun add ${pkg}`, { cause: err });
1860
+ throw new Error(injected ? `[stitchkit] createSocketIOServer could not load the optional peer "${pkg}" through the loader passed in \`peers\` — the artifact does not contain it. Check that the loader is a literal \`import('${pkg}')\` your bundler can follow, and that "${pkg}" is a dependency of the package being bundled.` : `[stitchkit] createSocketIOServer needs the optional peer "${pkg}" — install it: bun add ${pkg}. Shipping one self-contained artifact instead? Pass \`peers: { … }\` so your bundler puts it inside.`, { cause: err });
1862
1861
  }
1863
1862
  throw err;
1864
1863
  }
1865
1864
  }
1865
+ function isBunEngineModule(value) {
1866
+ return typeof value === "object" && value !== null && typeof Reflect.get(value, "Server") === "function";
1867
+ }
1866
1868
  function handshakeRejection(message) {
1867
1869
  const error = new Error(message);
1868
1870
  error.data = { code: "handshake_rejected" };
@@ -1906,11 +1908,11 @@ async function createSocketIOServer(config) {
1906
1908
  const transports = config.transports ?? (onBun ? ["websocket", "polling"] : ["websocket"]);
1907
1909
  const pingTimeout = config.pingTimeout ?? 20000;
1908
1910
  const pingInterval = config.pingInterval ?? 1e4;
1909
- const cors = {
1911
+ const cors = config.cors ? {
1910
1912
  origin: config.cors.origin,
1911
1913
  credentials: config.cors.credentials ?? true,
1912
1914
  methods: ["GET", "POST"]
1913
- };
1915
+ } : undefined;
1914
1916
  let accepting = true;
1915
1917
  let attached = false;
1916
1918
  let closePromise;
@@ -1939,7 +1941,8 @@ async function createSocketIOServer(config) {
1939
1941
  });
1940
1942
  checkRequest(webRequest).then(() => done(null, true), (error) => done(error instanceof Error ? error.message : "Request rejected", false));
1941
1943
  };
1942
- const { Server } = await importPeer(() => import(SOCKET_IO_SERVER).then((module) => module), SOCKET_IO_SERVER);
1944
+ const injectedServer = config.peers?.server;
1945
+ const { Server } = await importPeer(injectedServer ?? (() => import(SOCKET_IO_SERVER).then((module) => module)), SOCKET_IO_SERVER, injectedServer !== undefined);
1943
1946
  const io = new Server({
1944
1947
  ...config.serverOptions,
1945
1948
  path,
@@ -1966,7 +1969,12 @@ async function createSocketIOServer(config) {
1966
1969
  }
1967
1970
  };
1968
1971
  if (onBun) {
1969
- const { Server: Engine } = await importPeer(() => import(SOCKET_IO_BUN_ENGINE).then((module) => module), SOCKET_IO_BUN_ENGINE);
1972
+ const injectedEngine = config.peers?.bunEngine;
1973
+ const engineModule = await importPeer(injectedEngine ?? (() => import(SOCKET_IO_BUN_ENGINE).then((module) => module)), SOCKET_IO_BUN_ENGINE, injectedEngine !== undefined);
1974
+ if (!isBunEngineModule(engineModule)) {
1975
+ throw new Error(`[stitchkit] the loader passed in \`peers.bunEngine\` did not return the "${SOCKET_IO_BUN_ENGINE}" module — it must resolve to the module itself, as \`() => import('${SOCKET_IO_BUN_ENGINE}')\`.`);
1976
+ }
1977
+ const { Server: Engine } = engineModule;
1970
1978
  const engineOpts = {
1971
1979
  path,
1972
1980
  cors,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isUnsafeKey
3
- } from "./index-ps5pxp3h.js";
3
+ } from "./index-wd8g8z6e.js";
4
4
  import {
5
5
  isRecord
6
6
  } from "./index-smpbdg6k.js";
@@ -83,7 +83,7 @@ function redact(value, options = {}) {
83
83
  ancestors.add(input);
84
84
  const result = [...input.entries()].map(([key, value2]) => [
85
85
  walk(key, depth + 1),
86
- walk(value2, depth + 1)
86
+ typeof key === "string" && isSensitive(key) ? MASK : walk(value2, depth + 1)
87
87
  ]);
88
88
  ancestors.delete(input);
89
89
  return { _type: "map", entries: result };
@@ -2,10 +2,13 @@ import {
2
2
  ApplicationIdSchema,
3
3
  ApplicationShutdownResultSchema,
4
4
  ApplicationSnapshotSchema
5
- } from "./index-mgf6cdkm.js";
5
+ } from "./index-8eywc9zv.js";
6
6
  import {
7
7
  ShutdownOptionsSchema
8
8
  } from "./index-dk6e56g0.js";
9
+ import {
10
+ AppError
11
+ } from "./index-xxye8j3k.js";
9
12
 
10
13
  // src/application/graph.ts
11
14
  function resolveResourceGraph(resources) {
@@ -61,10 +64,21 @@ class ResourceCompletionBeforeReadyError extends Error {
61
64
  }
62
65
  }
63
66
 
64
- class ApplicationAdmissionError extends Error {
65
- code = "APPLICATION_NOT_ACCEPTING";
67
+ class ApplicationStartupInterruptedError extends Error {
66
68
  constructor() {
67
- super("Application is not accepting new operations");
69
+ super("[stitchkit] application startup interrupted by shutdown");
70
+ this.name = "ApplicationStartupInterruptedError";
71
+ }
72
+ }
73
+ var ApplicationShutdownOptionsSchema = ShutdownOptionsSchema.pick({
74
+ gracePeriodMs: true,
75
+ forceTimeoutMs: true,
76
+ signal: true
77
+ });
78
+
79
+ class ApplicationAdmissionError extends AppError {
80
+ constructor() {
81
+ super("APPLICATION_NOT_ACCEPTING", "Application is not accepting new operations", 503);
68
82
  this.name = "ApplicationAdmissionError";
69
83
  }
70
84
  }
@@ -87,6 +101,15 @@ function createApplication(config) {
87
101
  const id = ApplicationIdSchema.parse(config.id);
88
102
  const ordered = resolveResourceGraph(config.resources ?? []);
89
103
  const reverse = [...ordered].reverse();
104
+ const reportFailure = (resourceId, phase, error) => {
105
+ if (!config.onResourceFailure)
106
+ return;
107
+ try {
108
+ Promise.resolve(config.onResourceFailure({ resourceId, phase, error })).catch(() => {
109
+ return;
110
+ });
111
+ } catch {}
112
+ };
90
113
  const records = new Map;
91
114
  for (const entry of ordered) {
92
115
  records.set(entry.id, {
@@ -187,8 +210,10 @@ function createApplication(config) {
187
210
  const markLateCompletion = (record, failure) => {
188
211
  if (shutdownRequested || record.state === "stopping" || record.state === "stopped")
189
212
  return;
190
- if (failure)
213
+ if (failure) {
191
214
  record.failures.push("completion");
215
+ reportFailure(record.entry.id, "completion", failure.error);
216
+ }
192
217
  record.state = "failed";
193
218
  record.health = "unhealthy";
194
219
  accepting = activationComplete && isReady();
@@ -209,6 +234,7 @@ function createApplication(config) {
209
234
  } catch (error) {
210
235
  record.failures.push("close");
211
236
  record.state = "failed";
237
+ reportFailure(entry.id, "close", error);
212
238
  errors.push(error);
213
239
  }
214
240
  publish();
@@ -222,7 +248,7 @@ function createApplication(config) {
222
248
  try {
223
249
  for (const entry of ordered) {
224
250
  if (shutdownRequested || startupAbort.signal.aborted) {
225
- throw new Error("[stitchkit] application startup interrupted by shutdown");
251
+ throw new ApplicationStartupInterruptedError;
226
252
  }
227
253
  const record = records.get(entry.id);
228
254
  if (!record)
@@ -244,7 +270,7 @@ function createApplication(config) {
244
270
  try {
245
271
  const started = await entry.resource.start(contextFor(record, { signal: startupAbort.signal }));
246
272
  if (shutdownRequested || startupAbort.signal.aborted) {
247
- throw new Error("[stitchkit] application startup interrupted by shutdown");
273
+ throw new ApplicationStartupInterruptedError;
248
274
  }
249
275
  if (isStartResult(started)) {
250
276
  record.runtime = started;
@@ -254,12 +280,12 @@ function createApplication(config) {
254
280
  const completion = started.completion?.then(() => {
255
281
  completionSettled = true;
256
282
  if (resourceReady)
257
- markLateCompletion(record, false);
283
+ markLateCompletion(record);
258
284
  }, (error) => {
259
285
  completionSettled = true;
260
286
  completionFailure = error;
261
287
  if (resourceReady)
262
- markLateCompletion(record, true);
288
+ markLateCompletion(record, { error });
263
289
  });
264
290
  if (started.ready && completion) {
265
291
  const readiness = started.ready.then(() => "ready");
@@ -278,19 +304,21 @@ function createApplication(config) {
278
304
  } else if (completion) {}
279
305
  }
280
306
  if (shutdownRequested || startupAbort.signal.aborted) {
281
- throw new Error("[stitchkit] application startup interrupted by shutdown");
307
+ throw new ApplicationStartupInterruptedError;
282
308
  }
283
309
  record.state = "ready";
284
310
  record.health = "healthy";
285
311
  publish();
286
312
  } catch (error) {
287
- if (shutdownRequested || startupAbort.signal.aborted)
288
- throw error;
289
- record.failures.push(error instanceof ResourceCompletionBeforeReadyError ? "completion" : record.runtime?.ready ? "ready" : "start");
290
- record.state = "failed";
291
- record.health = "unhealthy";
292
- publish();
293
- if (entry.required)
313
+ const interrupted = shutdownRequested || startupAbort.signal.aborted;
314
+ if (!(error instanceof ApplicationStartupInterruptedError)) {
315
+ record.failures.push(error instanceof ResourceCompletionBeforeReadyError ? "completion" : record.runtime?.ready ? "ready" : "start");
316
+ record.state = "failed";
317
+ record.health = "unhealthy";
318
+ reportFailure(entry.id, record.failures[record.failures.length - 1] ?? "start", error);
319
+ publish();
320
+ }
321
+ if (interrupted || entry.required)
294
322
  throw error;
295
323
  }
296
324
  }
@@ -298,7 +326,7 @@ function createApplication(config) {
298
326
  publish();
299
327
  for (const entry of ordered) {
300
328
  if (shutdownRequested || startupAbort.signal.aborted) {
301
- throw new Error("[stitchkit] application startup interrupted by shutdown");
329
+ throw new ApplicationStartupInterruptedError;
302
330
  }
303
331
  const record = records.get(entry.id);
304
332
  if (record?.state !== "ready")
@@ -320,25 +348,27 @@ function createApplication(config) {
320
348
  try {
321
349
  await entry.resource.activate?.(contextFor(record));
322
350
  if (shutdownRequested || startupAbort.signal.aborted) {
323
- throw new Error("[stitchkit] application startup interrupted by shutdown");
351
+ throw new ApplicationStartupInterruptedError;
324
352
  }
325
353
  record.activated = true;
326
354
  if (entry.required && (record.state !== "ready" || record.health !== "healthy")) {
327
355
  throw new Error(`[stitchkit] required resource "${entry.id}" lost readiness during activation`);
328
356
  }
329
357
  } catch (error) {
330
- if (shutdownRequested || startupAbort.signal.aborted)
331
- throw error;
332
- record.failures.push("start");
333
- record.state = "failed";
334
- record.health = "unhealthy";
335
- publish();
336
- if (entry.required)
358
+ const interrupted = shutdownRequested || startupAbort.signal.aborted;
359
+ if (!(error instanceof ApplicationStartupInterruptedError)) {
360
+ record.failures.push("start");
361
+ record.state = "failed";
362
+ record.health = "unhealthy";
363
+ reportFailure(entry.id, "start", error);
364
+ publish();
365
+ }
366
+ if (interrupted || entry.required)
337
367
  throw error;
338
368
  }
339
369
  }
340
370
  if (shutdownRequested) {
341
- throw new Error("[stitchkit] application startup interrupted by shutdown");
371
+ throw new ApplicationStartupInterruptedError;
342
372
  }
343
373
  if (!isReady()) {
344
374
  throw new Error("[stitchkit] a required resource lost readiness during startup");
@@ -417,7 +447,7 @@ function createApplication(config) {
417
447
  const shutdown = (options) => {
418
448
  if (shutdownPromise)
419
449
  return shutdownPromise;
420
- const parsed = ShutdownOptionsSchema.parse(options ?? {});
450
+ const parsed = ApplicationShutdownOptionsSchema.parse(options ?? {});
421
451
  const startedAt = performance.now();
422
452
  const graceDeadlineAt = startedAt + parsed.gracePeriodMs;
423
453
  const forceDeadlineAt = graceDeadlineAt + parsed.forceTimeoutMs;
@@ -464,8 +494,9 @@ function createApplication(config) {
464
494
  break;
465
495
  if (result.error !== undefined)
466
496
  throw result.error;
467
- } catch {
497
+ } catch (error) {
468
498
  record.failures.push("admission");
499
+ reportFailure(entry.id, "admission", error);
469
500
  gracefulFailed = true;
470
501
  lifetimeAbort.abort();
471
502
  }
@@ -491,8 +522,9 @@ function createApplication(config) {
491
522
  }
492
523
  if (drained.error !== undefined)
493
524
  throw drained.error;
494
- } catch {
525
+ } catch (error) {
495
526
  record.failures.push("drain");
527
+ reportFailure(entry.id, "drain", error);
496
528
  gracefulFailed = true;
497
529
  lifetimeAbort.abort();
498
530
  break;
@@ -518,8 +550,9 @@ function createApplication(config) {
518
550
  record.closed = true;
519
551
  record.state = "stopped";
520
552
  publish();
521
- } catch {
553
+ } catch (error) {
522
554
  record.failures.push("close");
555
+ reportFailure(entry.id, "close", error);
523
556
  record.state = "failed";
524
557
  gracefulFailed = true;
525
558
  lifetimeAbort.abort();
@@ -556,17 +589,20 @@ function createApplication(config) {
556
589
  })));
557
590
  } else if (entry.resource.close) {
558
591
  record.failures.push("force");
592
+ reportFailure(entry.id, "force", new Error(`[stitchkit] resource "${entry.id}" was already closing and did not settle before the force deadline`));
559
593
  return;
560
594
  }
561
595
  const forced = await untilDeadline(cleanup ?? Promise.resolve(), forceAbort.signal);
562
596
  if (!forced.settled || forced.error !== undefined) {
563
597
  record.failures.push("force");
598
+ reportFailure(entry.id, "force", forced.settled ? forced.error : new Error("[stitchkit] forced cleanup did not settle in time"));
564
599
  return;
565
600
  }
566
601
  record.closed = true;
567
602
  record.state = "stopped";
568
- } catch {
603
+ } catch (error) {
569
604
  record.failures.push("force");
605
+ reportFailure(entry.id, "force", error);
570
606
  }
571
607
  }));
572
608
  clearTimeout(forceTimer);
@@ -614,4 +650,4 @@ function createApplication(config) {
614
650
  };
615
651
  }
616
652
 
617
- export { ApplicationAdmissionError, createApplication };
653
+ export { ApplicationShutdownOptionsSchema, ApplicationAdmissionError, createApplication };
@@ -46,6 +46,40 @@ var ApplicationSnapshotSchema = z.object({
46
46
  admission: ApplicationAdmissionSnapshotSchema,
47
47
  resources: z.array(ManagedResourceSnapshotSchema).readonly()
48
48
  }).readonly();
49
+ var ApplicationStatusProjectionSchema = z.object({
50
+ id: ApplicationIdSchema,
51
+ lifecycle: ApplicationLifecycleSchema,
52
+ health: ApplicationHealthSchema,
53
+ ready: z.boolean(),
54
+ capturedAt: z.string().datetime({ offset: true }),
55
+ resources: z.object({
56
+ total: NonNegativeIntegerSchema,
57
+ ready: NonNegativeIntegerSchema,
58
+ degraded: NonNegativeIntegerSchema,
59
+ failed: NonNegativeIntegerSchema
60
+ }).readonly()
61
+ }).readonly();
62
+ function projectApplicationStatus(snapshot) {
63
+ let ready = 0;
64
+ let degraded = 0;
65
+ let failed = 0;
66
+ for (const resource of snapshot.resources) {
67
+ if (resource.ready)
68
+ ready += 1;
69
+ if (resource.health === "degraded")
70
+ degraded += 1;
71
+ if (resource.state === "failed")
72
+ failed += 1;
73
+ }
74
+ return {
75
+ id: snapshot.id,
76
+ lifecycle: snapshot.lifecycle,
77
+ health: snapshot.health,
78
+ ready: snapshot.ready,
79
+ capturedAt: snapshot.capturedAt,
80
+ resources: { total: snapshot.resources.length, ready, degraded, failed }
81
+ };
82
+ }
49
83
  var ApplicationResourceShutdownSchema = z.object({
50
84
  id: ApplicationIdSchema,
51
85
  state: z.enum(["not-started", "closed", "force-failed"]),
@@ -63,4 +97,4 @@ var ApplicationShutdownResultSchema = z.object({
63
97
  durationMs: z.number().nonnegative()
64
98
  }).readonly();
65
99
 
66
- export { ApplicationIdSchema, ApplicationLifecycleSchema, ApplicationHealthSchema, ManagedResourceStateSchema, ApplicationAdmissionSnapshotSchema, ManagedResourceSnapshotSchema, ApplicationSnapshotSchema, ApplicationResourceShutdownSchema, ApplicationShutdownResultSchema };
100
+ export { ApplicationIdSchema, ApplicationLifecycleSchema, ApplicationHealthSchema, ManagedResourceStateSchema, ApplicationAdmissionSnapshotSchema, ManagedResourceSnapshotSchema, ApplicationSnapshotSchema, ApplicationStatusProjectionSchema, projectApplicationStatus, ApplicationResourceShutdownSchema, ApplicationShutdownResultSchema };
@@ -138,41 +138,30 @@ function createBoundedSinkManager(config) {
138
138
  flush() {
139
139
  return awaitGeneration(sequence);
140
140
  },
141
- getStatus() {
142
- return ObservabilitySinkStatusSchema.parse({
143
- capacity: maxPending,
144
- received,
145
- accepted,
146
- filtered,
147
- completed,
148
- dropped,
149
- failed,
150
- preparationFailed,
151
- preparing: preparing.size,
152
- pending: writes.size,
153
- closed
154
- });
155
- },
141
+ getStatus,
156
142
  close() {
157
143
  if (closePromise)
158
144
  return closePromise;
159
145
  closed = true;
160
- closePromise = awaitGeneration(sequence).then(() => ObservabilitySinkStatusSchema.parse({
161
- capacity: maxPending,
162
- received,
163
- accepted,
164
- filtered,
165
- completed,
166
- dropped,
167
- failed,
168
- preparationFailed,
169
- preparing: preparing.size,
170
- pending: writes.size,
171
- closed
172
- }));
146
+ closePromise = awaitGeneration(sequence).then(getStatus);
173
147
  return closePromise;
174
148
  }
175
149
  };
150
+ function getStatus() {
151
+ return ObservabilitySinkStatusSchema.parse({
152
+ capacity: maxPending,
153
+ received,
154
+ accepted,
155
+ filtered,
156
+ completed,
157
+ dropped,
158
+ failed,
159
+ preparationFailed,
160
+ preparing: preparing.size,
161
+ pending: writes.size,
162
+ closed
163
+ });
164
+ }
176
165
  }
177
166
 
178
167
  export { ObservabilitySinkStatusSchema, ObservabilityStatusSchema, ObservabilityDrainReportSchema, aggregateObservabilityStatus, createBoundedSinkManager };
@@ -2,18 +2,20 @@ import {
2
2
  contextContributionDelta,
3
3
  mergeContextContribution,
4
4
  prepareContextContribution
5
- } from "./index-41wm56v0.js";
5
+ } from "./index-y91zd0ch.js";
6
6
  import {
7
7
  base64UrlToBytes,
8
8
  bytesToBase64Url,
9
- forbidden,
10
9
  isUnsafeKey,
11
- safeJsonParse,
12
- unauthorized
13
- } from "./index-ps5pxp3h.js";
10
+ safeJsonParse
11
+ } from "./index-wd8g8z6e.js";
14
12
  import {
15
13
  isRecord
16
14
  } from "./index-smpbdg6k.js";
15
+ import {
16
+ forbidden,
17
+ unauthorized
18
+ } from "./index-xxye8j3k.js";
17
19
 
18
20
  // src/server/middleware/cookies.ts
19
21
  function parseCookies(header) {
@@ -80,6 +80,10 @@ function resolvePropagationContext(metadata, fallback) {
80
80
 
81
81
  // src/internal/route-pattern.ts
82
82
  var PARAM_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
83
+ function joinRoutePath(...parts) {
84
+ const joined = parts.filter((part) => Boolean(part)).map((part) => part.replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
85
+ return `/${joined}`;
86
+ }
83
87
  function parseTrailingWildcard(path) {
84
88
  const segments = path.split("/").filter(Boolean);
85
89
  const paramNames = new Set;
@@ -120,4 +124,4 @@ function parseTrailingWildcard(path) {
120
124
  return wildcard;
121
125
  }
122
126
 
123
- export { parseTrailingWildcard, createTraceContext, parseTraceparent, formatTraceparent, resolveTraceContext, childSpan, resolvePropagationContext };
127
+ export { joinRoutePath, parseTrailingWildcard, createTraceContext, parseTraceparent, formatTraceparent, resolveTraceContext, childSpan, resolvePropagationContext };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./index-48ffdxgk.js";
4
4
  import {
5
5
  parseTrailingWildcard
6
- } from "./index-y2rb7dwx.js";
6
+ } from "./index-pzyt11ch.js";
7
7
  import {
8
8
  isRecord,
9
9
  mapObject,
@@ -284,6 +284,13 @@ var STITCH_ERROR_STATUS = {
284
284
  FILE_TOO_LARGE: 413,
285
285
  FILE_EXISTS: 409,
286
286
  REALTIME_CONTRACT_VIOLATION: 500,
287
+ APPLICATION_NOT_ACCEPTING: 503,
288
+ GRAMMY_WEBHOOK_NOT_ACCEPTING: 503,
289
+ WAIT_TIMEOUT: 408,
290
+ WAIT_FAILED: 409,
291
+ DOWNLOAD_NOT_FOUND: 404,
292
+ VIEW_HTTP_ERROR: 502,
293
+ OPERATION_NOT_SUCCEEDED: 409,
287
294
  INTERNAL_SERVER_ERROR: 500
288
295
  };
289
296
  function isStitchErrorCode(code) {
@@ -1,13 +1,15 @@
1
1
  import {
2
- AppError,
3
2
  isUnsafeKey
4
- } from "./index-ps5pxp3h.js";
3
+ } from "./index-wd8g8z6e.js";
5
4
  import {
6
5
  resolveTraceContext
7
- } from "./index-y2rb7dwx.js";
6
+ } from "./index-pzyt11ch.js";
8
7
  import {
9
8
  isRecord
10
9
  } from "./index-smpbdg6k.js";
10
+ import {
11
+ AppError
12
+ } from "./index-xxye8j3k.js";
11
13
 
12
14
  // src/internal/errors.ts
13
15
  import { z } from "zod";
@@ -338,14 +338,6 @@ function rebuild(value) {
338
338
  node[key] = rebuild(child);
339
339
  return flattenNode(node);
340
340
  }
341
- function stringValues2(schema) {
342
- if (typeof schema.const === "string")
343
- return [schema.const];
344
- if (!Array.isArray(schema.enum))
345
- return null;
346
- const values = schema.enum.filter((value) => typeof value === "string");
347
- return values.length === schema.enum.length ? values : null;
348
- }
349
341
  function objectVariants(node) {
350
342
  if (!Array.isArray(node.oneOf) || node.oneOf.length < 2)
351
343
  return null;
@@ -372,7 +364,7 @@ function findDiscriminator(variants) {
372
364
  }
373
365
  const properties = variant.properties;
374
366
  const field = isRecord(properties) ? properties[key] : undefined;
375
- const branchValues = isRecord(field) ? stringValues2(field) : null;
367
+ const branchValues = isRecord(field) ? stringValues(field) : null;
376
368
  if (!branchValues || branchValues.length === 0) {
377
369
  valid = false;
378
370
  break;