skedyul 0.2.69 → 0.2.71
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/.build-stamp +1 -1
- package/dist/config.d.ts +5 -2
- package/dist/server.js +144 -78
- package/package.json +1 -1
package/dist/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1769638280655
|
package/dist/config.d.ts
CHANGED
|
@@ -602,9 +602,12 @@ export interface PageDefinition {
|
|
|
602
602
|
export type WebhookHttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
603
603
|
export interface WebhookRequest {
|
|
604
604
|
method: string;
|
|
605
|
-
|
|
606
|
-
|
|
605
|
+
url: string;
|
|
606
|
+
path: string;
|
|
607
|
+
headers: Record<string, string | string[] | undefined>;
|
|
607
608
|
query: Record<string, string>;
|
|
609
|
+
body: unknown;
|
|
610
|
+
rawBody?: Buffer;
|
|
608
611
|
}
|
|
609
612
|
export interface WebhookHandlerContext {
|
|
610
613
|
appInstallationId: string | null;
|
package/dist/server.js
CHANGED
|
@@ -679,38 +679,69 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
679
679
|
else {
|
|
680
680
|
parsedBody = rawBody;
|
|
681
681
|
}
|
|
682
|
-
//
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
};
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
682
|
+
// Check if this is an envelope format from the platform
|
|
683
|
+
// Envelope format: { env: {...}, request: {...}, context: {...} }
|
|
684
|
+
const isEnvelope = (typeof parsedBody === 'object' &&
|
|
685
|
+
parsedBody !== null &&
|
|
686
|
+
'env' in parsedBody &&
|
|
687
|
+
'request' in parsedBody &&
|
|
688
|
+
'context' in parsedBody);
|
|
689
|
+
let webhookRequest;
|
|
690
|
+
let webhookContext;
|
|
691
|
+
let requestEnv = {};
|
|
692
|
+
if (isEnvelope) {
|
|
693
|
+
// Platform envelope format - extract env, request, and context
|
|
694
|
+
const envelope = parsedBody;
|
|
695
|
+
requestEnv = envelope.env ?? {};
|
|
696
|
+
// Parse the original request body
|
|
697
|
+
let originalParsedBody = envelope.request.body;
|
|
698
|
+
const originalContentType = envelope.request.headers['content-type'] ?? '';
|
|
699
|
+
if (originalContentType.includes('application/json')) {
|
|
700
|
+
try {
|
|
701
|
+
originalParsedBody = envelope.request.body ? JSON.parse(envelope.request.body) : {};
|
|
702
|
+
}
|
|
703
|
+
catch {
|
|
704
|
+
// Keep as string if JSON parsing fails
|
|
705
|
+
}
|
|
705
706
|
}
|
|
707
|
+
webhookRequest = {
|
|
708
|
+
method: envelope.request.method,
|
|
709
|
+
url: envelope.request.url,
|
|
710
|
+
path: envelope.request.path,
|
|
711
|
+
headers: envelope.request.headers,
|
|
712
|
+
query: envelope.request.query,
|
|
713
|
+
body: originalParsedBody,
|
|
714
|
+
rawBody: envelope.request.body ? Buffer.from(envelope.request.body, 'utf-8') : undefined,
|
|
715
|
+
};
|
|
716
|
+
webhookContext = {
|
|
717
|
+
env: { ...process.env, ...requestEnv },
|
|
718
|
+
appInstallationId: envelope.context.appInstallationId,
|
|
719
|
+
workplace: envelope.context.workplace,
|
|
720
|
+
registration: envelope.context.registration ?? {},
|
|
721
|
+
};
|
|
706
722
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
723
|
+
else {
|
|
724
|
+
// Direct request format (legacy or direct calls)
|
|
725
|
+
webhookRequest = {
|
|
726
|
+
method: req.method ?? 'POST',
|
|
727
|
+
url: url.toString(),
|
|
728
|
+
path: pathname,
|
|
729
|
+
headers: req.headers,
|
|
730
|
+
query: Object.fromEntries(url.searchParams.entries()),
|
|
731
|
+
body: parsedBody,
|
|
732
|
+
rawBody: rawBody ? Buffer.from(rawBody, 'utf-8') : undefined,
|
|
733
|
+
};
|
|
734
|
+
webhookContext = {
|
|
735
|
+
env: process.env,
|
|
736
|
+
appInstallationId: null,
|
|
737
|
+
workplace: null,
|
|
738
|
+
registration: {},
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
// Temporarily inject env into process.env for skedyul client to use
|
|
742
|
+
// (same pattern as tool handler)
|
|
743
|
+
const originalEnv = { ...process.env };
|
|
744
|
+
Object.assign(process.env, requestEnv);
|
|
714
745
|
// Invoke the handler
|
|
715
746
|
let webhookResponse;
|
|
716
747
|
try {
|
|
@@ -721,6 +752,10 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
721
752
|
sendJSON(res, 500, { error: 'Webhook handler error' });
|
|
722
753
|
return;
|
|
723
754
|
}
|
|
755
|
+
finally {
|
|
756
|
+
// Restore original env
|
|
757
|
+
process.env = originalEnv;
|
|
758
|
+
}
|
|
724
759
|
// Send response
|
|
725
760
|
const status = webhookResponse.status ?? 200;
|
|
726
761
|
const responseHeaders = {
|
|
@@ -826,8 +861,8 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
826
861
|
key,
|
|
827
862
|
typeof value === 'string' ? value : value?.[0] ?? '',
|
|
828
863
|
]));
|
|
829
|
-
const
|
|
830
|
-
method: req.method,
|
|
864
|
+
const coreWebhookRequest = {
|
|
865
|
+
method: req.method ?? 'POST',
|
|
831
866
|
headers: normalizedHeaders,
|
|
832
867
|
body: webhookBody,
|
|
833
868
|
query: Object.fromEntries(url.searchParams.entries()),
|
|
@@ -837,7 +872,7 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
|
|
|
837
872
|
? Buffer.from(rawWebhookBody, 'utf-8')
|
|
838
873
|
: undefined,
|
|
839
874
|
};
|
|
840
|
-
const webhookResponse = await service_1.coreApiService.dispatchWebhook(
|
|
875
|
+
const webhookResponse = await service_1.coreApiService.dispatchWebhook(coreWebhookRequest);
|
|
841
876
|
res.writeHead(webhookResponse.status, {
|
|
842
877
|
'Content-Type': 'application/json',
|
|
843
878
|
});
|
|
@@ -965,50 +1000,77 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
|
|
|
965
1000
|
else {
|
|
966
1001
|
parsedBody = rawBody;
|
|
967
1002
|
}
|
|
968
|
-
//
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
const registrationContextHeader = event.headers?.['x-skedyul-registration-context'] ??
|
|
993
|
-
event.headers?.['X-Skedyul-Registration-Context'];
|
|
994
|
-
// Parse registration context from base64-encoded header
|
|
995
|
-
let registrationContext = {};
|
|
996
|
-
if (registrationContextHeader) {
|
|
997
|
-
try {
|
|
998
|
-
const decoded = Buffer.from(registrationContextHeader, 'base64').toString('utf-8');
|
|
999
|
-
registrationContext = JSON.parse(decoded);
|
|
1000
|
-
}
|
|
1001
|
-
catch {
|
|
1002
|
-
console.warn('Failed to parse X-Skedyul-Registration-Context header');
|
|
1003
|
+
// Check if this is an envelope format from the platform
|
|
1004
|
+
// Envelope format: { env: {...}, request: {...}, context: {...} }
|
|
1005
|
+
const isEnvelope = (typeof parsedBody === 'object' &&
|
|
1006
|
+
parsedBody !== null &&
|
|
1007
|
+
'env' in parsedBody &&
|
|
1008
|
+
'request' in parsedBody &&
|
|
1009
|
+
'context' in parsedBody);
|
|
1010
|
+
let webhookRequest;
|
|
1011
|
+
let webhookContext;
|
|
1012
|
+
let requestEnv = {};
|
|
1013
|
+
if (isEnvelope) {
|
|
1014
|
+
// Platform envelope format - extract env, request, and context
|
|
1015
|
+
const envelope = parsedBody;
|
|
1016
|
+
requestEnv = envelope.env ?? {};
|
|
1017
|
+
// Parse the original request body
|
|
1018
|
+
let originalParsedBody = envelope.request.body;
|
|
1019
|
+
const originalContentType = envelope.request.headers['content-type'] ?? '';
|
|
1020
|
+
if (originalContentType.includes('application/json')) {
|
|
1021
|
+
try {
|
|
1022
|
+
originalParsedBody = envelope.request.body ? JSON.parse(envelope.request.body) : {};
|
|
1023
|
+
}
|
|
1024
|
+
catch {
|
|
1025
|
+
// Keep as string if JSON parsing fails
|
|
1026
|
+
}
|
|
1003
1027
|
}
|
|
1028
|
+
webhookRequest = {
|
|
1029
|
+
method: envelope.request.method,
|
|
1030
|
+
url: envelope.request.url,
|
|
1031
|
+
path: envelope.request.path,
|
|
1032
|
+
headers: envelope.request.headers,
|
|
1033
|
+
query: envelope.request.query,
|
|
1034
|
+
body: originalParsedBody,
|
|
1035
|
+
rawBody: envelope.request.body ? Buffer.from(envelope.request.body, 'utf-8') : undefined,
|
|
1036
|
+
};
|
|
1037
|
+
webhookContext = {
|
|
1038
|
+
env: { ...process.env, ...requestEnv },
|
|
1039
|
+
appInstallationId: envelope.context.appInstallationId,
|
|
1040
|
+
workplace: envelope.context.workplace,
|
|
1041
|
+
registration: envelope.context.registration ?? {},
|
|
1042
|
+
};
|
|
1004
1043
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1044
|
+
else {
|
|
1045
|
+
// Direct request format (legacy or direct calls)
|
|
1046
|
+
const forwardedProto = event.headers?.['x-forwarded-proto'] ??
|
|
1047
|
+
event.headers?.['X-Forwarded-Proto'];
|
|
1048
|
+
const protocol = forwardedProto ?? 'https';
|
|
1049
|
+
const host = event.headers?.host ?? event.headers?.Host ?? 'localhost';
|
|
1050
|
+
const queryString = event.queryStringParameters
|
|
1051
|
+
? '?' + new URLSearchParams(event.queryStringParameters).toString()
|
|
1052
|
+
: '';
|
|
1053
|
+
const webhookUrl = `${protocol}://${host}${path}${queryString}`;
|
|
1054
|
+
webhookRequest = {
|
|
1055
|
+
method,
|
|
1056
|
+
url: webhookUrl,
|
|
1057
|
+
path,
|
|
1058
|
+
headers: event.headers,
|
|
1059
|
+
query: event.queryStringParameters ?? {},
|
|
1060
|
+
body: parsedBody,
|
|
1061
|
+
rawBody: rawBody ? Buffer.from(rawBody, 'utf-8') : undefined,
|
|
1062
|
+
};
|
|
1063
|
+
webhookContext = {
|
|
1064
|
+
env: process.env,
|
|
1065
|
+
appInstallationId: null,
|
|
1066
|
+
workplace: null,
|
|
1067
|
+
registration: {},
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
// Temporarily inject env into process.env for skedyul client to use
|
|
1071
|
+
// (same pattern as tool handler)
|
|
1072
|
+
const originalEnv = { ...process.env };
|
|
1073
|
+
Object.assign(process.env, requestEnv);
|
|
1012
1074
|
// Invoke the handler
|
|
1013
1075
|
let webhookResponse;
|
|
1014
1076
|
try {
|
|
@@ -1018,6 +1080,10 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
|
|
|
1018
1080
|
console.error(`Webhook handler '${handle}' error:`, err);
|
|
1019
1081
|
return createResponse(500, { error: 'Webhook handler error' }, headers);
|
|
1020
1082
|
}
|
|
1083
|
+
finally {
|
|
1084
|
+
// Restore original env
|
|
1085
|
+
process.env = originalEnv;
|
|
1086
|
+
}
|
|
1021
1087
|
// Build response headers
|
|
1022
1088
|
const responseHeaders = {
|
|
1023
1089
|
...headers,
|
|
@@ -1072,9 +1138,9 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
|
|
|
1072
1138
|
const protocol = forwardedProto ?? 'https';
|
|
1073
1139
|
const host = event.headers?.host ?? event.headers?.Host ?? 'localhost';
|
|
1074
1140
|
const webhookUrl = `${protocol}://${host}${event.path}`;
|
|
1075
|
-
const
|
|
1141
|
+
const coreWebhookRequest = {
|
|
1076
1142
|
method,
|
|
1077
|
-
headers: event.headers ?? {},
|
|
1143
|
+
headers: (event.headers ?? {}),
|
|
1078
1144
|
body: webhookBody,
|
|
1079
1145
|
query: event.queryStringParameters ?? {},
|
|
1080
1146
|
url: webhookUrl,
|
|
@@ -1083,7 +1149,7 @@ function createServerlessInstance(config, tools, callTool, state, mcpServer, reg
|
|
|
1083
1149
|
? Buffer.from(rawWebhookBody, 'utf-8')
|
|
1084
1150
|
: undefined,
|
|
1085
1151
|
};
|
|
1086
|
-
const webhookResponse = await service_1.coreApiService.dispatchWebhook(
|
|
1152
|
+
const webhookResponse = await service_1.coreApiService.dispatchWebhook(coreWebhookRequest);
|
|
1087
1153
|
return createResponse(webhookResponse.status, webhookResponse.body ?? {}, headers);
|
|
1088
1154
|
}
|
|
1089
1155
|
if (path === '/estimate' && method === 'POST') {
|