stitchkit 0.68.10 → 0.68.11

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.
@@ -1,6 +1,6 @@
1
1
  import type { StitchLogger } from '../logger.js';
2
2
  import type { RealtimeAcknowledgedEvent, RealtimeAcknowledgement, RealtimeContract, RealtimeEventRegistry, RealtimeRejectedEventHook, RealtimeRequestArguments } from '../realtime/contract.js';
3
- import { type RealtimeRequestOptions } from '../realtime/request.js';
3
+ import { type RealtimeRequestOptions, type RealtimeRequestPhaseHook } from '../realtime/request.js';
4
4
  import { type ValidatedRealtimeSocket } from '../realtime/socket.js';
5
5
  /**
6
6
  * How this project loads the optional Socket.IO **client** peer.
@@ -207,9 +207,15 @@ export interface BindRealtimeClientOptions {
207
207
  export interface RealtimeClientOptions<TServerToClient extends RealtimeEventRegistry> extends BindRealtimeClientOptions, SocketIOClientConfig<{
208
208
  [TEvent in keyof TServerToClient]: (...args: unknown[]) => void;
209
209
  }> {
210
+ /**
211
+ * Observe bounded metadata-only phases of acknowledged requests. Engine.IO
212
+ * phases are local encoder/decoder boundaries, not remote send time or RTT.
213
+ * Observer failures are isolated from request lifecycle.
214
+ */
215
+ onRequestPhase?: RealtimeRequestPhaseHook;
210
216
  }
211
217
  /** Add contract validation and typed acknowledgements without owning the transport lifecycle. */
212
218
  export declare function bindRealtimeClient<const TServerToClient extends RealtimeEventRegistry, const TClientToServer extends RealtimeEventRegistry>(contract: RealtimeContract<TServerToClient, TClientToServer>, transport: RealtimeClientTransport, { onRejected, logger }?: BindRealtimeClientOptions): BoundRealtimeClient<TServerToClient, TClientToServer>;
213
- export declare function createRealtimeClient<const TServerToClient extends RealtimeEventRegistry, const TClientToServer extends RealtimeEventRegistry>(contract: RealtimeContract<TServerToClient, TClientToServer>, { onRejected, logger, ...config }: RealtimeClientOptions<TServerToClient>): RealtimeClient<TServerToClient, TClientToServer>;
219
+ export declare function createRealtimeClient<const TServerToClient extends RealtimeEventRegistry, const TClientToServer extends RealtimeEventRegistry>(contract: RealtimeContract<TServerToClient, TClientToServer>, { onRejected, logger, onRequestPhase, ...config }: RealtimeClientOptions<TServerToClient>): RealtimeClient<TServerToClient, TClientToServer>;
214
220
  export declare function createSocketIOClient<TServerEvents extends SocketEventMap, TClientEvents extends SocketEventMap>(config: SocketIOClientConfig<TServerEvents>): SocketIOClient<TServerEvents, TClientEvents>;
215
221
  //# sourceMappingURL=socket-io.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/browser/socket-io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/browser/socket-io.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,19 @@
1
1
  // src/realtime/request.ts
