@xemahq/platform-common 0.5.1 → 0.5.3

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.
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './lib/biome-database';
4
4
  export * as Briefcase from './lib/briefcase/index';
5
5
  export * from './lib/deliverable-output-contract';
6
6
  export * from './lib/derive-required-workspace-slots';
7
+ export * from './lib/edge-stream/index';
7
8
  export * from './lib/encryption';
8
9
  export * from './lib/envelope-encryption';
9
10
  export * from './lib/blind-index';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAIrC,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oCAAoC,CAAC;AACnD,cAAc,yBAAyB,CAAC;AAGxC,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAG1C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAIrC,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oCAAoC,CAAC;AACnD,cAAc,yBAAyB,CAAC;AAGxC,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAG1C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -43,6 +43,7 @@ __exportStar(require("./lib/biome-database"), exports);
43
43
  exports.Briefcase = __importStar(require("./lib/briefcase/index"));
44
44
  __exportStar(require("./lib/deliverable-output-contract"), exports);
45
45
  __exportStar(require("./lib/derive-required-workspace-slots"), exports);
46
+ __exportStar(require("./lib/edge-stream/index"), exports);
46
47
  __exportStar(require("./lib/encryption"), exports);
47
48
  __exportStar(require("./lib/envelope-encryption"), exports);
