@zapier/zapier-sdk 0.32.0 → 0.32.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.
- package/CHANGELOG.md +6 -0
- package/dist/index.cjs +60 -38
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +60 -38
- package/dist/plugins/eventEmission/index.d.ts +1 -0
- package/dist/plugins/eventEmission/index.d.ts.map +1 -1
- package/dist/plugins/eventEmission/index.js +49 -45
- package/dist/plugins/eventEmission/index.test.js +92 -0
- package/dist/plugins/request/index.test.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -5503,7 +5503,7 @@ function getCpuTime() {
|
|
|
5503
5503
|
|
|
5504
5504
|
// package.json
|
|
5505
5505
|
var package_default = {
|
|
5506
|
-
version: "0.32.
|
|
5506
|
+
version: "0.32.1"};
|
|
5507
5507
|
|
|
5508
5508
|
// src/plugins/eventEmission/builders.ts
|
|
5509
5509
|
function createBaseEvent(context = {}) {
|
|
@@ -5627,6 +5627,20 @@ var APPLICATION_LIFECYCLE_EVENT_SUBJECT = "platform.sdk.ApplicationLifecycleEven
|
|
|
5627
5627
|
var ERROR_OCCURRED_EVENT_SUBJECT = "platform.sdk.ErrorOccurredEvent";
|
|
5628
5628
|
var METHOD_CALLED_EVENT_SUBJECT = "platform.sdk.MethodCalledEvent";
|
|
5629
5629
|
var transportStates = /* @__PURE__ */ new WeakMap();
|
|
5630
|
+
async function emitWithTimeout(transport, subject, event) {
|
|
5631
|
+
try {
|
|
5632
|
+
await Promise.race([
|
|
5633
|
+
transport.emit(subject, event),
|
|
5634
|
+
new Promise((resolve2) => {
|
|
5635
|
+
const timer = setTimeout(resolve2, TELEMETRY_EMIT_TIMEOUT_MS);
|
|
5636
|
+
if (typeof timer.unref === "function") {
|
|
5637
|
+
timer.unref();
|
|
5638
|
+
}
|
|
5639
|
+
})
|
|
5640
|
+
]);
|
|
5641
|
+
} catch {
|
|
5642
|
+
}
|
|
5643
|
+
}
|
|
5630
5644
|
async function silentEmit(transport, subject, event, userContextPromise) {
|
|
5631
5645
|
try {
|
|
5632
5646
|
let state = transportStates.get(transport);
|
|
@@ -5705,6 +5719,7 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5705
5719
|
})();
|
|
5706
5720
|
const startupTime = Date.now();
|
|
5707
5721
|
let shutdownStartTime = null;
|
|
5722
|
+
let closed = false;
|
|
5708
5723
|
if (!config.enabled) {
|
|
5709
5724
|
return {
|
|
5710
5725
|
context: {
|
|
@@ -5724,6 +5739,8 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5724
5739
|
correlation_id: null
|
|
5725
5740
|
}),
|
|
5726
5741
|
emitMethodCalled: () => {
|
|
5742
|
+
},
|
|
5743
|
+
close: async () => {
|
|
5727
5744
|
}
|
|
5728
5745
|
}
|
|
5729
5746
|
}
|
|
@@ -5766,6 +5783,7 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5766
5783
|
if (typeof process?.on === "function") {
|
|
5767
5784
|
removeExistingListeners();
|
|
5768
5785
|
const exitHandler = (code) => {
|
|
5786
|
+
if (closed) return;
|
|
5769
5787
|
const uptime = Date.now() - startupTime;
|
|
5770
5788
|
const shutdownDuration = shutdownStartTime ? Date.now() - shutdownStartTime : null;
|
|
5771
5789
|
const exitEvent = buildApplicationLifecycleEvent({
|
|
@@ -5799,18 +5817,11 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5799
5817
|
errorEvent = { ...errorEvent, ...userContext };
|
|
5800
5818
|
} catch {
|
|
5801
5819
|
}
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
if (typeof timer.unref === "function") {
|
|
5808
|
-
timer.unref();
|
|
5809
|
-
}
|
|
5810
|
-
})
|
|
5811
|
-
]);
|
|
5812
|
-
} catch {
|
|
5813
|
-
}
|
|
5820
|
+
await emitWithTimeout(
|
|
5821
|
+
transport,
|
|
5822
|
+
ERROR_OCCURRED_EVENT_SUBJECT,
|
|
5823
|
+
errorEvent
|
|
5824
|
+
);
|
|
5814
5825
|
};
|
|
5815
5826
|
registeredListeners.uncaughtException = uncaughtExceptionHandler;
|
|
5816
5827
|
process.on("uncaughtException", uncaughtExceptionHandler);
|
|
@@ -5834,18 +5845,11 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5834
5845
|
errorEvent = { ...errorEvent, ...userContext };
|
|
5835
5846
|
} catch {
|
|
5836
5847
|
}
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
if (typeof timer.unref === "function") {
|
|
5843
|
-
timer.unref();
|
|
5844
|
-
}
|
|
5845
|
-
})
|
|
5846
|
-
]);
|
|
5847
|
-
} catch {
|
|
5848
|
-
}
|
|
5848
|
+
await emitWithTimeout(
|
|
5849
|
+
transport,
|
|
5850
|
+
ERROR_OCCURRED_EVENT_SUBJECT,
|
|
5851
|
+
errorEvent
|
|
5852
|
+
);
|
|
5849
5853
|
};
|
|
5850
5854
|
registeredListeners.unhandledRejection = unhandledRejectionHandler;
|
|
5851
5855
|
process.on("unhandledRejection", unhandledRejectionHandler);
|
|
@@ -5863,18 +5867,11 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5863
5867
|
signalEvent = { ...signalEvent, ...userContext };
|
|
5864
5868
|
} catch {
|
|
5865
5869
|
}
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
if (typeof timer.unref === "function") {
|
|
5872
|
-
timer.unref();
|
|
5873
|
-
}
|
|
5874
|
-
})
|
|
5875
|
-
]);
|
|
5876
|
-
} catch {
|
|
5877
|
-
}
|
|
5870
|
+
await emitWithTimeout(
|
|
5871
|
+
transport,
|
|
5872
|
+
APPLICATION_LIFECYCLE_EVENT_SUBJECT,
|
|
5873
|
+
signalEvent
|
|
5874
|
+
);
|
|
5878
5875
|
const exitCode = signal === "SIGINT" ? 130 : 143;
|
|
5879
5876
|
process.exit(exitCode);
|
|
5880
5877
|
};
|
|
@@ -5886,6 +5883,30 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5886
5883
|
process.on("SIGTERM", sigtermHandler);
|
|
5887
5884
|
}
|
|
5888
5885
|
}
|
|
5886
|
+
const close = async (exitCode) => {
|
|
5887
|
+
if (closed) return;
|
|
5888
|
+
closed = true;
|
|
5889
|
+
const uptime = Date.now() - startupTime;
|
|
5890
|
+
const shutdownDuration = shutdownStartTime ? Date.now() - shutdownStartTime : null;
|
|
5891
|
+
let exitEvent = buildApplicationLifecycleEvent({
|
|
5892
|
+
lifecycle_event_type: "exit",
|
|
5893
|
+
exit_code: exitCode ?? 0,
|
|
5894
|
+
uptime_ms: uptime,
|
|
5895
|
+
is_graceful_shutdown: (exitCode ?? 0) === 0,
|
|
5896
|
+
shutdown_duration_ms: shutdownDuration
|
|
5897
|
+
});
|
|
5898
|
+
try {
|
|
5899
|
+
const userContext = await getUserContext;
|
|
5900
|
+
exitEvent = { ...exitEvent, ...userContext };
|
|
5901
|
+
} catch {
|
|
5902
|
+
}
|
|
5903
|
+
await emitWithTimeout(
|
|
5904
|
+
transport,
|
|
5905
|
+
APPLICATION_LIFECYCLE_EVENT_SUBJECT,
|
|
5906
|
+
exitEvent
|
|
5907
|
+
);
|
|
5908
|
+
removeExistingListeners();
|
|
5909
|
+
};
|
|
5889
5910
|
return {
|
|
5890
5911
|
context: {
|
|
5891
5912
|
eventEmission: {
|
|
@@ -5906,7 +5927,8 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5906
5927
|
event,
|
|
5907
5928
|
getUserContext
|
|
5908
5929
|
);
|
|
5909
|
-
}
|
|
5930
|
+
},
|
|
5931
|
+
close
|
|
5910
5932
|
}
|
|
5911
5933
|
}
|
|
5912
5934
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -388,6 +388,7 @@ interface EventEmissionContext {
|
|
|
388
388
|
emit<T extends any>(subject: string, event: T): void;
|
|
389
389
|
createBaseEvent(): Promise<BaseEvent>;
|
|
390
390
|
emitMethodCalled(data: MethodCalledEventData): void;
|
|
391
|
+
close(exitCode?: number): Promise<void>;
|
|
391
392
|
};
|
|
392
393
|
}
|
|
393
394
|
interface EventEmissionProvides {
|
package/dist/index.mjs
CHANGED
|
@@ -5481,7 +5481,7 @@ function getCpuTime() {
|
|
|
5481
5481
|
|
|
5482
5482
|
// package.json
|
|
5483
5483
|
var package_default = {
|
|
5484
|
-
version: "0.32.
|
|
5484
|
+
version: "0.32.1"};
|
|
5485
5485
|
|
|
5486
5486
|
// src/plugins/eventEmission/builders.ts
|
|
5487
5487
|
function createBaseEvent(context = {}) {
|
|
@@ -5605,6 +5605,20 @@ var APPLICATION_LIFECYCLE_EVENT_SUBJECT = "platform.sdk.ApplicationLifecycleEven
|
|
|
5605
5605
|
var ERROR_OCCURRED_EVENT_SUBJECT = "platform.sdk.ErrorOccurredEvent";
|
|
5606
5606
|
var METHOD_CALLED_EVENT_SUBJECT = "platform.sdk.MethodCalledEvent";
|
|
5607
5607
|
var transportStates = /* @__PURE__ */ new WeakMap();
|
|
5608
|
+
async function emitWithTimeout(transport, subject, event) {
|
|
5609
|
+
try {
|
|
5610
|
+
await Promise.race([
|
|
5611
|
+
transport.emit(subject, event),
|
|
5612
|
+
new Promise((resolve2) => {
|
|
5613
|
+
const timer = setTimeout(resolve2, TELEMETRY_EMIT_TIMEOUT_MS);
|
|
5614
|
+
if (typeof timer.unref === "function") {
|
|
5615
|
+
timer.unref();
|
|
5616
|
+
}
|
|
5617
|
+
})
|
|
5618
|
+
]);
|
|
5619
|
+
} catch {
|
|
5620
|
+
}
|
|
5621
|
+
}
|
|
5608
5622
|
async function silentEmit(transport, subject, event, userContextPromise) {
|
|
5609
5623
|
try {
|
|
5610
5624
|
let state = transportStates.get(transport);
|
|
@@ -5683,6 +5697,7 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5683
5697
|
})();
|
|
5684
5698
|
const startupTime = Date.now();
|
|
5685
5699
|
let shutdownStartTime = null;
|
|
5700
|
+
let closed = false;
|
|
5686
5701
|
if (!config.enabled) {
|
|
5687
5702
|
return {
|
|
5688
5703
|
context: {
|
|
@@ -5702,6 +5717,8 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5702
5717
|
correlation_id: null
|
|
5703
5718
|
}),
|
|
5704
5719
|
emitMethodCalled: () => {
|
|
5720
|
+
},
|
|
5721
|
+
close: async () => {
|
|
5705
5722
|
}
|
|
5706
5723
|
}
|
|
5707
5724
|
}
|
|
@@ -5744,6 +5761,7 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5744
5761
|
if (typeof process?.on === "function") {
|
|
5745
5762
|
removeExistingListeners();
|
|
5746
5763
|
const exitHandler = (code) => {
|
|
5764
|
+
if (closed) return;
|
|
5747
5765
|
const uptime = Date.now() - startupTime;
|
|
5748
5766
|
const shutdownDuration = shutdownStartTime ? Date.now() - shutdownStartTime : null;
|
|
5749
5767
|
const exitEvent = buildApplicationLifecycleEvent({
|
|
@@ -5777,18 +5795,11 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5777
5795
|
errorEvent = { ...errorEvent, ...userContext };
|
|
5778
5796
|
} catch {
|
|
5779
5797
|
}
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
if (typeof timer.unref === "function") {
|
|
5786
|
-
timer.unref();
|
|
5787
|
-
}
|
|
5788
|
-
})
|
|
5789
|
-
]);
|
|
5790
|
-
} catch {
|
|
5791
|
-
}
|
|
5798
|
+
await emitWithTimeout(
|
|
5799
|
+
transport,
|
|
5800
|
+
ERROR_OCCURRED_EVENT_SUBJECT,
|
|
5801
|
+
errorEvent
|
|
5802
|
+
);
|
|
5792
5803
|
};
|
|
5793
5804
|
registeredListeners.uncaughtException = uncaughtExceptionHandler;
|
|
5794
5805
|
process.on("uncaughtException", uncaughtExceptionHandler);
|
|
@@ -5812,18 +5823,11 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5812
5823
|
errorEvent = { ...errorEvent, ...userContext };
|
|
5813
5824
|
} catch {
|
|
5814
5825
|
}
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
if (typeof timer.unref === "function") {
|
|
5821
|
-
timer.unref();
|
|
5822
|
-
}
|
|
5823
|
-
})
|
|
5824
|
-
]);
|
|
5825
|
-
} catch {
|
|
5826
|
-
}
|
|
5826
|
+
await emitWithTimeout(
|
|
5827
|
+
transport,
|
|
5828
|
+
ERROR_OCCURRED_EVENT_SUBJECT,
|
|
5829
|
+
errorEvent
|
|
5830
|
+
);
|
|
5827
5831
|
};
|
|
5828
5832
|
registeredListeners.unhandledRejection = unhandledRejectionHandler;
|
|
5829
5833
|
process.on("unhandledRejection", unhandledRejectionHandler);
|
|
@@ -5841,18 +5845,11 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5841
5845
|
signalEvent = { ...signalEvent, ...userContext };
|
|
5842
5846
|
} catch {
|
|
5843
5847
|
}
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
if (typeof timer.unref === "function") {
|
|
5850
|
-
timer.unref();
|
|
5851
|
-
}
|
|
5852
|
-
})
|
|
5853
|
-
]);
|
|
5854
|
-
} catch {
|
|
5855
|
-
}
|
|
5848
|
+
await emitWithTimeout(
|
|
5849
|
+
transport,
|
|
5850
|
+
APPLICATION_LIFECYCLE_EVENT_SUBJECT,
|
|
5851
|
+
signalEvent
|
|
5852
|
+
);
|
|
5856
5853
|
const exitCode = signal === "SIGINT" ? 130 : 143;
|
|
5857
5854
|
process.exit(exitCode);
|
|
5858
5855
|
};
|
|
@@ -5864,6 +5861,30 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5864
5861
|
process.on("SIGTERM", sigtermHandler);
|
|
5865
5862
|
}
|
|
5866
5863
|
}
|
|
5864
|
+
const close = async (exitCode) => {
|
|
5865
|
+
if (closed) return;
|
|
5866
|
+
closed = true;
|
|
5867
|
+
const uptime = Date.now() - startupTime;
|
|
5868
|
+
const shutdownDuration = shutdownStartTime ? Date.now() - shutdownStartTime : null;
|
|
5869
|
+
let exitEvent = buildApplicationLifecycleEvent({
|
|
5870
|
+
lifecycle_event_type: "exit",
|
|
5871
|
+
exit_code: exitCode ?? 0,
|
|
5872
|
+
uptime_ms: uptime,
|
|
5873
|
+
is_graceful_shutdown: (exitCode ?? 0) === 0,
|
|
5874
|
+
shutdown_duration_ms: shutdownDuration
|
|
5875
|
+
});
|
|
5876
|
+
try {
|
|
5877
|
+
const userContext = await getUserContext;
|
|
5878
|
+
exitEvent = { ...exitEvent, ...userContext };
|
|
5879
|
+
} catch {
|
|
5880
|
+
}
|
|
5881
|
+
await emitWithTimeout(
|
|
5882
|
+
transport,
|
|
5883
|
+
APPLICATION_LIFECYCLE_EVENT_SUBJECT,
|
|
5884
|
+
exitEvent
|
|
5885
|
+
);
|
|
5886
|
+
removeExistingListeners();
|
|
5887
|
+
};
|
|
5867
5888
|
return {
|
|
5868
5889
|
context: {
|
|
5869
5890
|
eventEmission: {
|
|
@@ -5884,7 +5905,8 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
5884
5905
|
event,
|
|
5885
5906
|
getUserContext
|
|
5886
5907
|
);
|
|
5887
|
-
}
|
|
5908
|
+
},
|
|
5909
|
+
close
|
|
5888
5910
|
}
|
|
5889
5911
|
}
|
|
5890
5912
|
};
|
|
@@ -25,6 +25,7 @@ export interface EventEmissionContext {
|
|
|
25
25
|
emit<T extends any>(subject: string, event: T): void;
|
|
26
26
|
createBaseEvent(): Promise<BaseEvent>;
|
|
27
27
|
emitMethodCalled(data: MethodCalledEventData): void;
|
|
28
|
+
close(exitCode?: number): Promise<void>;
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
export interface EventEmissionProvides {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/eventEmission/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAWnE,OAAO,KAAK,EAAgB,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAsCnE;;;GAGG;AACH,wBAAgB,qBAAqB,SAEpC;AAGD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,WAAW,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;CACrC;AAGD,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE;QACb,SAAS,EAAE,cAAc,CAAC;QAC1B,MAAM,EAAE,mBAAmB,CAAC;QAE5B,IAAI,CAAC,CAAC,SAAS,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;QAErD,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;QAEtC,gBAAgB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/eventEmission/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAWnE,OAAO,KAAK,EAAgB,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAsCnE;;;GAGG;AACH,wBAAgB,qBAAqB,SAEpC;AAGD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,WAAW,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;CACrC;AAGD,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE;QACb,SAAS,EAAE,cAAc,CAAC;QAC1B,MAAM,EAAE,mBAAmB,CAAC;QAE5B,IAAI,CAAC,CAAC,SAAS,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;QAErD,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;QAEtC,gBAAgB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAAC;QAIpD,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACzC,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAiHD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CACtC,EAAE,EACF;IACE,OAAO,EAAE;QACP,aAAa,CAAC,EAAE,mBAAmB,CAAC;QACpC,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,EACD,qBAAqB,CAwTtB,CAAC;AAGF,YAAY,EACV,YAAY,EACZ,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,EAC1B,eAAe,EACf,eAAe,EACf,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,cAAc,SAAS,CAAC"}
|
|
@@ -41,6 +41,22 @@ const ERROR_OCCURRED_EVENT_SUBJECT = "platform.sdk.ErrorOccurredEvent";
|
|
|
41
41
|
const METHOD_CALLED_EVENT_SUBJECT = "platform.sdk.MethodCalledEvent";
|
|
42
42
|
// Track transport success/failure so we only log failure once.
|
|
43
43
|
const transportStates = new WeakMap();
|
|
44
|
+
async function emitWithTimeout(transport, subject, event) {
|
|
45
|
+
try {
|
|
46
|
+
await Promise.race([
|
|
47
|
+
transport.emit(subject, event),
|
|
48
|
+
new Promise((resolve) => {
|
|
49
|
+
const timer = setTimeout(resolve, TELEMETRY_EMIT_TIMEOUT_MS);
|
|
50
|
+
if (typeof timer.unref === "function") {
|
|
51
|
+
timer.unref();
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Silently ignore telemetry failures
|
|
58
|
+
}
|
|
59
|
+
}
|
|
44
60
|
// Silent emission wrapper with smart first-failure logging
|
|
45
61
|
async function silentEmit(transport, subject, event, userContextPromise) {
|
|
46
62
|
try {
|
|
@@ -135,6 +151,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
135
151
|
})();
|
|
136
152
|
const startupTime = Date.now();
|
|
137
153
|
let shutdownStartTime = null;
|
|
154
|
+
let closed = false;
|
|
138
155
|
// If disabled, return noop implementations
|
|
139
156
|
if (!config.enabled) {
|
|
140
157
|
return {
|
|
@@ -154,6 +171,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
154
171
|
correlation_id: null,
|
|
155
172
|
}),
|
|
156
173
|
emitMethodCalled: () => { },
|
|
174
|
+
close: async () => { },
|
|
157
175
|
},
|
|
158
176
|
},
|
|
159
177
|
};
|
|
@@ -201,6 +219,8 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
201
219
|
removeExistingListeners();
|
|
202
220
|
// Handle normal process exit
|
|
203
221
|
const exitHandler = (code) => {
|
|
222
|
+
if (closed)
|
|
223
|
+
return;
|
|
204
224
|
const uptime = Date.now() - startupTime;
|
|
205
225
|
const shutdownDuration = shutdownStartTime
|
|
206
226
|
? Date.now() - shutdownStartTime
|
|
@@ -235,21 +255,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
235
255
|
catch {
|
|
236
256
|
// Continue with original event if user context fails
|
|
237
257
|
}
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
await Promise.race([
|
|
241
|
-
transport.emit(ERROR_OCCURRED_EVENT_SUBJECT, errorEvent),
|
|
242
|
-
new Promise((resolve) => {
|
|
243
|
-
const timer = setTimeout(resolve, TELEMETRY_EMIT_TIMEOUT_MS);
|
|
244
|
-
if (typeof timer.unref === "function") {
|
|
245
|
-
timer.unref();
|
|
246
|
-
}
|
|
247
|
-
}),
|
|
248
|
-
]);
|
|
249
|
-
}
|
|
250
|
-
catch {
|
|
251
|
-
// Silently ignore telemetry failures
|
|
252
|
-
}
|
|
258
|
+
await emitWithTimeout(transport, ERROR_OCCURRED_EVENT_SUBJECT, errorEvent);
|
|
253
259
|
};
|
|
254
260
|
registeredListeners.uncaughtException = uncaughtExceptionHandler;
|
|
255
261
|
process.on("uncaughtException", uncaughtExceptionHandler);
|
|
@@ -281,21 +287,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
281
287
|
catch {
|
|
282
288
|
// Continue with original event if user context fails
|
|
283
289
|
}
|
|
284
|
-
|
|
285
|
-
try {
|
|
286
|
-
await Promise.race([
|
|
287
|
-
transport.emit(ERROR_OCCURRED_EVENT_SUBJECT, errorEvent),
|
|
288
|
-
new Promise((resolve) => {
|
|
289
|
-
const timer = setTimeout(resolve, TELEMETRY_EMIT_TIMEOUT_MS);
|
|
290
|
-
if (typeof timer.unref === "function") {
|
|
291
|
-
timer.unref();
|
|
292
|
-
}
|
|
293
|
-
}),
|
|
294
|
-
]);
|
|
295
|
-
}
|
|
296
|
-
catch {
|
|
297
|
-
// Silently ignore telemetry failures
|
|
298
|
-
}
|
|
290
|
+
await emitWithTimeout(transport, ERROR_OCCURRED_EVENT_SUBJECT, errorEvent);
|
|
299
291
|
};
|
|
300
292
|
registeredListeners.unhandledRejection = unhandledRejectionHandler;
|
|
301
293
|
process.on("unhandledRejection", unhandledRejectionHandler);
|
|
@@ -317,21 +309,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
317
309
|
catch {
|
|
318
310
|
// Continue with original event if user context fails
|
|
319
311
|
}
|
|
320
|
-
|
|
321
|
-
try {
|
|
322
|
-
await Promise.race([
|
|
323
|
-
transport.emit(APPLICATION_LIFECYCLE_EVENT_SUBJECT, signalEvent),
|
|
324
|
-
new Promise((resolve) => {
|
|
325
|
-
const timer = setTimeout(resolve, TELEMETRY_EMIT_TIMEOUT_MS);
|
|
326
|
-
if (typeof timer.unref === "function") {
|
|
327
|
-
timer.unref();
|
|
328
|
-
}
|
|
329
|
-
}),
|
|
330
|
-
]);
|
|
331
|
-
}
|
|
332
|
-
catch {
|
|
333
|
-
// Silently ignore telemetry failures
|
|
334
|
-
}
|
|
312
|
+
await emitWithTimeout(transport, APPLICATION_LIFECYCLE_EVENT_SUBJECT, signalEvent);
|
|
335
313
|
// Exit with appropriate code (128 + signal number)
|
|
336
314
|
const exitCode = signal === "SIGINT" ? 130 : 143;
|
|
337
315
|
process.exit(exitCode);
|
|
@@ -345,6 +323,31 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
345
323
|
process.on("SIGTERM", sigtermHandler);
|
|
346
324
|
}
|
|
347
325
|
}
|
|
326
|
+
const close = async (exitCode) => {
|
|
327
|
+
if (closed)
|
|
328
|
+
return;
|
|
329
|
+
closed = true;
|
|
330
|
+
const uptime = Date.now() - startupTime;
|
|
331
|
+
const shutdownDuration = shutdownStartTime
|
|
332
|
+
? Date.now() - shutdownStartTime
|
|
333
|
+
: null;
|
|
334
|
+
let exitEvent = buildApplicationLifecycleEvent({
|
|
335
|
+
lifecycle_event_type: "exit",
|
|
336
|
+
exit_code: exitCode ?? 0,
|
|
337
|
+
uptime_ms: uptime,
|
|
338
|
+
is_graceful_shutdown: (exitCode ?? 0) === 0,
|
|
339
|
+
shutdown_duration_ms: shutdownDuration,
|
|
340
|
+
});
|
|
341
|
+
try {
|
|
342
|
+
const userContext = await getUserContext;
|
|
343
|
+
exitEvent = { ...exitEvent, ...userContext };
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// Continue with original event if user context fails
|
|
347
|
+
}
|
|
348
|
+
await emitWithTimeout(transport, APPLICATION_LIFECYCLE_EVENT_SUBJECT, exitEvent);
|
|
349
|
+
removeExistingListeners();
|
|
350
|
+
};
|
|
348
351
|
return {
|
|
349
352
|
context: {
|
|
350
353
|
eventEmission: {
|
|
@@ -361,6 +364,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
361
364
|
};
|
|
362
365
|
silentEmit(transport, METHOD_CALLED_EVENT_SUBJECT, event, getUserContext);
|
|
363
366
|
},
|
|
367
|
+
close,
|
|
364
368
|
},
|
|
365
369
|
},
|
|
366
370
|
};
|
|
@@ -661,6 +661,98 @@ describe("emitMethodCalled call_context", () => {
|
|
|
661
661
|
expect(mockTransport.emit).toHaveBeenCalledWith("platform.sdk.MethodCalledEvent", expect.objectContaining({ call_context: "mcp" }));
|
|
662
662
|
});
|
|
663
663
|
});
|
|
664
|
+
describe("close()", () => {
|
|
665
|
+
beforeEach(() => {
|
|
666
|
+
vi.clearAllMocks();
|
|
667
|
+
cleanupEventListeners();
|
|
668
|
+
mockGetToken.mockResolvedValue(undefined);
|
|
669
|
+
});
|
|
670
|
+
afterEach(() => {
|
|
671
|
+
cleanupEventListeners();
|
|
672
|
+
});
|
|
673
|
+
it("should emit exit lifecycle event", async () => {
|
|
674
|
+
const plugin = eventEmissionPlugin({
|
|
675
|
+
sdk: {},
|
|
676
|
+
context: {
|
|
677
|
+
meta: {},
|
|
678
|
+
options: {
|
|
679
|
+
eventEmission: {
|
|
680
|
+
enabled: true,
|
|
681
|
+
transport: { type: "console" },
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
});
|
|
686
|
+
await plugin.context.eventEmission.close(0);
|
|
687
|
+
expect(mockTransport.emit).toHaveBeenCalledWith("platform.sdk.ApplicationLifecycleEvent", expect.objectContaining({
|
|
688
|
+
lifecycle_event_type: "exit",
|
|
689
|
+
exit_code: 0,
|
|
690
|
+
is_graceful_shutdown: true,
|
|
691
|
+
}));
|
|
692
|
+
});
|
|
693
|
+
it("should be idempotent — second call is a no-op", async () => {
|
|
694
|
+
const plugin = eventEmissionPlugin({
|
|
695
|
+
sdk: {},
|
|
696
|
+
context: {
|
|
697
|
+
meta: {},
|
|
698
|
+
options: {
|
|
699
|
+
eventEmission: {
|
|
700
|
+
enabled: true,
|
|
701
|
+
transport: { type: "console" },
|
|
702
|
+
},
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
});
|
|
706
|
+
await plugin.context.eventEmission.close(0);
|
|
707
|
+
const callCountAfterFirst = mockTransport.emit.mock.calls.filter((call) => call[0] === "platform.sdk.ApplicationLifecycleEvent" &&
|
|
708
|
+
call[1]?.lifecycle_event_type === "exit").length;
|
|
709
|
+
await plugin.context.eventEmission.close(0);
|
|
710
|
+
const callCountAfterSecond = mockTransport.emit.mock.calls.filter((call) => call[0] === "platform.sdk.ApplicationLifecycleEvent" &&
|
|
711
|
+
call[1]?.lifecycle_event_type === "exit").length;
|
|
712
|
+
expect(callCountAfterSecond).toBe(callCountAfterFirst);
|
|
713
|
+
});
|
|
714
|
+
it("should remove process listeners after close", async () => {
|
|
715
|
+
const initialExitCount = process.listenerCount("exit");
|
|
716
|
+
const plugin = eventEmissionPlugin({
|
|
717
|
+
sdk: {},
|
|
718
|
+
context: {
|
|
719
|
+
meta: {},
|
|
720
|
+
options: {
|
|
721
|
+
eventEmission: {
|
|
722
|
+
enabled: true,
|
|
723
|
+
transport: { type: "console" },
|
|
724
|
+
},
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
});
|
|
728
|
+
expect(process.listenerCount("exit")).toBe(initialExitCount + 1);
|
|
729
|
+
await plugin.context.eventEmission.close(0);
|
|
730
|
+
expect(process.listenerCount("exit")).toBe(initialExitCount);
|
|
731
|
+
});
|
|
732
|
+
it("should handle transport failures silently", async () => {
|
|
733
|
+
const failingTransport = {
|
|
734
|
+
emit: vi.fn().mockRejectedValue(new Error("Network error")),
|
|
735
|
+
close: vi.fn().mockResolvedValue(undefined),
|
|
736
|
+
};
|
|
737
|
+
vi.mocked(createTransport).mockReturnValueOnce(failingTransport);
|
|
738
|
+
const plugin = eventEmissionPlugin({
|
|
739
|
+
sdk: {},
|
|
740
|
+
context: {
|
|
741
|
+
meta: {},
|
|
742
|
+
options: {
|
|
743
|
+
eventEmission: {
|
|
744
|
+
enabled: true,
|
|
745
|
+
transport: {
|
|
746
|
+
type: "http",
|
|
747
|
+
endpoint: "https://example.com",
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
});
|
|
753
|
+
await expect(plugin.context.eventEmission.close(1)).resolves.toBeUndefined();
|
|
754
|
+
});
|
|
755
|
+
});
|
|
664
756
|
describe("Process Listener Cleanup", () => {
|
|
665
757
|
beforeEach(() => {
|
|
666
758
|
// Clean up any listeners from previous tests
|