2
+ import { z } from "zod";
3
+ var RealtimeRequestPhaseSchema = z.enum([
4
+ "engine-handoff",
5
+ "engine-ack-received",
6
+ "settled",
7
+ "timeout",
8
+ "disconnected"
9
+ ]);
10
+ var RealtimeRequestPhaseEventSchema = z.object({
11
+ requestId: z.string().min(1),
12
+ event: z.string().min(1),
13
+ phase: RealtimeRequestPhaseSchema,
14
+ elapsedMs: z.number().finite().nonnegative()
15
+ }).strict();
16
+
2
17
  class RealtimeRequestTimeoutError extends Error {
3
18
  code = "REALTIME_REQUEST_TIMEOUT";
4
19
  event;
package/dist/index.js CHANGED
@@ -1099,6 +1099,21 @@ function isModuleNotFound(error) {
1099
1099
  }
1100
1100
 
1101
1101
  // src/realtime/request.ts
1102
+ import { z as z2 } from "zod";
1103
+ var RealtimeRequestPhaseSchema = z2.enum([
1104
+ "engine-handoff",
1105
+ "engine-ack-received",
1106
+ "settled",
1107
+ "timeout",
1108
+ "disconnected"
1109
+ ]);
1110
+ var RealtimeRequestPhaseEventSchema = z2.object({
1111
+ requestId: z2.string().min(1),
1112
+ event: z2.string().min(1),
1113
+ phase: RealtimeRequestPhaseSchema,
1114
+ elapsedMs: z2.number().finite().nonnegative()
1115
+ }).strict();
1116
+
1102
1117
  class RealtimeRequestTimeoutError extends Error {
1103
1118
  code = "REALTIME_REQUEST_TIMEOUT";
1104
1119
  event;
@@ -1186,9 +1201,9 @@ function parseIssues(value) {
1186
1201
  }
1187
1202
 
1188
1203
  // src/realtime/rejection.ts
1189
- import { z as z2 } from "zod";
1204
+ import { z as z3 } from "zod";
1190
1205
  function realtimeContractViolation(options) {
1191
- const issues = options.cause instanceof z2.ZodError ? zodIssues(options.cause) : undefined;
1206
+ const issues = options.cause instanceof z3.ZodError ? zodIssues(options.cause) : undefined;
1192
1207
  const reason = options.reason.replaceAll("-", " ");
1193
1208
  const error = new AppError("REALTIME_CONTRACT_VIOLATION", `Realtime event "${options.event}" (${options.direction}, ${options.phase}): ${reason}`, 500, {
1194
1209
  event: options.event,
@@ -1469,6 +1484,63 @@ function createRetainedTopics() {
1469
1484
  }
1470
1485
 
1471
1486
  // src/browser/socket-io.ts
1487
+ var realtimeRequestTraces = new WeakMap;
1488
+ function observeRealtimeRequestPhase(trace, phase) {
1489
+ const observation = {
1490
+ requestId: trace.requestId,
1491
+ event: trace.event,
1492
+ phase,
1493
+ elapsedMs: performance.now() - trace.startedAt
1494
+ };
1495
+ try {
1496
+ const result = trace.observe(observation);
1497
+ if (result)
1498
+ Promise.resolve(result).catch(() => {
1499
+ return;
1500
+ });
1501
+ } catch {}
1502
+ }
1503
+ function socketIoPacketIdentity(data, expected) {
1504
+ if (typeof data !== "string")
1505
+ return null;
1506
+ const type = data.charAt(0);
1507
+ const binary = type === (expected === "event" ? "5" : "6");
1508
+ if (type !== (expected === "event" ? "2" : "3") && !binary)
1509
+ return null;
1510
+ let offset = 1;
1511
+ if (binary) {
1512
+ const separator = data.indexOf("-", offset);
1513
+ if (separator < 0)
1514
+ return null;
1515
+ for (let index = offset;index < separator; index += 1) {
1516
+ const code = data.charCodeAt(index);
1517
+ if (code < 48 || code > 57)
1518
+ return null;
1519
+ }
1520
+ offset = separator + 1;
1521
+ }
1522
+ let namespace = "/";
1523
+ if (data.charAt(offset) === "/") {
1524
+ const separator = data.indexOf(",", offset);
1525
+ if (separator < 0)
1526
+ return null;
1527
+ namespace = data.slice(offset, separator);
1528
+ offset = separator + 1;
1529
+ }
1530
+ const start = offset;
1531
+ while (offset < data.length) {
1532
+ const code = data.charCodeAt(offset);
1533
+ if (code < 48 || code > 57)
1534
+ break;
1535
+ offset += 1;
1536
+ }
1537
+ if (offset === start)
1538
+ return null;
1539
+ return { namespace, id: data.slice(start, offset) };
1540
+ }
1541
+ function packetIdentityKey(identity) {
1542
+ return `${identity.namespace}:${identity.id}`;
1543
+ }
1472
1544
  var SOCKET_IO_CLIENT = "socket.io-client";
1473
1545
  var ioLoader = null;
1474
1546
  function loadIo() {
@@ -1564,8 +1636,20 @@ function bindRealtimeClient(contract, transport, { onRejected, logger } = {}) {
1564
1636
  if (!definition?.ack) {
1565
1637
  throw new Error(`Realtime request "${event}" has no acknowledgement schema`);
1566
1638
  }
1567
- const value = await transport.emitWithAck(event, parsedArgs, { timeoutMs });
1568
- const acknowledgement = parseRealtimeRequestAcknowledgement(definition.ack, event, "client-inbound", value, onRejected, logger);
1639
+ const pending = transport.emitWithAck(event, parsedArgs, { timeoutMs });
1640
+ const trace = realtimeRequestTraces.get(pending);
1641
+ if (trace)
1642
+ realtimeRequestTraces.delete(pending);
1643
+ const value = await pending;
1644
+ let acknowledgement;
1645
+ try {
1646
+ acknowledgement = parseRealtimeRequestAcknowledgement(definition.ack, event, "client-inbound", value, onRejected, logger);
1647
+ } finally {
1648
+ if (trace && !trace.closed) {
1649
+ trace.closed = true;
1650
+ observeRealtimeRequestPhase(trace, "settled");
1651
+ }
1652
+ }
1569
1653
  return acknowledgement;
1570
1654
  }
1571
1655
  return {
@@ -1577,8 +1661,8 @@ function bindRealtimeClient(contract, transport, { onRejected, logger } = {}) {
1577
1661
  onConnectionChange: (listener) => transport.onConnectionChange(listener)
1578
1662
  };
1579
1663
  }
1580
- function createRealtimeClient(contract, { onRejected, logger, ...config }) {
1581
- const transport = createSocketIOClient(config);
1664
+ function createRealtimeClient(contract, { onRejected, logger, onRequestPhase, ...config }) {
1665
+ const transport = createSocketIOClientInternal(config, onRequestPhase);
1582
1666
  const bound = bindRealtimeClient(contract, transport, { onRejected, logger });
1583
1667
  return {
1584
1668
  ...bound,
@@ -1590,12 +1674,17 @@ function createRealtimeClient(contract, { onRejected, logger, ...config }) {
1590
1674
  };
1591
1675
  }
1592
1676
  function createSocketIOClient(config) {
1677
+ return createSocketIOClientInternal(config);
1678
+ }
1679
+ function createSocketIOClientInternal(config, onRequestPhase) {
1593
1680
  let socket = null;
1594
1681
  const resolveIo = createIoResolver(config.peers?.client);
1595
1682
  let desiredConnected = false;
1596
1683
  let loadingPeer = false;
1597
1684
  let reconnectTimer = null;
1598
1685
  const pendingRequestDisconnects = new Set;
1686
+ const requestTracesByNativeKey = new Map;
1687
+ let startingRequestTrace = null;
1599
1688
  const serverDisconnectDelay = config.reconnectOnServerDisconnect ?? 1000;
1600
1689
  const connectionListeners = new Set;
1601
1690
  const subscriptions = new Set;
@@ -1629,6 +1718,37 @@ function createSocketIOClient(config) {
1629
1718
  reconnectionDelayMax: config.reconnectionDelayMax ?? 5000,
1630
1719
  timeout: config.timeout ?? 20000
1631
1720
  });
1721
+ if (onRequestPhase) {
1722
+ socket.io.on("open", () => {
1723
+ const engine = socket?.io.engine;
1724
+ if (!engine)
1725
+ return;
1726
+ engine.on("packetCreate", (packet) => {
1727
+ if (!startingRequestTrace || packet.type !== "message")
1728
+ return;
1729
+ const identity = socketIoPacketIdentity(packet.data, "event");
1730
+ if (!identity)
1731
+ return;
1732
+ const key = packetIdentityKey(identity);
1733
+ startingRequestTrace.nativeKey = key;
1734
+ requestTracesByNativeKey.set(key, startingRequestTrace);
1735
+ observeRealtimeRequestPhase(startingRequestTrace, "engine-handoff");
1736
+ });
1737
+ engine.on("packet", (packet) => {
1738
+ if (packet.type !== "message")
1739
+ return;
1740
+ const identity = socketIoPacketIdentity(packet.data, "ack");
1741
+ if (!identity)
1742
+ return;
1743
+ const key = packetIdentityKey(identity);
1744
+ const trace = requestTracesByNativeKey.get(key);
1745
+ if (!trace || trace.closed)
1746
+ return;
1747
+ observeRealtimeRequestPhase(trace, "engine-ack-received");
1748
+ requestTracesByNativeKey.delete(key);
1749
+ });
1750
+ });
1751
+ }
1632
1752
  socket.on("connect", () => notifyConnection(true));
1633
1753
  socket.on("disconnect", (reason) => {
1634
1754
  notifyConnection(false, reason);
@@ -1738,11 +1858,30 @@ function createSocketIOClient(config) {
1738
1858
  return true;
1739
1859
  },
1740
1860
  emitWithAck(event, args, options) {
1861
+ const trace = onRequestPhase ? {
1862
+ requestId: crypto.randomUUID(),
1863
+ event,
1864
+ startedAt: performance.now(),
1865
+ observe: onRequestPhase,
1866
+ closed: false
1867
+ } : undefined;
1868
+ const closeTrace = (phase) => {
1869
+ if (!trace || trace.closed)
1870
+ return;
1871
+ trace.closed = true;
1872
+ if (trace.nativeKey)
1873
+ requestTracesByNativeKey.delete(trace.nativeKey);
1874
+ observeRealtimeRequestPhase(trace, phase);
1875
+ };
1741
1876
  const active = socket;
1742
1877
  if (!active?.connected) {
1743
- return Promise.reject(new RealtimeRequestDisconnectedError(event));
1878
+ const pending2 = Promise.reject(new RealtimeRequestDisconnectedError(event));
1879
+ closeTrace("disconnected");
1880
+ if (trace)
1881
+ realtimeRequestTraces.set(pending2, trace);
1882
+ return pending2;
1744
1883
  }
1745
- return new Promise((resolve, reject) => {
1884
+ const pending = new Promise((resolve, reject) => {
1746
1885
  let settled = false;
1747
1886
  const finish = (result) => {
1748
1887
  if (settled)
@@ -1753,14 +1892,31 @@ function createSocketIOClient(config) {
1753
1892
  result();
1754
1893
  };
1755
1894
  const onDisconnect = () => {
1756
- finish(() => reject(new RealtimeRequestDisconnectedError(event)));
1895
+ finish(() => {
1896
+ closeTrace("disconnected");
1897
+ reject(new RealtimeRequestDisconnectedError(event));
1898
+ });
1757
1899
  };
1758
1900
  pendingRequestDisconnects.add(onDisconnect);
1759
1901
  active.on("disconnect", onDisconnect);
1760
- active.timeout(options.timeoutMs).emitWithAck(event, ...args).then((value) => finish(() => resolve(value)), () => {
1761
- finish(() => reject(active.connected ? new RealtimeRequestTimeoutError(event, options.timeoutMs) : new RealtimeRequestDisconnectedError(event)));
1902
+ let acknowledgement;
1903
+ startingRequestTrace = trace ?? null;
1904
+ try {
1905
+ acknowledgement = active.timeout(options.timeoutMs).emitWithAck(event, ...args);
1906
+ } finally {
1907
+ startingRequestTrace = null;
1908
+ }
1909
+ acknowledgement.then((value) => finish(() => resolve(value)), () => {
1910
+ finish(() => {
1911
+ const connected = active.connected;
1912
+ closeTrace(connected ? "timeout" : "disconnected");
1913
+ reject(connected ? new RealtimeRequestTimeoutError(event, options.timeoutMs) : new RealtimeRequestDisconnectedError(event));
1914
+ });
1762
1915
  });
1763
1916
  });
1917
+ if (trace)
1918
+ realtimeRequestTraces.set(pending, trace);
1919
+ return pending;
1764
1920
  },
1765
1921
  onConnectionChange(listener) {
1766
1922
  connectionListeners.add(listener);
@@ -1783,6 +1939,8 @@ export {
1783
1939
  REALTIME_REJECTION_KEY,
1784
1940
  RealtimeRequestDisconnectedError,
1785
1941
  RealtimeRequestInvalidAcknowledgementError,
1942
+ RealtimeRequestPhaseEventSchema,
1943
+ RealtimeRequestPhaseSchema,
1786
1944
  RealtimeRequestRejectedError,
1787
1945
  RealtimeRequestTimeoutError,
1788
1946
  STITCH_ERROR_STATUS,
package/dist/node.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  implementRegistry
17
17
  } from "./index-hxh98zbm.js";
18
18
  import"./index-f24xg2cw.js";
19
- import"./index-557by2db.js";
19
+ import"./index-7b188kmz.js";
20
20
  import {
21
21
  ShutdownOptionsSchema,
22
22
  ShutdownResultSchema,
@@ -1,5 +1,5 @@
1
1
  export { defineRealtimeContract, type InferRealtimeEventMap, type RealtimeAcknowledgedEvent, type RealtimeAcknowledgement, type RealtimeContract, type RealtimeEmitArguments, type RealtimeEventArguments, type RealtimeEventDefinition, type RealtimeEventHandler, type RealtimeEventRegistry, type RealtimeRejectDirection, type RealtimeRejectedEvent, type RealtimeRejectedEventHook, type RealtimeRequestArguments, } from './contract.js';
2
2
  export { asRealtimeRejection, REALTIME_REJECTION_KEY, type RealtimeRejectionEnvelope, type RealtimeRejectionIssue, type RealtimeRejectionReport, } from './rejected-frame.js';
3
- export { RealtimeRequestDisconnectedError, RealtimeRequestInvalidAcknowledgementError, type RealtimeRequestOptions, RealtimeRequestRejectedError, RealtimeRequestTimeoutError, } from './request.js';
3
+ export { RealtimeRequestDisconnectedError, RealtimeRequestInvalidAcknowledgementError, type RealtimeRequestOptions, type RealtimeRequestPhase, type RealtimeRequestPhaseEvent, RealtimeRequestPhaseEventSchema, type RealtimeRequestPhaseHook, RealtimeRequestPhaseSchema, RealtimeRequestRejectedError, RealtimeRequestTimeoutError, } from './request.js';
4
4
  export type { ValidatedRealtimeSocket } from './socket.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/realtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,gCAAgC,EAChC,0CAA0C,EAC1C,KAAK,sBAAsB,EAC3B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/realtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,gCAAgC,EAChC,0CAA0C,EAC1C,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,+BAA+B,EAC/B,KAAK,wBAAwB,EAC7B,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC"}
@@ -1,4 +1,29 @@
1
+ import { z } from 'zod';
1
2
  import type { RealtimeRejectionIssue } from './rejected-frame.js';
3
+ /** Closed lifecycle reported by an opt-in acknowledged-request observer. */
4
+ export declare const RealtimeRequestPhaseSchema: z.ZodEnum<{
5
+ disconnected: "disconnected";
6
+ "engine-ack-received": "engine-ack-received";
7
+ "engine-handoff": "engine-handoff";
8
+ settled: "settled";
9
+ timeout: "timeout";
10
+ }>;
11
+ /** Metadata-only observation: no arguments, acknowledgement or packet bytes. */
12
+ export declare const RealtimeRequestPhaseEventSchema: z.ZodObject<{
13
+ requestId: z.ZodString;
14
+ event: z.ZodString;
15
+ phase: z.ZodEnum<{
16
+ disconnected: "disconnected";
17
+ "engine-ack-received": "engine-ack-received";
18
+ "engine-handoff": "engine-handoff";
19
+ settled: "settled";
20
+ timeout: "timeout";
21
+ }>;
22
+ elapsedMs: z.ZodNumber;
23
+ }, z.core.$strict>;
24
+ export type RealtimeRequestPhase = z.infer<typeof RealtimeRequestPhaseSchema>;
25
+ export type RealtimeRequestPhaseEvent = z.infer<typeof RealtimeRequestPhaseEventSchema>;
26
+ export type RealtimeRequestPhaseHook = (event: RealtimeRequestPhaseEvent) => void | Promise<void>;
2
27
  export interface RealtimeRequestOptions {
3
28
  /** Maximum acknowledgement wait in milliseconds. Must be finite and > 0. */
4
29
  timeoutMs: number;
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/realtime/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,8BAA8B;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,YAAY,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAK3C;CACF;AAED,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,mCAAmC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,YAAY,KAAK,EAAE,MAAM,EAIxB;CACF;AAED,qBAAa,0CAA2C,SAAQ,KAAK;IACnE,QAAQ,CAAC,IAAI,8CAA8C;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,YAAY,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAIxC;CACF;AAED;;;;;;;;;GASG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,+BAA+B;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,sBAAsB,EAAE,GAAG,SAAS,CAAC;IAEtD,YACE,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,sBAAsB,EAAE,EAOlC;CACF"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/realtime/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,4EAA4E;AAC5E,eAAO,MAAM,0BAA0B;;;;;;EAMrC,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,+BAA+B;;;;;;;;;;;kBAOjC,CAAC;AAEZ,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AACxF,MAAM,MAAM,wBAAwB,GAAG,CACrC,KAAK,EAAE,yBAAyB,KAC7B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,8BAA8B;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,YAAY,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAK3C;CACF;AAED,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,mCAAmC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,YAAY,KAAK,EAAE,MAAM,EAIxB;CACF;AAED,qBAAa,0CAA2C,SAAQ,KAAK;IACnE,QAAQ,CAAC,IAAI,8CAA8C;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,YAAY,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAIxC;CACF;AAED;;;;;;;;;GASG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,+BAA+B;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,sBAAsB,EAAE,GAAG,SAAS,CAAC;IAEtD,YACE,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,sBAAsB,EAAE,EAOlC;CACF"}
@@ -53,7 +53,7 @@ import {
53
53
  isWithinDir,
54
54
  realPathWithinDir
55
55
  } from "../index-sbdmyz75.js";
56
- import"../index-557by2db.js";
56
+ import"../index-7b188kmz.js";
57
57
  import {
58
58
  ShutdownOptionsSchema,
59
59
  ShutdownResultSchema,
package/dist/testing.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  RealtimeRequestDisconnectedError,
12
12
  RealtimeRequestInvalidAcknowledgementError,
13
13
  RealtimeRequestTimeoutError
14
- } from "./index-557by2db.js";
14
+ } from "./index-7b188kmz.js";
15
15
  import"./index-dk6e56g0.js";
16
16
  import {
17
17
  mcpProjectionCandidate,
package/llms-full.txt CHANGED
@@ -6161,6 +6161,7 @@ const socket = createRealtimeClient(realtimeContract, {
6161
6161
  url: 'https://api.example.com',
6162
6162
  retain: ['note:created'],
6163
6163
  onRejected: (event) => reportClientError(event),
6164
+ onRequestPhase: (event) => metrics.realtimeRequestPhase(event),
6164
6165
  })
6165
6166
 
6166
6167
  socket.connect()
@@ -6215,6 +6216,48 @@ or resumable delivery should use separate correlated events or the async
6215
6216
  operation protocol; keeping one acknowledgement open is not a durable RPC/job
6216
6217
  transport.
6217
6218
 
6219
+ ### Acknowledged-request phases
6220
+
6221
+ `createRealtimeClient` can expose the local boundary that a single Promise
6222
+ normally hides:
6223
+
6224
+ ```ts
6225
+ const socket = createRealtimeClient(realtimeContract, {
6226
+ url,
6227
+ onRequestPhase: ({ requestId, event, phase, elapsedMs }) => {
6228
+ requestPhaseHistogram.record(elapsedMs, { requestId, event, phase })
6229
+ },
6230
+ })
6231
+ ```
6232
+
6233
+ The hook is opt-in and each record has exactly four metadata fields: an opaque,
6234
+ Kit-owned `requestId`, the contract event name, monotonic `elapsedMs`, and one
6235
+ closed phase:
6236
+
6237
+ | Phase | Exact local boundary |
6238
+ |-------|----------------------|
6239
+ | `engine-handoff` | Engine.IO created the outbound message packet and accepted it into its write path |
6240
+ | `engine-ack-received` | Engine.IO decoded the inbound acknowledgement message, before Socket.IO invokes the acknowledgement callback |
6241
+ | `settled` | the acknowledgement callback ran and Stitchkit finished acknowledgement validation |
6242
+ | `timeout` | the existing native acknowledgement timeout won |
6243
+ | `disconnected` | the request began disconnected or an in-flight disconnect won |
6244
+
6245
+ Engine handoff is not proof of a physical network write. Engine acknowledgement
6246
+ receipt is not a remote clock, end-to-end RTT or proof that application
6247
+ validation has run. The useful interval is local and monotonic:
6248
+ `engine-ack-received → settled` isolates callback scheduling plus validation
6249
+ from transport waiting.
6250
+
6251
+ Records never contain request arguments, acknowledgement values, raw packets,
6252
+ credentials, URLs or query data. Concurrent requests are correlated internally
6253
+ with Socket.IO acknowledgement ids, but those ids are never exposed. A timeout
6254
+ or disconnect is terminal, a late packet cannot reopen the identity, and sync
6255
+ or async observer failures are ignored so telemetry cannot change request
6256
+ correctness. With no hook, no request identity, Engine.IO listener or correlation
6257
+ map entry is created. The low-level `createSocketIOClient` and non-owning
6258
+ `bindRealtimeClient` remain unchanged; this phase surface belongs to the
6259
+ canonical composed client that owns both transport and validation.
6260
+
6218
6261
  ## Low-level transport
6219
6262
 
6220
6263
  `createSocketIOClient` remains the low-level Socket.IO transport wrapper for
@@ -11248,7 +11291,7 @@ The browser-and-server entrypoint. Re-exports everything from
11248
11291
  | `SocketIOClientConfig` | _type_ | config for `createSocketIOClient` (incl. `retain`, `onConnectError`, `onDroppedEmit`) |
11249
11292
  | `SocketEventMap` | _type_ | the shape of an event map |
11250
11293
  | `RealtimeClient` | _type_ | validated client inferred from a realtime contract |
11251
- | `RealtimeClientOptions` | _type_ | transport options and the rejected-event hook for `createRealtimeClient` |
11294
+ | `RealtimeClientOptions` | _type_ | transport options plus rejected-event and metadata-only acknowledged-request phase hooks for `createRealtimeClient` |
11252
11295
  | `BoundRealtimeClient` | _type_ | validated non-owning `on`/`emit`/`request` client with no `connect`/`disconnect` |
11253
11296
  | `RealtimeClientTransport` | _type_ | minimal existing transport capability accepted by `bindRealtimeClient` |
11254
11297
  | `BindRealtimeClientOptions` | _type_ | rejection/logger options for a bound existing transport |
@@ -11256,6 +11299,9 @@ The browser-and-server entrypoint. Re-exports everything from
11256
11299
  | `RealtimeAcknowledgement` | _type_ | validated acknowledgement output inferred from an event definition |
11257
11300
  | `RealtimeRequestArguments` | _type_ | request arguments inferred from an acknowledged event tuple |
11258
11301
  | `RealtimeRequestOptions` | _type_ | finite positive native acknowledgement `timeoutMs` |
11302
+ | `RealtimeRequestPhaseSchema` / `RealtimeRequestPhase` | schema / _type_ | closed `engine-handoff` / `engine-ack-received` / `settled` / `timeout` / `disconnected` lifecycle |
11303
+ | `RealtimeRequestPhaseEventSchema` / `RealtimeRequestPhaseEvent` | schema / _type_ | strict metadata-only `{ requestId, event, phase, elapsedMs }` observation |
11304
+ | `RealtimeRequestPhaseHook` | _type_ | isolated sync/async observer accepted by `RealtimeClientOptions.onRequestPhase` |
11259
11305
  | `RealtimeRequestTimeoutError` | class | stable `REALTIME_REQUEST_TIMEOUT` rejection |
11260
11306
  | `RealtimeRequestDisconnectedError` | class | stable `REALTIME_REQUEST_DISCONNECTED` rejection, including an immediate disconnected call |
11261
11307
  | `RealtimeRequestInvalidAcknowledgementError` | class | invalid ack was reported through `onRejected` and the request rejected |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.68.10",
3
+ "version": "0.68.11",
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",