@zapier/zapier-sdk 0.15.2 → 0.15.4
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 +12 -0
- package/dist/api/auth.d.ts +10 -0
- package/dist/api/auth.d.ts.map +1 -1
- package/dist/api/auth.js +35 -0
- package/dist/api/schemas.d.ts +38 -38
- package/dist/index.cjs +209 -27
- package/dist/index.d.mts +151 -59
- package/dist/index.mjs +209 -27
- package/dist/plugins/eventEmission/index.d.ts +1 -1
- package/dist/plugins/eventEmission/index.d.ts.map +1 -1
- package/dist/plugins/eventEmission/index.js +90 -22
- package/dist/plugins/eventEmission/index.test.js +179 -2
- package/dist/plugins/fetch/schemas.d.ts +2 -2
- package/dist/plugins/getAction/schemas.d.ts +2 -2
- package/dist/plugins/getInputFieldsSchema/schemas.d.ts +2 -2
- package/dist/plugins/listActions/index.test.js +25 -0
- package/dist/plugins/listActions/schemas.d.ts +2 -2
- package/dist/plugins/listAuthentications/index.test.js +20 -0
- package/dist/plugins/listInputFieldChoices/schemas.d.ts +6 -6
- package/dist/plugins/listInputFields/schemas.d.ts +6 -6
- package/dist/plugins/manifest/index.d.ts +42 -3
- package/dist/plugins/manifest/index.d.ts.map +1 -1
- package/dist/plugins/manifest/index.js +68 -1
- package/dist/plugins/manifest/index.test.js +513 -1
- package/dist/plugins/manifest/schemas.d.ts +75 -2
- package/dist/plugins/manifest/schemas.d.ts.map +1 -1
- package/dist/plugins/manifest/schemas.js +27 -3
- package/dist/plugins/request/schemas.d.ts +4 -4
- package/dist/plugins/runAction/schemas.d.ts +6 -6
- package/dist/schemas/Action.d.ts +1 -1
- package/dist/schemas/Auth.d.ts +6 -6
- package/dist/sdk.d.ts +23 -1
- package/dist/sdk.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2699,6 +2699,17 @@ async function readFile(filePath) {
|
|
|
2699
2699
|
throw new Error(`File not found: ${filePath}`);
|
|
2700
2700
|
}
|
|
2701
2701
|
var DEFAULT_CONFIG_PATH = ".zapierrc";
|
|
2702
|
+
var ActionEntrySchema = z.object({
|
|
2703
|
+
appKey: z.string().describe("App key (slug or implementation name)"),
|
|
2704
|
+
actionKey: z.string().describe("Action key identifier"),
|
|
2705
|
+
actionType: z.string().describe("Action type (e.g., 'read', 'write', 'search')"),
|
|
2706
|
+
authenticationId: z.number().nullable().optional().describe("Authentication ID used"),
|
|
2707
|
+
inputs: z.record(z.unknown()).optional().describe("Resolved input values"),
|
|
2708
|
+
schema: z.record(z.unknown()).describe(
|
|
2709
|
+
"Complete JSON Schema from getInputFieldsSchema (includes $schema, type, properties, required, etc.)"
|
|
2710
|
+
),
|
|
2711
|
+
createdAt: z.string().describe("ISO 8601 timestamp when created")
|
|
2712
|
+
});
|
|
2702
2713
|
var ManifestSchema = z.object({
|
|
2703
2714
|
apps: z.record(
|
|
2704
2715
|
z.string(),
|
|
@@ -2708,8 +2719,9 @@ var ManifestSchema = z.object({
|
|
|
2708
2719
|
),
|
|
2709
2720
|
version: z.string().describe("Version string (e.g., '1.21.1')")
|
|
2710
2721
|
})
|
|
2711
|
-
)
|
|
2712
|
-
|
|
2722
|
+
),
|
|
2723
|
+
actions: z.record(z.string(), ActionEntrySchema).optional().describe("Saved action configurations with their schemas")
|
|
2724
|
+
}).describe("Manifest for app version locking and action configurations");
|
|
2713
2725
|
z.object({
|
|
2714
2726
|
manifestPath: z.string().optional().describe("Path to manifest file"),
|
|
2715
2727
|
manifest: z.record(
|
|
@@ -2980,7 +2992,81 @@ var manifestPlugin = (params) => {
|
|
|
2980
2992
|
await writeManifestToFile(updatedManifest, configPath);
|
|
2981
2993
|
resolvedManifest = void 0;
|
|
2982
2994
|
}
|
|
2983
|
-
return
|
|
2995
|
+
return {
|
|
2996
|
+
key: manifestKey,
|
|
2997
|
+
entry,
|
|
2998
|
+
manifest: updatedManifest
|
|
2999
|
+
};
|
|
3000
|
+
};
|
|
3001
|
+
const addActionEntry = async (options2) => {
|
|
3002
|
+
const {
|
|
3003
|
+
name,
|
|
3004
|
+
entry,
|
|
3005
|
+
configPath = DEFAULT_CONFIG_PATH,
|
|
3006
|
+
skipWrite = false,
|
|
3007
|
+
manifest: inputManifest
|
|
3008
|
+
} = options2;
|
|
3009
|
+
const manifest2 = inputManifest || await readManifestFromFile(configPath) || { apps: {} };
|
|
3010
|
+
const actions = manifest2.actions || {};
|
|
3011
|
+
if (actions[name] && !skipWrite) {
|
|
3012
|
+
throw new Error(
|
|
3013
|
+
`Action "${name}" already exists. Please choose a different name or remove the existing action first.`
|
|
3014
|
+
);
|
|
3015
|
+
}
|
|
3016
|
+
const updatedManifest = {
|
|
3017
|
+
...manifest2,
|
|
3018
|
+
actions: {
|
|
3019
|
+
...actions,
|
|
3020
|
+
[name]: entry
|
|
3021
|
+
}
|
|
3022
|
+
};
|
|
3023
|
+
if (!skipWrite) {
|
|
3024
|
+
await writeManifestToFile(updatedManifest, configPath);
|
|
3025
|
+
resolvedManifest = void 0;
|
|
3026
|
+
}
|
|
3027
|
+
return {
|
|
3028
|
+
name,
|
|
3029
|
+
entry,
|
|
3030
|
+
manifest: updatedManifest
|
|
3031
|
+
};
|
|
3032
|
+
};
|
|
3033
|
+
const findActionEntry = ({
|
|
3034
|
+
name,
|
|
3035
|
+
manifest: manifest2
|
|
3036
|
+
}) => {
|
|
3037
|
+
return manifest2.actions?.[name] || null;
|
|
3038
|
+
};
|
|
3039
|
+
const listActionEntries = async ({
|
|
3040
|
+
configPath = DEFAULT_CONFIG_PATH
|
|
3041
|
+
} = {}) => {
|
|
3042
|
+
const manifest2 = await readManifestFromFile(configPath) || { };
|
|
3043
|
+
return Object.entries(manifest2.actions || {});
|
|
3044
|
+
};
|
|
3045
|
+
const deleteActionEntry = async ({
|
|
3046
|
+
name,
|
|
3047
|
+
configPath = DEFAULT_CONFIG_PATH,
|
|
3048
|
+
skipWrite = false
|
|
3049
|
+
}) => {
|
|
3050
|
+
const manifest2 = await readManifestFromFile(configPath) || { apps: {} };
|
|
3051
|
+
if (!manifest2.actions?.[name]) {
|
|
3052
|
+
throw new Error(`Action "${name}" does not exist.`);
|
|
3053
|
+
}
|
|
3054
|
+
const { [name]: removed, ...remainingActions } = manifest2.actions;
|
|
3055
|
+
const updatedManifest = {
|
|
3056
|
+
...manifest2,
|
|
3057
|
+
actions: remainingActions
|
|
3058
|
+
};
|
|
3059
|
+
if (!skipWrite) {
|
|
3060
|
+
await writeManifestToFile(updatedManifest, configPath);
|
|
3061
|
+
resolvedManifest = void 0;
|
|
3062
|
+
}
|
|
3063
|
+
return updatedManifest;
|
|
3064
|
+
};
|
|
3065
|
+
const hasActionEntry = ({
|
|
3066
|
+
name,
|
|
3067
|
+
manifest: manifest2
|
|
3068
|
+
}) => {
|
|
3069
|
+
return !!manifest2.actions?.[name];
|
|
2984
3070
|
};
|
|
2985
3071
|
return {
|
|
2986
3072
|
context: {
|
|
@@ -2990,7 +3076,14 @@ var manifestPlugin = (params) => {
|
|
|
2990
3076
|
api,
|
|
2991
3077
|
manifest: await getResolvedManifest() ?? { apps: {} }
|
|
2992
3078
|
}),
|
|
2993
|
-
updateManifestEntry
|
|
3079
|
+
updateManifestEntry,
|
|
3080
|
+
addActionEntry,
|
|
3081
|
+
findActionEntry,
|
|
3082
|
+
listActionEntries,
|
|
3083
|
+
deleteActionEntry,
|
|
3084
|
+
hasActionEntry,
|
|
3085
|
+
findManifestEntry,
|
|
3086
|
+
readManifestFromFile
|
|
2994
3087
|
}
|
|
2995
3088
|
};
|
|
2996
3089
|
};
|
|
@@ -3084,6 +3177,34 @@ function getAuthorizationHeader(token) {
|
|
|
3084
3177
|
}
|
|
3085
3178
|
return `Bearer ${token}`;
|
|
3086
3179
|
}
|
|
3180
|
+
function extractUserIdsFromJwt(token) {
|
|
3181
|
+
try {
|
|
3182
|
+
const parts = token.split(".");
|
|
3183
|
+
if (parts.length !== 3) {
|
|
3184
|
+
return { customuser_id: null, account_id: null };
|
|
3185
|
+
}
|
|
3186
|
+
const payload = JSON.parse(
|
|
3187
|
+
Buffer.from(parts[1], "base64url").toString("utf-8")
|
|
3188
|
+
);
|
|
3189
|
+
let actualPayload = payload;
|
|
3190
|
+
if (payload.sub_type === "service" && payload.njwt) {
|
|
3191
|
+
const nestedParts = payload.njwt.split(".");
|
|
3192
|
+
if (nestedParts.length === 3) {
|
|
3193
|
+
actualPayload = JSON.parse(
|
|
3194
|
+
Buffer.from(nestedParts[1], "base64url").toString("utf-8")
|
|
3195
|
+
);
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
const accountId = actualPayload["zap:acc"] != null ? parseInt(String(actualPayload["zap:acc"]), 10) : null;
|
|
3199
|
+
const customUserId = actualPayload.sub_type === "customuser" && actualPayload.sub != null ? parseInt(String(actualPayload.sub), 10) : null;
|
|
3200
|
+
return {
|
|
3201
|
+
customuser_id: customUserId !== null && !isNaN(customUserId) ? customUserId : null,
|
|
3202
|
+
account_id: accountId !== null && !isNaN(accountId) ? accountId : null
|
|
3203
|
+
};
|
|
3204
|
+
} catch {
|
|
3205
|
+
return { customuser_id: null, account_id: null };
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3087
3208
|
|
|
3088
3209
|
// src/api/debug.ts
|
|
3089
3210
|
var utilModule = null;
|
|
@@ -4480,7 +4601,7 @@ function getCpuTime() {
|
|
|
4480
4601
|
|
|
4481
4602
|
// package.json
|
|
4482
4603
|
var package_default = {
|
|
4483
|
-
version: "0.15.
|
|
4604
|
+
version: "0.15.4"};
|
|
4484
4605
|
|
|
4485
4606
|
// src/plugins/eventEmission/builders.ts
|
|
4486
4607
|
function createBaseEvent(context = {}) {
|
|
@@ -4551,17 +4672,26 @@ function buildErrorEventWithContext(data, context = {}) {
|
|
|
4551
4672
|
}
|
|
4552
4673
|
|
|
4553
4674
|
// src/plugins/eventEmission/index.ts
|
|
4675
|
+
var TELEMETRY_EMIT_TIMEOUT_MS = 300;
|
|
4554
4676
|
var APPLICATION_LIFECYCLE_EVENT_SUBJECT = "platform.sdk.ApplicationLifecycleEvent";
|
|
4555
4677
|
var ERROR_OCCURRED_EVENT_SUBJECT = "platform.sdk.ErrorOccurredEvent";
|
|
4556
4678
|
var transportStates = /* @__PURE__ */ new WeakMap();
|
|
4557
|
-
async function silentEmit(transport, subject, event) {
|
|
4679
|
+
async function silentEmit(transport, subject, event, userContextPromise) {
|
|
4558
4680
|
try {
|
|
4559
4681
|
let state = transportStates.get(transport);
|
|
4560
4682
|
if (!state) {
|
|
4561
4683
|
state = { hasWorked: false, hasLoggedFailure: false };
|
|
4562
4684
|
transportStates.set(transport, state);
|
|
4563
4685
|
}
|
|
4564
|
-
|
|
4686
|
+
let enrichedEvent = event;
|
|
4687
|
+
if (userContextPromise) {
|
|
4688
|
+
try {
|
|
4689
|
+
const userContext = await userContextPromise;
|
|
4690
|
+
enrichedEvent = Object.assign({}, event, userContext);
|
|
4691
|
+
} catch {
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
transport.emit(subject, enrichedEvent).then(() => {
|
|
4565
4695
|
state.hasWorked = true;
|
|
4566
4696
|
}).catch((error) => {
|
|
4567
4697
|
if (!state.hasWorked && !state.hasLoggedFailure) {
|
|
@@ -4609,6 +4739,19 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4609
4739
|
)
|
|
4610
4740
|
)
|
|
4611
4741
|
};
|
|
4742
|
+
const getUserContext = (async () => {
|
|
4743
|
+
try {
|
|
4744
|
+
const { getToken } = await import('@zapier/zapier-sdk-cli-login');
|
|
4745
|
+
const token = await getToken({
|
|
4746
|
+
baseUrl: context.options.baseUrl
|
|
4747
|
+
});
|
|
4748
|
+
if (token) {
|
|
4749
|
+
return extractUserIdsFromJwt(token);
|
|
4750
|
+
}
|
|
4751
|
+
} catch {
|
|
4752
|
+
}
|
|
4753
|
+
return { customuser_id: null, account_id: null };
|
|
4754
|
+
})();
|
|
4612
4755
|
const startupTime = Date.now();
|
|
4613
4756
|
let shutdownStartTime = null;
|
|
4614
4757
|
if (!config.enabled) {
|
|
@@ -4619,7 +4762,7 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4619
4762
|
config,
|
|
4620
4763
|
emit: () => {
|
|
4621
4764
|
},
|
|
4622
|
-
createBaseEvent: () => ({
|
|
4765
|
+
createBaseEvent: async () => ({
|
|
4623
4766
|
event_id: generateEventId(),
|
|
4624
4767
|
timestamp_ms: getCurrentTimestamp(),
|
|
4625
4768
|
release_id: getReleaseId(),
|
|
@@ -4639,21 +4782,34 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4639
4782
|
} catch {
|
|
4640
4783
|
transport = createTransport({ type: "noop" });
|
|
4641
4784
|
}
|
|
4642
|
-
const createBaseEventHelper = () =>
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4785
|
+
const createBaseEventHelper = async () => {
|
|
4786
|
+
const baseEvent = {
|
|
4787
|
+
event_id: generateEventId(),
|
|
4788
|
+
timestamp_ms: getCurrentTimestamp(),
|
|
4789
|
+
release_id: getReleaseId(),
|
|
4790
|
+
customuser_id: null,
|
|
4791
|
+
account_id: null,
|
|
4792
|
+
identity_id: null,
|
|
4793
|
+
visitor_id: null,
|
|
4794
|
+
correlation_id: null
|
|
4795
|
+
};
|
|
4796
|
+
try {
|
|
4797
|
+
const userContext = await getUserContext;
|
|
4798
|
+
return { ...baseEvent, ...userContext };
|
|
4799
|
+
} catch {
|
|
4800
|
+
return baseEvent;
|
|
4801
|
+
}
|
|
4802
|
+
};
|
|
4652
4803
|
if (config.enabled) {
|
|
4653
4804
|
const startupEvent = buildApplicationLifecycleEvent({
|
|
4654
4805
|
lifecycle_event_type: "startup"
|
|
4655
4806
|
});
|
|
4656
|
-
silentEmit(
|
|
4807
|
+
silentEmit(
|
|
4808
|
+
transport,
|
|
4809
|
+
APPLICATION_LIFECYCLE_EVENT_SUBJECT,
|
|
4810
|
+
startupEvent,
|
|
4811
|
+
getUserContext
|
|
4812
|
+
);
|
|
4657
4813
|
if (typeof process?.on === "function") {
|
|
4658
4814
|
process.on("exit", (code) => {
|
|
4659
4815
|
const uptime = Date.now() - startupTime;
|
|
@@ -4665,10 +4821,15 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4665
4821
|
is_graceful_shutdown: code === 0,
|
|
4666
4822
|
shutdown_duration_ms: shutdownDuration
|
|
4667
4823
|
});
|
|
4668
|
-
silentEmit(
|
|
4824
|
+
silentEmit(
|
|
4825
|
+
transport,
|
|
4826
|
+
APPLICATION_LIFECYCLE_EVENT_SUBJECT,
|
|
4827
|
+
exitEvent,
|
|
4828
|
+
getUserContext
|
|
4829
|
+
);
|
|
4669
4830
|
});
|
|
4670
4831
|
process.on("uncaughtException", async (error) => {
|
|
4671
|
-
|
|
4832
|
+
let errorEvent = buildErrorEventWithContext({
|
|
4672
4833
|
error_message: error.message || "Unknown error",
|
|
4673
4834
|
error_type: "UncaughtException",
|
|
4674
4835
|
error_stack_trace: error.stack || null,
|
|
@@ -4677,10 +4838,17 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4677
4838
|
is_recoverable: false,
|
|
4678
4839
|
execution_start_time: startupTime
|
|
4679
4840
|
});
|
|
4841
|
+
try {
|
|
4842
|
+
const userContext = await getUserContext;
|
|
4843
|
+
errorEvent = { ...errorEvent, ...userContext };
|
|
4844
|
+
} catch {
|
|
4845
|
+
}
|
|
4680
4846
|
try {
|
|
4681
4847
|
await Promise.race([
|
|
4682
4848
|
transport.emit(ERROR_OCCURRED_EVENT_SUBJECT, errorEvent),
|
|
4683
|
-
new Promise(
|
|
4849
|
+
new Promise(
|
|
4850
|
+
(resolve2) => setTimeout(resolve2, TELEMETRY_EMIT_TIMEOUT_MS)
|
|
4851
|
+
)
|
|
4684
4852
|
]);
|
|
4685
4853
|
} catch {
|
|
4686
4854
|
}
|
|
@@ -4690,7 +4858,7 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4690
4858
|
async (reason, promise) => {
|
|
4691
4859
|
const errorMessage = reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "Unhandled promise rejection";
|
|
4692
4860
|
const errorStack = reason instanceof Error ? reason.stack : null;
|
|
4693
|
-
|
|
4861
|
+
let errorEvent = buildErrorEventWithContext({
|
|
4694
4862
|
error_message: errorMessage,
|
|
4695
4863
|
error_type: "UnhandledRejection",
|
|
4696
4864
|
error_stack_trace: errorStack,
|
|
@@ -4702,10 +4870,17 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4702
4870
|
promise: String(promise)
|
|
4703
4871
|
}
|
|
4704
4872
|
});
|
|
4873
|
+
try {
|
|
4874
|
+
const userContext = await getUserContext;
|
|
4875
|
+
errorEvent = { ...errorEvent, ...userContext };
|
|
4876
|
+
} catch {
|
|
4877
|
+
}
|
|
4705
4878
|
try {
|
|
4706
4879
|
await Promise.race([
|
|
4707
4880
|
transport.emit(ERROR_OCCURRED_EVENT_SUBJECT, errorEvent),
|
|
4708
|
-
new Promise(
|
|
4881
|
+
new Promise(
|
|
4882
|
+
(resolve2) => setTimeout(resolve2, TELEMETRY_EMIT_TIMEOUT_MS)
|
|
4883
|
+
)
|
|
4709
4884
|
]);
|
|
4710
4885
|
} catch {
|
|
4711
4886
|
}
|
|
@@ -4714,16 +4889,23 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4714
4889
|
const handleSignal = async (signal) => {
|
|
4715
4890
|
shutdownStartTime = Date.now();
|
|
4716
4891
|
const uptime = Date.now() - startupTime;
|
|
4717
|
-
|
|
4892
|
+
let signalEvent = buildApplicationLifecycleEvent({
|
|
4718
4893
|
lifecycle_event_type: "signal_termination",
|
|
4719
4894
|
signal_name: signal,
|
|
4720
4895
|
uptime_ms: uptime,
|
|
4721
4896
|
is_graceful_shutdown: true
|
|
4722
4897
|
});
|
|
4898
|
+
try {
|
|
4899
|
+
const userContext = await getUserContext;
|
|
4900
|
+
signalEvent = { ...signalEvent, ...userContext };
|
|
4901
|
+
} catch {
|
|
4902
|
+
}
|
|
4723
4903
|
try {
|
|
4724
4904
|
await Promise.race([
|
|
4725
4905
|
transport.emit(APPLICATION_LIFECYCLE_EVENT_SUBJECT, signalEvent),
|
|
4726
|
-
new Promise(
|
|
4906
|
+
new Promise(
|
|
4907
|
+
(resolve2) => setTimeout(resolve2, TELEMETRY_EMIT_TIMEOUT_MS)
|
|
4908
|
+
)
|
|
4727
4909
|
]);
|
|
4728
4910
|
} catch {
|
|
4729
4911
|
}
|
|
@@ -4739,7 +4921,7 @@ var eventEmissionPlugin = ({ context }) => {
|
|
|
4739
4921
|
transport,
|
|
4740
4922
|
config,
|
|
4741
4923
|
emit: (subject, event) => {
|
|
4742
|
-
silentEmit(transport, subject, event);
|
|
4924
|
+
silentEmit(transport, subject, event, getUserContext);
|
|
4743
4925
|
},
|
|
4744
4926
|
createBaseEvent: createBaseEventHelper
|
|
4745
4927
|
}
|
|
@@ -16,7 +16,7 @@ export interface EventEmissionContext {
|
|
|
16
16
|
transport: EventTransport;
|
|
17
17
|
config: EventEmissionConfig;
|
|
18
18
|
emit<T extends any>(subject: string, event: T): void;
|
|
19
|
-
createBaseEvent(): BaseEvent
|
|
19
|
+
createBaseEvent(): Promise<BaseEvent>;
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
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;
|
|
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;AAenE,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;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;KACvC,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AA4FD,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,CAyQtB,CAAC;AAGF,YAAY,EACV,YAAY,EACZ,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,EAC1B,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,cAAc,SAAS,CAAC"}
|
|
@@ -6,14 +6,17 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { createTransport } from "./transport";
|
|
8
8
|
import { generateEventId, getCurrentTimestamp, getReleaseId } from "./utils";
|
|
9
|
+
import { extractUserIdsFromJwt } from "../../api/auth";
|
|
9
10
|
import { buildApplicationLifecycleEvent, buildErrorEventWithContext, } from "./builders";
|
|
10
11
|
import { getTrackingBaseUrl } from "../../utils/url-utils";
|
|
12
|
+
// Maximum time to wait for telemetry emission before allowing process to exit
|
|
13
|
+
const TELEMETRY_EMIT_TIMEOUT_MS = 300;
|
|
11
14
|
const APPLICATION_LIFECYCLE_EVENT_SUBJECT = "platform.sdk.ApplicationLifecycleEvent";
|
|
12
15
|
const ERROR_OCCURRED_EVENT_SUBJECT = "platform.sdk.ErrorOccurredEvent";
|
|
13
16
|
// Track transport success/failure so we only log failure once.
|
|
14
17
|
const transportStates = new WeakMap();
|
|
15
18
|
// Silent emission wrapper with smart first-failure logging
|
|
16
|
-
async function silentEmit(transport, subject, event) {
|
|
19
|
+
async function silentEmit(transport, subject, event, userContextPromise) {
|
|
17
20
|
try {
|
|
18
21
|
// Get or initialize state for this transport
|
|
19
22
|
let state = transportStates.get(transport);
|
|
@@ -21,9 +24,21 @@ async function silentEmit(transport, subject, event) {
|
|
|
21
24
|
state = { hasWorked: false, hasLoggedFailure: false };
|
|
22
25
|
transportStates.set(transport, state);
|
|
23
26
|
}
|
|
27
|
+
// Resolve user context and merge into event
|
|
28
|
+
let enrichedEvent = event;
|
|
29
|
+
if (userContextPromise) {
|
|
30
|
+
try {
|
|
31
|
+
const userContext = await userContextPromise;
|
|
32
|
+
// Use Object.assign to safely merge user context into event
|
|
33
|
+
enrichedEvent = Object.assign({}, event, userContext);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// If user context promise fails, continue with original event
|
|
37
|
+
}
|
|
38
|
+
}
|
|
24
39
|
// Fire and forget - don't await the transport
|
|
25
40
|
transport
|
|
26
|
-
.emit(subject,
|
|
41
|
+
.emit(subject, enrichedEvent)
|
|
27
42
|
.then(() => {
|
|
28
43
|
// Mark as working if any emit succeeds
|
|
29
44
|
state.hasWorked = true;
|
|
@@ -76,6 +91,24 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
76
91
|
: // Otherwise, use option transport or default
|
|
77
92
|
(context.options.eventEmission?.transport ?? defaultTransport),
|
|
78
93
|
};
|
|
94
|
+
// Create getUserContext promise for dynamic user context injection
|
|
95
|
+
const getUserContext = (async () => {
|
|
96
|
+
try {
|
|
97
|
+
// Dynamically import the CLI login package if available
|
|
98
|
+
const { getToken } = await import("@zapier/zapier-sdk-cli-login");
|
|
99
|
+
// Pass baseUrl for potential token refresh operations
|
|
100
|
+
const token = await getToken({
|
|
101
|
+
baseUrl: context.options.baseUrl,
|
|
102
|
+
});
|
|
103
|
+
if (token) {
|
|
104
|
+
return extractUserIdsFromJwt(token);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// CLI login package not available or getToken failed, fall back to null context
|
|
109
|
+
}
|
|
110
|
+
return { customuser_id: null, account_id: null };
|
|
111
|
+
})();
|
|
79
112
|
const startupTime = Date.now();
|
|
80
113
|
let shutdownStartTime = null;
|
|
81
114
|
// If disabled, return noop implementations
|
|
@@ -86,7 +119,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
86
119
|
transport: createTransport({ type: "noop" }),
|
|
87
120
|
config,
|
|
88
121
|
emit: () => { },
|
|
89
|
-
createBaseEvent: () => ({
|
|
122
|
+
createBaseEvent: async () => ({
|
|
90
123
|
event_id: generateEventId(),
|
|
91
124
|
timestamp_ms: getCurrentTimestamp(),
|
|
92
125
|
release_id: getReleaseId(),
|
|
@@ -109,23 +142,34 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
109
142
|
transport = createTransport({ type: "noop" });
|
|
110
143
|
}
|
|
111
144
|
// Helper to create base event
|
|
112
|
-
const createBaseEventHelper = () =>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
145
|
+
const createBaseEventHelper = async () => {
|
|
146
|
+
const baseEvent = {
|
|
147
|
+
event_id: generateEventId(),
|
|
148
|
+
timestamp_ms: getCurrentTimestamp(),
|
|
149
|
+
release_id: getReleaseId(),
|
|
150
|
+
customuser_id: null,
|
|
151
|
+
account_id: null,
|
|
152
|
+
identity_id: null,
|
|
153
|
+
visitor_id: null,
|
|
154
|
+
correlation_id: null,
|
|
155
|
+
};
|
|
156
|
+
// Enrich with user context if available
|
|
157
|
+
try {
|
|
158
|
+
const userContext = await getUserContext;
|
|
159
|
+
return { ...baseEvent, ...userContext };
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Return base event if user context fails
|
|
163
|
+
return baseEvent;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
122
166
|
// Register lifecycle event handlers if enabled
|
|
123
167
|
if (config.enabled) {
|
|
124
168
|
// Emit startup event
|
|
125
169
|
const startupEvent = buildApplicationLifecycleEvent({
|
|
126
170
|
lifecycle_event_type: "startup",
|
|
127
171
|
});
|
|
128
|
-
silentEmit(transport, APPLICATION_LIFECYCLE_EVENT_SUBJECT, startupEvent);
|
|
172
|
+
silentEmit(transport, APPLICATION_LIFECYCLE_EVENT_SUBJECT, startupEvent, getUserContext);
|
|
129
173
|
// Register process event handlers (Node.js only)
|
|
130
174
|
if (typeof process?.on === "function") {
|
|
131
175
|
// Handle normal process exit
|
|
@@ -141,11 +185,11 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
141
185
|
is_graceful_shutdown: code === 0,
|
|
142
186
|
shutdown_duration_ms: shutdownDuration,
|
|
143
187
|
});
|
|
144
|
-
silentEmit(transport, APPLICATION_LIFECYCLE_EVENT_SUBJECT, exitEvent);
|
|
188
|
+
silentEmit(transport, APPLICATION_LIFECYCLE_EVENT_SUBJECT, exitEvent, getUserContext);
|
|
145
189
|
});
|
|
146
190
|
// Handle uncaught exceptions
|
|
147
191
|
process.on("uncaughtException", async (error) => {
|
|
148
|
-
|
|
192
|
+
let errorEvent = buildErrorEventWithContext({
|
|
149
193
|
error_message: error.message || "Unknown error",
|
|
150
194
|
error_type: "UncaughtException",
|
|
151
195
|
error_stack_trace: error.stack || null,
|
|
@@ -154,11 +198,19 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
154
198
|
is_recoverable: false,
|
|
155
199
|
execution_start_time: startupTime,
|
|
156
200
|
});
|
|
201
|
+
// Enrich with user context if available
|
|
202
|
+
try {
|
|
203
|
+
const userContext = await getUserContext;
|
|
204
|
+
errorEvent = { ...errorEvent, ...userContext };
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// Continue with original event if user context fails
|
|
208
|
+
}
|
|
157
209
|
// Wait up to 300ms for telemetry to send before allowing process to exit
|
|
158
210
|
try {
|
|
159
211
|
await Promise.race([
|
|
160
212
|
transport.emit(ERROR_OCCURRED_EVENT_SUBJECT, errorEvent),
|
|
161
|
-
new Promise((resolve) => setTimeout(resolve,
|
|
213
|
+
new Promise((resolve) => setTimeout(resolve, TELEMETRY_EMIT_TIMEOUT_MS)),
|
|
162
214
|
]);
|
|
163
215
|
}
|
|
164
216
|
catch {
|
|
@@ -174,7 +226,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
174
226
|
? reason
|
|
175
227
|
: "Unhandled promise rejection";
|
|
176
228
|
const errorStack = reason instanceof Error ? reason.stack : null;
|
|
177
|
-
|
|
229
|
+
let errorEvent = buildErrorEventWithContext({
|
|
178
230
|
error_message: errorMessage,
|
|
179
231
|
error_type: "UnhandledRejection",
|
|
180
232
|
error_stack_trace: errorStack,
|
|
@@ -186,11 +238,19 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
186
238
|
promise: String(promise),
|
|
187
239
|
},
|
|
188
240
|
});
|
|
241
|
+
// Enrich with user context if available
|
|
242
|
+
try {
|
|
243
|
+
const userContext = await getUserContext;
|
|
244
|
+
errorEvent = { ...errorEvent, ...userContext };
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Continue with original event if user context fails
|
|
248
|
+
}
|
|
189
249
|
// Wait up to 300ms for telemetry to send
|
|
190
250
|
try {
|
|
191
251
|
await Promise.race([
|
|
192
252
|
transport.emit(ERROR_OCCURRED_EVENT_SUBJECT, errorEvent),
|
|
193
|
-
new Promise((resolve) => setTimeout(resolve,
|
|
253
|
+
new Promise((resolve) => setTimeout(resolve, TELEMETRY_EMIT_TIMEOUT_MS)),
|
|
194
254
|
]);
|
|
195
255
|
}
|
|
196
256
|
catch {
|
|
@@ -201,17 +261,25 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
201
261
|
const handleSignal = async (signal) => {
|
|
202
262
|
shutdownStartTime = Date.now();
|
|
203
263
|
const uptime = Date.now() - startupTime;
|
|
204
|
-
|
|
264
|
+
let signalEvent = buildApplicationLifecycleEvent({
|
|
205
265
|
lifecycle_event_type: "signal_termination",
|
|
206
266
|
signal_name: signal,
|
|
207
267
|
uptime_ms: uptime,
|
|
208
268
|
is_graceful_shutdown: true,
|
|
209
269
|
});
|
|
270
|
+
// Enrich with user context if available
|
|
271
|
+
try {
|
|
272
|
+
const userContext = await getUserContext;
|
|
273
|
+
signalEvent = { ...signalEvent, ...userContext };
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
// Continue with original event if user context fails
|
|
277
|
+
}
|
|
210
278
|
// Wait up to 300ms for telemetry to send
|
|
211
279
|
try {
|
|
212
280
|
await Promise.race([
|
|
213
281
|
transport.emit(APPLICATION_LIFECYCLE_EVENT_SUBJECT, signalEvent),
|
|
214
|
-
new Promise((resolve) => setTimeout(resolve,
|
|
282
|
+
new Promise((resolve) => setTimeout(resolve, TELEMETRY_EMIT_TIMEOUT_MS)),
|
|
215
283
|
]);
|
|
216
284
|
}
|
|
217
285
|
catch {
|
|
@@ -231,7 +299,7 @@ export const eventEmissionPlugin = ({ context }) => {
|
|
|
231
299
|
transport,
|
|
232
300
|
config,
|
|
233
301
|
emit: (subject, event) => {
|
|
234
|
-
silentEmit(transport, subject, event);
|
|
302
|
+
silentEmit(transport, subject, event, getUserContext);
|
|
235
303
|
},
|
|
236
304
|
createBaseEvent: createBaseEventHelper,
|
|
237
305
|
},
|