48
49
  __exportStar(require("./lib/blind-index"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,sDAAoC;AACpC,sDAAoC;AACpC,uDAAqC;AAIrC,mEAAmD;AACnD,oEAAkD;AAClD,wEAAsD;AACtD,mDAAiC;AACjC,4DAA0C;AAC1C,oDAAkC;AAClC,+DAA6C;AAC7C,0DAAwC;AACxC,uDAAqC;AACrC,oDAAkC;AAClC,yDAAuC;AACvC,iEAA+C;AAC/C,wDAAsC;AACtC,4DAA0C;AAC1C,yDAAuC;AACvC,yDAAuC;AACvC,gEAA8C;AAC9C,sDAAoC;AACpC,2DAAyC;AACzC,uDAAqC;AACrC,wDAAsC;AACtC,4DAA0C;AAC1C,4DAA0C;AAC1C,wDAAsC;AACtC,4DAA0C;AAC1C,sDAAoC;AACpC,qDAAmC;AACnC,qEAAmD;AACnD,0DAAwC;AAGxC,kEAAgD;AAChD,uDAAqC;AACrC,2DAAyC;AACzC,4DAA0C;AAG1C,yDAAuC;AAGvC,uDAAqC;AAGrC,iDAA+B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,sDAAoC;AACpC,sDAAoC;AACpC,uDAAqC;AAIrC,mEAAmD;AACnD,oEAAkD;AAClD,wEAAsD;AACtD,0DAAwC;AACxC,mDAAiC;AACjC,4DAA0C;AAC1C,oDAAkC;AAClC,+DAA6C;AAC7C,0DAAwC;AACxC,uDAAqC;AACrC,oDAAkC;AAClC,yDAAuC;AACvC,iEAA+C;AAC/C,wDAAsC;AACtC,4DAA0C;AAC1C,yDAAuC;AACvC,yDAAuC;AACvC,gEAA8C;AAC9C,sDAAoC;AACpC,2DAAyC;AACzC,uDAAqC;AACrC,wDAAsC;AACtC,4DAA0C;AAC1C,4DAA0C;AAC1C,wDAAsC;AACtC,4DAA0C;AAC1C,sDAAoC;AACpC,qDAAmC;AACnC,qEAAmD;AACnD,0DAAwC;AAGxC,kEAAgD;AAChD,uDAAqC;AACrC,2DAAyC;AACzC,4DAA0C;AAG1C,yDAAuC;AAGvC,uDAAqC;AAGrC,iDAA+B"}
@@ -0,0 +1,5 @@
1
+ export declare const EDGE_PROXY_READ_TIMEOUT_MS = 125000;
2
+ export declare const EDGE_WEBSOCKET_IDLE_TIMEOUT_MS = 100000;
3
+ export declare const SSE_HEARTBEAT_INTERVAL_MS = 20000;
4
+ export declare const WS_PING_INTERVAL_MS = 25000;
5
+ //# sourceMappingURL=edge-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-budget.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-stream/edge-budget.ts"],"names":[],"mappings":"AAqCA,eAAO,MAAM,0BAA0B,SAAU,CAAC;AAOlD,eAAO,MAAM,8BAA8B,SAAU,CAAC;AAGtD,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAGhD,eAAO,MAAM,mBAAmB,QAAS,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WS_PING_INTERVAL_MS = exports.SSE_HEARTBEAT_INTERVAL_MS = exports.EDGE_WEBSOCKET_IDLE_TIMEOUT_MS = exports.EDGE_PROXY_READ_TIMEOUT_MS = void 0;
4
+ exports.EDGE_PROXY_READ_TIMEOUT_MS = 125_000;
5
+ exports.EDGE_WEBSOCKET_IDLE_TIMEOUT_MS = 100_000;
6
+ exports.SSE_HEARTBEAT_INTERVAL_MS = 20_000;
7
+ exports.WS_PING_INTERVAL_MS = 25_000;
8
+ //# sourceMappingURL=edge-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-budget.js","sourceRoot":"","sources":["../../../src/lib/edge-stream/edge-budget.ts"],"names":[],"mappings":";;;AAqCa,QAAA,0BAA0B,GAAG,OAAO,CAAC;AAOrC,QAAA,8BAA8B,GAAG,OAAO,CAAC;AAGzC,QAAA,yBAAyB,GAAG,MAAM,CAAC;AAGnC,QAAA,mBAAmB,GAAG,MAAM,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './edge-budget';
2
+ export * from './sse-stream';
3
+ export * from './ws-keepalive';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-stream/index.ts"],"names":[],"mappings":"AAUA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./edge-budget"), exports);
18
+ __exportStar(require("./sse-stream"), exports);
19
+ __exportStar(require("./ws-keepalive"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/edge-stream/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAUA,gDAA8B;AAC9B,+CAA6B;AAC7B,iDAA+B"}
@@ -0,0 +1,20 @@
1
+ import type { ServerResponse } from 'node:http';
2
+ export type IsClosedFn = () => boolean;
3
+ export declare function writeOrAwaitDrain(res: ServerResponse, chunk: string, isClosed: IsClosedFn): Promise<void>;
4
+ export interface SseStreamOptions {
5
+ readonly heartbeatIntervalMs?: number;
6
+ readonly write?: (chunk: string) => void | Promise<void>;
7
+ readonly isClosed?: IsClosedFn;
8
+ readonly beat?: () => void | Promise<void>;
9
+ readonly onHeartbeatError?: (error: unknown) => void;
10
+ }
11
+ export interface SseStream {
12
+ readonly alive: () => boolean;
13
+ readonly comment: (text: string) => void;
14
+ readonly stop: () => void;
15
+ }
16
+ export declare function openSseStream(res: ServerResponse, options?: SseStreamOptions): SseStream;
17
+ export declare function openSseRelay(res: ServerResponse, options: {
18
+ readonly heartbeatOwnedBy: string;
19
+ }): void;
20
+ //# sourceMappingURL=sse-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-stream.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-stream/sse-stream.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAYhD,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC;AAevC,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,MAAM,WAAW,gBAAgB;IAM/B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAMtC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAS/B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAQ3C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,SAAS;IAExB,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC;IAO9B,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzC,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;CAC3B;AAaD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE,gBAAqB,GAC7B,SAAS,CA8FX;AAcD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE;IAAE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC7C,IAAI,CAYN"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeOrAwaitDrain = writeOrAwaitDrain;
4
+ exports.openSseStream = openSseStream;
5
+ exports.openSseRelay = openSseRelay;
6
+ const edge_budget_1 = require("./edge-budget");
7
+ async function writeOrAwaitDrain(res, chunk, isClosed) {
8
+ if (isClosed() || res.writableEnded || res.destroyed) {
9
+ return;
10
+ }
11
+ const ok = res.write(chunk);
12
+ if (ok) {
13
+ return;
14
+ }
15
+ await new Promise((resolve) => {
16
+ const settle = () => {
17
+ res.removeListener('drain', settle);
18
+ res.removeListener('close', settle);
19
+ res.removeListener('error', settle);
20
+ resolve();
21
+ };
22
+ res.once('drain', settle);
23
+ res.once('close', settle);
24
+ res.once('error', settle);
25
+ });
26
+ }
27
+ const HEARTBEAT_COMMENT = 'heartbeat';
28
+ function openSseStream(res, options = {}) {
29
+ const intervalMs = options.heartbeatIntervalMs ?? edge_budget_1.SSE_HEARTBEAT_INTERVAL_MS;
30
+ if (!Number.isInteger(intervalMs) || intervalMs <= 0) {
31
+ throw new Error(`openSseStream: heartbeatIntervalMs must be a positive integer, received ${String(intervalMs)}.`);
32
+ }
33
+ if (intervalMs >= edge_budget_1.EDGE_WEBSOCKET_IDLE_TIMEOUT_MS) {
34
+ throw new Error(`openSseStream: heartbeatIntervalMs ${intervalMs}ms is at or above the ${edge_budget_1.EDGE_WEBSOCKET_IDLE_TIMEOUT_MS}ms edge idle window, so it cannot keep the stream alive. See edge-budget.ts.`);
35
+ }
36
+ res.setHeader('Content-Type', 'text/event-stream');
37
+ res.setHeader('Cache-Control', 'no-cache, no-transform');
38
+ res.setHeader('Connection', 'keep-alive');
39
+ res.setHeader('X-Accel-Buffering', 'no');
40
+ res.flushHeaders();
41
+ res.socket?.setNoDelay(true);
42
+ const isClosed = options.isClosed ?? (() => false);
43
+ const write = options.write ??
44
+ ((chunk) => writeOrAwaitDrain(res, chunk, isClosed));
45
+ let stopped = false;
46
+ let timer;
47
+ const alive = () => !stopped && !res.writableEnded && !res.destroyed && !isClosed();
48
+ const stop = () => {
49
+ if (stopped) {
50
+ return;
51
+ }
52
+ stopped = true;
53
+ if (timer !== undefined) {
54
+ clearInterval(timer);
55
+ }
56
+ res.removeListener('close', stop);
57
+ res.removeListener('error', stop);
58
+ };
59
+ timer = setInterval(() => {
60
+ if (!alive()) {
61
+ stop();
62
+ return;
63
+ }
64
+ try {
65
+ const result = options.beat
66
+ ? options.beat()
67
+ : write(`: ${HEARTBEAT_COMMENT}\n\n`);
68
+ if (result instanceof Promise) {
69
+ result.catch((error) => {
70
+ stop();
71
+ options.onHeartbeatError?.(error);
72
+ });
73
+ }
74
+ }
75
+ catch (error) {
76
+ stop();
77
+ options.onHeartbeatError?.(error);
78
+ }
79
+ }, intervalMs);
80
+ timer.unref?.();
81
+ res.once('close', stop);
82
+ res.once('error', stop);
83
+ const commentFn = (text) => {
84
+ if (/[\r\n]/.test(text)) {
85
+ throw new Error('SseStream.comment: an SSE comment must not contain CR or LF — it would end the comment and let the remainder parse as an event.');
86
+ }
87
+ if (!alive()) {
88
+ return;
89
+ }
90
+ const result = write(`: ${text}\n\n`);
91
+ if (result instanceof Promise) {
92
+ result.catch((error) => {
93
+ options.onHeartbeatError?.(error);
94
+ });
95
+ }
96
+ };
97
+ return { alive, comment: commentFn, stop };
98
+ }
99
+ function openSseRelay(res, options) {
100
+ if (options.heartbeatOwnedBy.trim().length === 0) {
101
+ throw new Error('openSseRelay: heartbeatOwnedBy must name the upstream whose heartbeat keeps this relay alive. A relay cannot beat for itself without corrupting forwarded frames.');
102
+ }
103
+ res.setHeader('Content-Type', 'text/event-stream');
104
+ res.setHeader('Cache-Control', 'no-cache, no-transform');
105
+ res.setHeader('Connection', 'keep-alive');
106
+ res.setHeader('X-Accel-Buffering', 'no');
107
+ res.flushHeaders();
108
+ res.socket?.setNoDelay(true);
109
+ }
110
+ //# sourceMappingURL=sse-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-stream.js","sourceRoot":"","sources":["../../../src/lib/edge-stream/sse-stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface WebSocketKeepaliveTarget {
2
+ readonly readyState: number;
3
+ ping(): void;
4
+ }
5
+ export interface WebSocketKeepaliveOptions {
6
+ readonly intervalMs?: number;
7
+ readonly onError?: (error: unknown) => void;
8
+ }
9
+ export interface WebSocketKeepalive {
10
+ readonly stop: () => void;
11
+ }
12
+ export declare function startWebSocketKeepalive(socket: WebSocketKeepaliveTarget, options?: WebSocketKeepaliveOptions): WebSocketKeepalive;
13
+ //# sourceMappingURL=ws-keepalive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-keepalive.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-stream/ws-keepalive.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,IAAI,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,yBAAyB;IAExC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAM7B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,kBAAkB;IAEjC,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;CAC3B;AAUD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,wBAAwB,EAChC,OAAO,GAAE,yBAA8B,GACtC,kBAAkB,CAoCpB"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startWebSocketKeepalive = startWebSocketKeepalive;
4
+ const edge_budget_1 = require("./edge-budget");
5
+ const WEBSOCKET_OPEN = 1;
6
+ function startWebSocketKeepalive(socket, options = {}) {
7
+ const intervalMs = options.intervalMs ?? edge_budget_1.WS_PING_INTERVAL_MS;
8
+ if (!Number.isInteger(intervalMs) || intervalMs <= 0) {
9
+ throw new Error(`startWebSocketKeepalive: intervalMs must be a positive integer, received ${String(intervalMs)}.`);
10
+ }
11
+ let stopped = false;
12
+ let timer;
13
+ const stop = () => {
14
+ if (stopped) {
15
+ return;
16
+ }
17
+ stopped = true;
18
+ if (timer !== undefined) {
19
+ clearInterval(timer);
20
+ }
21
+ };
22
+ timer = setInterval(() => {
23
+ if (socket.readyState !== WEBSOCKET_OPEN) {
24
+ stop();
25
+ return;
26
+ }
27
+ try {
28
+ socket.ping();
29
+ }
30
+ catch (error) {
31
+ stop();
32
+ options.onError?.(error);
33
+ }
34
+ }, intervalMs);
35
+ timer.unref?.();
36
+ return { stop };
37
+ }
38
+ //# sourceMappingURL=ws-keepalive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-keepalive.js","sourceRoot":"","sources":["../../../src/lib/edge-stream/ws-keepalive.ts"],"names":[],"mappings":";;AAoDA,0DAuCC;AA9ED,+CAAoD;AAOpD,MAAM,cAAc,GAAG,CAAC,CAAC;AAgCzB,SAAgB,uBAAuB,CACrC,MAAgC,EAChC,UAAqC,EAAE;IAEvC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,iCAAmB,CAAC;IAC7D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CACb,4EAA4E,MAAM,CAAC,UAAU,CAAC,GAAG,CAClG,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,KAAiD,CAAC;IAEtD,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QACD,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,aAAa,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QACvB,IAAI,MAAM,CAAC,UAAU,KAAK,cAAc,EAAE,CAAC;YACzC,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,EAAE,CAAC;YACP,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,EAAE,UAAU,CAAC,CAAC;IACd,KAAgC,CAAC,KAAK,EAAE,EAAE,CAAC;IAE5C,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/platform-common",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Shared NestJS building blocks for Xema services — auth guards, response redaction, CORS configuration, and crypto helpers.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
@@ -26,7 +26,10 @@
26
26
  "@nestjs/platform-express": ">=10",
27
27
  "@nestjs/swagger": ">=7",
28
28
  "rxjs": ">=7",
29
- "@xemahq/kernel-contracts": ">=0.57.0"
29
+ "@xemahq/kernel-contracts": ">=0.57.0",
30
+ "class-validator": ">=0.14",
31
+ "class-transformer": ">=0.5",
32
+ "reflect-metadata": ">=0.2"
30
33
  },
31
34
  "peerDependenciesMeta": {
32
35
  "@nestjs/platform-express": {
@@ -59,7 +62,7 @@
59
62
  "rxjs": "7.8.2",
60
63
  "ts-jest": "^29.4.9",
61
64
  "typescript": "5.9.3",
62
- "@xemahq/kernel-contracts": "^0.57.0"
65
+ "@xemahq/kernel-contracts": "^0.58.0"
63
66
  },
64
67
  "exports": {
65
68
  ".": {