patchwork-os 0.2.0-alpha.35 → 0.2.0-alpha.37
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/README.md +70 -15
- package/dist/activityLog.d.ts +49 -0
- package/dist/activityLog.js +78 -0
- package/dist/activityLog.js.map +1 -1
- package/dist/approvalHttp.d.ts +25 -0
- package/dist/approvalHttp.js +74 -18
- package/dist/approvalHttp.js.map +1 -1
- package/dist/approvalInsights.d.ts +49 -0
- package/dist/approvalInsights.js +97 -0
- package/dist/approvalInsights.js.map +1 -0
- package/dist/approvalQueue.d.ts +11 -0
- package/dist/approvalQueue.js +80 -1
- package/dist/approvalQueue.js.map +1 -1
- package/dist/approvalSignals.d.ts +124 -0
- package/dist/approvalSignals.js +512 -0
- package/dist/approvalSignals.js.map +1 -0
- package/dist/automation.d.ts +37 -0
- package/dist/automation.js +105 -61
- package/dist/automation.js.map +1 -1
- package/dist/automationSuggestions.d.ts +79 -0
- package/dist/automationSuggestions.js +150 -0
- package/dist/automationSuggestions.js.map +1 -0
- package/dist/bridge.js +46 -0
- package/dist/bridge.js.map +1 -1
- package/dist/ccPermissions.d.ts +15 -0
- package/dist/ccPermissions.js +15 -0
- package/dist/ccPermissions.js.map +1 -1
- package/dist/claudeDriver.js +74 -16
- package/dist/claudeDriver.js.map +1 -1
- package/dist/commands/patchworkInit.d.ts +8 -0
- package/dist/commands/patchworkInit.js +41 -5
- package/dist/commands/patchworkInit.js.map +1 -1
- package/dist/commands/recipe.d.ts +20 -0
- package/dist/commands/recipe.js +194 -5
- package/dist/commands/recipe.js.map +1 -1
- package/dist/commands/recipeInstall.js +93 -4
- package/dist/commands/recipeInstall.js.map +1 -1
- package/dist/commands/tracesExport.d.ts +83 -0
- package/dist/commands/tracesExport.js +269 -0
- package/dist/commands/tracesExport.js.map +1 -0
- package/dist/commands/tracesImport.d.ts +56 -0
- package/dist/commands/tracesImport.js +161 -0
- package/dist/commands/tracesImport.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/connectorRoutes.d.ts +43 -0
- package/dist/connectorRoutes.js +1713 -0
- package/dist/connectorRoutes.js.map +1 -0
- package/dist/connectors/asana.js +6 -7
- package/dist/connectors/asana.js.map +1 -1
- package/dist/connectors/baseConnector.d.ts +20 -0
- package/dist/connectors/baseConnector.js +45 -4
- package/dist/connectors/baseConnector.js.map +1 -1
- package/dist/connectors/discord.js +6 -7
- package/dist/connectors/discord.js.map +1 -1
- package/dist/connectors/gmail.js +39 -10
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.js +36 -10
- package/dist/connectors/googleCalendar.js.map +1 -1
- package/dist/connectors/googleDrive.js +22 -6
- package/dist/connectors/googleDrive.js.map +1 -1
- package/dist/connectors/linear.js +2 -2
- package/dist/connectors/linear.js.map +1 -1
- package/dist/connectors/mcpOAuth.js +26 -2
- package/dist/connectors/mcpOAuth.js.map +1 -1
- package/dist/connectors/oauthStateStore.d.ts +31 -0
- package/dist/connectors/oauthStateStore.js +52 -0
- package/dist/connectors/oauthStateStore.js.map +1 -0
- package/dist/connectors/slack.d.ts +15 -0
- package/dist/connectors/slack.js +54 -4
- package/dist/connectors/slack.js.map +1 -1
- package/dist/connectors/tokenStorage.js +27 -2
- package/dist/connectors/tokenStorage.js.map +1 -1
- package/dist/connectors/zendesk.js +19 -1
- package/dist/connectors/zendesk.js.map +1 -1
- package/dist/cors.d.ts +10 -0
- package/dist/cors.js +29 -0
- package/dist/cors.js.map +1 -0
- package/dist/decisionReplay.d.ts +72 -0
- package/dist/decisionReplay.js +92 -0
- package/dist/decisionReplay.js.map +1 -0
- package/dist/decisionTraceLog.d.ts +6 -0
- package/dist/decisionTraceLog.js +54 -2
- package/dist/decisionTraceLog.js.map +1 -1
- package/dist/fp/automationInterpreter.js +25 -21
- package/dist/fp/automationInterpreter.js.map +1 -1
- package/dist/fp/automationState.js +4 -1
- package/dist/fp/automationState.js.map +1 -1
- package/dist/fp/policyParser.js +4 -1
- package/dist/fp/policyParser.js.map +1 -1
- package/dist/inboxRoutes.d.ts +22 -0
- package/dist/inboxRoutes.js +114 -0
- package/dist/inboxRoutes.js.map +1 -0
- package/dist/index.js +479 -17
- package/dist/index.js.map +1 -1
- package/dist/mcpRoutes.d.ts +37 -0
- package/dist/mcpRoutes.js +76 -0
- package/dist/mcpRoutes.js.map +1 -0
- package/dist/oauth.d.ts +3 -0
- package/dist/oauth.js +151 -26
- package/dist/oauth.js.map +1 -1
- package/dist/oauthRoutes.d.ts +32 -0
- package/dist/oauthRoutes.js +124 -0
- package/dist/oauthRoutes.js.map +1 -0
- package/dist/orchestrator/orchestratorBridge.js +2 -2
- package/dist/orchestrator/orchestratorBridge.js.map +1 -1
- package/dist/patchworkConfig.d.ts +7 -0
- package/dist/patchworkConfig.js.map +1 -1
- package/dist/pluginLoader.d.ts +12 -0
- package/dist/pluginLoader.js +43 -4
- package/dist/pluginLoader.js.map +1 -1
- package/dist/pluginWatcher.js +8 -3
- package/dist/pluginWatcher.js.map +1 -1
- package/dist/preToolUseHook.d.ts +12 -0
- package/dist/preToolUseHook.js +23 -0
- package/dist/preToolUseHook.js.map +1 -1
- package/dist/recipeOrchestration.d.ts +1 -0
- package/dist/recipeOrchestration.js +173 -13
- package/dist/recipeOrchestration.js.map +1 -1
- package/dist/recipeRoutes.d.ts +154 -0
- package/dist/recipeRoutes.js +1107 -0
- package/dist/recipeRoutes.js.map +1 -0
- package/dist/recipes/chainedRunner.d.ts +15 -0
- package/dist/recipes/chainedRunner.js +73 -8
- package/dist/recipes/chainedRunner.js.map +1 -1
- package/dist/recipes/compiler.js +3 -3
- package/dist/recipes/compiler.js.map +1 -1
- package/dist/recipes/installer.js +3 -3
- package/dist/recipes/installer.js.map +1 -1
- package/dist/recipes/migrationWarnings.d.ts +12 -0
- package/dist/recipes/migrationWarnings.js +44 -0
- package/dist/recipes/migrationWarnings.js.map +1 -0
- package/dist/recipes/resolveRecipePath.d.ts +69 -0
- package/dist/recipes/resolveRecipePath.js +202 -0
- package/dist/recipes/resolveRecipePath.js.map +1 -0
- package/dist/recipes/tools/file.d.ts +6 -0
- package/dist/recipes/tools/file.js +12 -8
- package/dist/recipes/tools/file.js.map +1 -1
- package/dist/recipes/tools/index.d.ts +2 -0
- package/dist/recipes/tools/index.js +2 -0
- package/dist/recipes/tools/index.js.map +1 -1
- package/dist/recipes/tools/jira.d.ts +14 -0
- package/dist/recipes/tools/jira.js +369 -0
- package/dist/recipes/tools/jira.js.map +1 -0
- package/dist/recipes/tools/linear.js +6 -3
- package/dist/recipes/tools/linear.js.map +1 -1
- package/dist/recipes/tools/sentry.d.ts +12 -0
- package/dist/recipes/tools/sentry.js +73 -0
- package/dist/recipes/tools/sentry.js.map +1 -0
- package/dist/recipes/tools/slack.js +7 -3
- package/dist/recipes/tools/slack.js.map +1 -1
- package/dist/recipes/validation.js +83 -14
- package/dist/recipes/validation.js.map +1 -1
- package/dist/recipes/yamlRunner.d.ts +7 -0
- package/dist/recipes/yamlRunner.js +107 -13
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +44 -1
- package/dist/recipesHttp.js +168 -15
- package/dist/recipesHttp.js.map +1 -1
- package/dist/runLog.d.ts +14 -0
- package/dist/runLog.js +88 -4
- package/dist/runLog.js.map +1 -1
- package/dist/schemas/dry-run-plan.v1.json +139 -0
- package/dist/schemas/recipe.v1.json +684 -0
- package/dist/server.d.ts +71 -10
- package/dist/server.js +363 -1703
- package/dist/server.js.map +1 -1
- package/dist/ssrfGuard.d.ts +54 -0
- package/dist/ssrfGuard.js +122 -0
- package/dist/ssrfGuard.js.map +1 -0
- package/dist/streamableHttp.d.ts +8 -0
- package/dist/streamableHttp.js +112 -21
- package/dist/streamableHttp.js.map +1 -1
- package/dist/tools/getDocumentSymbols.d.ts +24 -0
- package/dist/tools/getDocumentSymbols.js +74 -8
- package/dist/tools/getDocumentSymbols.js.map +1 -1
- package/dist/tools/getSecurityAdvisories.js +10 -1
- package/dist/tools/getSecurityAdvisories.js.map +1 -1
- package/dist/tools/getSessionUsage.d.ts +3 -0
- package/dist/tools/getSessionUsage.js +3 -0
- package/dist/tools/getSessionUsage.js.map +1 -1
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +32 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/transaction.d.ts +19 -0
- package/dist/tools/transaction.js +29 -0
- package/dist/tools/transaction.js.map +1 -1
- package/dist/traceEncryption.d.ts +46 -0
- package/dist/traceEncryption.js +124 -0
- package/dist/traceEncryption.js.map +1 -0
- package/dist/transport.d.ts +39 -0
- package/dist/transport.js +88 -8
- package/dist/transport.js.map +1 -1
- package/package.json +4 -2
- package/templates/policies/README.md +72 -0
- package/templates/policies/conservative.json +14 -0
- package/templates/policies/developer.json +14 -0
- package/templates/policies/headless-ci.json +24 -0
- package/templates/policies/personal-assistant.json +15 -0
- package/templates/policies/regulated-industry.json +18 -0
- package/templates/recipes/webhook/README.md +70 -0
- package/templates/recipes/webhook/capture-thought.yaml +26 -0
- package/templates/recipes/webhook/customer-escalation.yaml +49 -0
- package/templates/recipes/webhook/incident-intake.yaml +46 -0
- package/templates/recipes/webhook/meeting-prep.yaml +48 -0
- package/templates/recipes/webhook/morning-brief.yaml +57 -0
|
@@ -0,0 +1,1713 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector route dispatcher — extracted from src/server.ts.
|
|
3
|
+
*
|
|
4
|
+
* Owns every `/connections/*` HTTP endpoint (auth start / OAuth callback /
|
|
5
|
+
* test ping / disconnect / connect-with-body) for the 18 supported
|
|
6
|
+
* connectors.
|
|
7
|
+
*
|
|
8
|
+
* Two entrypoints — the split exists because OAuth callbacks must run
|
|
9
|
+
* BEFORE the bearer-auth gate (they're browser redirects from the vendor
|
|
10
|
+
* with no Patchwork token), while CRUD routes must run AFTER it:
|
|
11
|
+
*
|
|
12
|
+
* - `tryHandlePublicConnectorRoute` — `/connections/<vendor>/callback`
|
|
13
|
+
* routes. Server.ts calls this BEFORE bearer-auth.
|
|
14
|
+
* - `tryHandleConnectorRoute` — auth/test/disconnect/connect routes.
|
|
15
|
+
* Server.ts calls this AFTER bearer-auth.
|
|
16
|
+
*
|
|
17
|
+
* Mechanical lift — no behavior change:
|
|
18
|
+
* - Handler bodies are byte-identical to the original blocks save for
|
|
19
|
+
* wrapping a few non-IIFE call sites in `void (async()=>{...})()` so
|
|
20
|
+
* both functions can return boolean synchronously rather than
|
|
21
|
+
* Promise<boolean>. The microtask delay this introduces is invisible
|
|
22
|
+
* to clients — the parent request handler `return`s on a true result
|
|
23
|
+
* either way, and `res.end()` has always been async.
|
|
24
|
+
* - Pre-extraction grep confirmed zero `this.` references in either
|
|
25
|
+
* block, so no dependency injection was needed.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Try to handle a `/connections/<vendor>/callback` route. These are
|
|
29
|
+
* unauthenticated browser redirects from the OAuth vendor and MUST run
|
|
30
|
+
* before the bearer-auth gate. Returns true if the route was dispatched.
|
|
31
|
+
*/
|
|
32
|
+
export function tryHandlePublicConnectorRoute(req, res, parsedUrl) {
|
|
33
|
+
if (parsedUrl.pathname === "/connections/github/callback" &&
|
|
34
|
+
req.method === "GET") {
|
|
35
|
+
void (async () => {
|
|
36
|
+
try {
|
|
37
|
+
const { handleGithubCallback } = await import("./connectors/github.js");
|
|
38
|
+
const code = parsedUrl.searchParams.get("code");
|
|
39
|
+
const state = parsedUrl.searchParams.get("state");
|
|
40
|
+
const error = parsedUrl.searchParams.get("error");
|
|
41
|
+
const result = await handleGithubCallback(code, state, error);
|
|
42
|
+
res.writeHead(result.status, {
|
|
43
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
44
|
+
});
|
|
45
|
+
res.end(result.body);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (!res.headersSent) {
|
|
49
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
50
|
+
res.end(JSON.stringify({
|
|
51
|
+
error: err instanceof Error ? err.message : String(err),
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (parsedUrl.pathname === "/connections/linear/callback" &&
|
|
59
|
+
req.method === "GET") {
|
|
60
|
+
void (async () => {
|
|
61
|
+
try {
|
|
62
|
+
const { handleLinearCallback } = await import("./connectors/linear.js");
|
|
63
|
+
const code = parsedUrl.searchParams.get("code");
|
|
64
|
+
const state = parsedUrl.searchParams.get("state");
|
|
65
|
+
const error = parsedUrl.searchParams.get("error");
|
|
66
|
+
const result = await handleLinearCallback(code, state, error);
|
|
67
|
+
res.writeHead(result.status, {
|
|
68
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
69
|
+
});
|
|
70
|
+
res.end(result.body);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (!res.headersSent) {
|
|
74
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
75
|
+
res.end(JSON.stringify({
|
|
76
|
+
error: err instanceof Error ? err.message : String(err),
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
})();
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (parsedUrl.pathname === "/connections/sentry/callback" &&
|
|
84
|
+
req.method === "GET") {
|
|
85
|
+
void (async () => {
|
|
86
|
+
try {
|
|
87
|
+
const { handleSentryCallback } = await import("./connectors/sentry.js");
|
|
88
|
+
const code = parsedUrl.searchParams.get("code");
|
|
89
|
+
const state = parsedUrl.searchParams.get("state");
|
|
90
|
+
const error = parsedUrl.searchParams.get("error");
|
|
91
|
+
const result = await handleSentryCallback(code, state, error);
|
|
92
|
+
res.writeHead(result.status, {
|
|
93
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
94
|
+
});
|
|
95
|
+
res.end(result.body);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
if (!res.headersSent) {
|
|
99
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
100
|
+
res.end(JSON.stringify({
|
|
101
|
+
error: err instanceof Error ? err.message : String(err),
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
})();
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
if (parsedUrl.pathname === "/connections/google-calendar/callback" &&
|
|
109
|
+
req.method === "GET") {
|
|
110
|
+
void (async () => {
|
|
111
|
+
try {
|
|
112
|
+
const { handleCalendarCallback } = await import("./connectors/googleCalendar.js");
|
|
113
|
+
const code = parsedUrl.searchParams.get("code");
|
|
114
|
+
const state = parsedUrl.searchParams.get("state");
|
|
115
|
+
const error = parsedUrl.searchParams.get("error");
|
|
116
|
+
const result = await handleCalendarCallback(code, state, error);
|
|
117
|
+
res.writeHead(result.status, {
|
|
118
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
119
|
+
});
|
|
120
|
+
res.end(result.body);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
if (!res.headersSent) {
|
|
124
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
125
|
+
res.end(JSON.stringify({
|
|
126
|
+
error: err instanceof Error ? err.message : String(err),
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
})();
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
if (parsedUrl.pathname === "/connections/google-drive/callback" &&
|
|
134
|
+
req.method === "GET") {
|
|
135
|
+
void (async () => {
|
|
136
|
+
try {
|
|
137
|
+
const { handleDriveCallback } = await import("./connectors/googleDrive.js");
|
|
138
|
+
const code = parsedUrl.searchParams.get("code");
|
|
139
|
+
const state = parsedUrl.searchParams.get("state");
|
|
140
|
+
const error = parsedUrl.searchParams.get("error");
|
|
141
|
+
const result = await handleDriveCallback(code, state, error);
|
|
142
|
+
res.writeHead(result.status, {
|
|
143
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
144
|
+
});
|
|
145
|
+
res.end(result.body);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
if (!res.headersSent) {
|
|
149
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
150
|
+
res.end(JSON.stringify({
|
|
151
|
+
error: err instanceof Error ? err.message : String(err),
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
})();
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
if (parsedUrl.pathname === "/connections/slack/callback" &&
|
|
159
|
+
req.method === "GET") {
|
|
160
|
+
void (async () => {
|
|
161
|
+
try {
|
|
162
|
+
const { handleSlackCallback } = await import("./connectors/slack.js");
|
|
163
|
+
const code = parsedUrl.searchParams.get("code");
|
|
164
|
+
const state = parsedUrl.searchParams.get("state");
|
|
165
|
+
const error = parsedUrl.searchParams.get("error");
|
|
166
|
+
const result = await handleSlackCallback(code, state, error);
|
|
167
|
+
res.writeHead(result.status, {
|
|
168
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
169
|
+
});
|
|
170
|
+
res.end(result.body);
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
if (!res.headersSent) {
|
|
174
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
175
|
+
res.end(JSON.stringify({
|
|
176
|
+
error: err instanceof Error ? err.message : String(err),
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
})();
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
if (parsedUrl.pathname === "/connections/gmail/callback" &&
|
|
184
|
+
req.method === "GET") {
|
|
185
|
+
void (async () => {
|
|
186
|
+
try {
|
|
187
|
+
const { handleGmailCallback } = await import("./connectors/gmail.js");
|
|
188
|
+
const code = parsedUrl.searchParams.get("code");
|
|
189
|
+
const state = parsedUrl.searchParams.get("state");
|
|
190
|
+
const error = parsedUrl.searchParams.get("error");
|
|
191
|
+
const result = await handleGmailCallback(code, state, error);
|
|
192
|
+
res.writeHead(result.status, {
|
|
193
|
+
"Content-Type": result.contentType ?? "text/html",
|
|
194
|
+
});
|
|
195
|
+
res.end(result.body);
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
if (!res.headersSent) {
|
|
199
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
200
|
+
res.end(JSON.stringify({
|
|
201
|
+
error: err instanceof Error ? err.message : String(err),
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
})();
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Try to handle a `/connections/*` route (auth start / test / disconnect /
|
|
212
|
+
* connect-with-body). Returns true if the route was dispatched (caller
|
|
213
|
+
* should `return` from the request handler), false if no route matched
|
|
214
|
+
* (caller should fall through to other route checks).
|
|
215
|
+
*
|
|
216
|
+
* The actual response is written asynchronously inside an IIFE; this
|
|
217
|
+
* function returns synchronously as soon as the route is recognized.
|
|
218
|
+
*/
|
|
219
|
+
export function tryHandleConnectorRoute(req, res, parsedUrl) {
|
|
220
|
+
// ── Gmail / Connections endpoints ───────────────────────────────────────
|
|
221
|
+
if (parsedUrl.pathname === "/connections" && req.method === "GET") {
|
|
222
|
+
void (async () => {
|
|
223
|
+
try {
|
|
224
|
+
const { handleConnectionsList } = await import("./connectors/gmail.js");
|
|
225
|
+
const result = await handleConnectionsList();
|
|
226
|
+
res.writeHead(result.status, {
|
|
227
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
228
|
+
});
|
|
229
|
+
res.end(result.body);
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
if (!res.headersSent) {
|
|
233
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
234
|
+
res.end(JSON.stringify({
|
|
235
|
+
error: err instanceof Error ? err.message : String(err),
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
})();
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
if (parsedUrl.pathname === "/connections/gmail/auth" &&
|
|
243
|
+
req.method === "GET") {
|
|
244
|
+
void (async () => {
|
|
245
|
+
try {
|
|
246
|
+
const { handleGmailAuthRedirect } = await import("./connectors/gmail.js");
|
|
247
|
+
const result = handleGmailAuthRedirect();
|
|
248
|
+
if (result.redirect) {
|
|
249
|
+
res.writeHead(302, { Location: result.redirect });
|
|
250
|
+
res.end();
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
res.writeHead(result.status, {
|
|
254
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
255
|
+
});
|
|
256
|
+
res.end(result.body);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
if (!res.headersSent) {
|
|
261
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
262
|
+
res.end(JSON.stringify({
|
|
263
|
+
error: err instanceof Error ? err.message : String(err),
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
})();
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
if (parsedUrl.pathname === "/connections/gmail" && req.method === "DELETE") {
|
|
271
|
+
void (async () => {
|
|
272
|
+
try {
|
|
273
|
+
const { handleGmailDisconnect } = await import("./connectors/gmail.js");
|
|
274
|
+
const result = await handleGmailDisconnect();
|
|
275
|
+
res.writeHead(result.status, {
|
|
276
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
277
|
+
});
|
|
278
|
+
res.end(result.body);
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
if (!res.headersSent) {
|
|
282
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
283
|
+
res.end(JSON.stringify({
|
|
284
|
+
error: err instanceof Error ? err.message : String(err),
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
})();
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
if (parsedUrl.pathname === "/connections/gmail/test" &&
|
|
292
|
+
req.method === "POST") {
|
|
293
|
+
void (async () => {
|
|
294
|
+
try {
|
|
295
|
+
const { handleGmailTest } = await import("./connectors/gmail.js");
|
|
296
|
+
const result = await handleGmailTest();
|
|
297
|
+
res.writeHead(result.status, {
|
|
298
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
299
|
+
});
|
|
300
|
+
res.end(result.body);
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
if (!res.headersSent) {
|
|
304
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
305
|
+
res.end(JSON.stringify({
|
|
306
|
+
error: err instanceof Error ? err.message : String(err),
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
})();
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
// ── GitHub MCP connector routes ─────────────────────────────────────
|
|
314
|
+
if (parsedUrl.pathname === "/connections/github/auth" &&
|
|
315
|
+
req.method === "GET") {
|
|
316
|
+
void (async () => {
|
|
317
|
+
try {
|
|
318
|
+
const { handleGithubAuthorize } = await import("./connectors/github.js");
|
|
319
|
+
const result = await handleGithubAuthorize();
|
|
320
|
+
if (result.redirect) {
|
|
321
|
+
res.writeHead(302, { Location: result.redirect });
|
|
322
|
+
res.end();
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
res.writeHead(result.status, {
|
|
326
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
327
|
+
});
|
|
328
|
+
res.end(result.body);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch (err) {
|
|
332
|
+
if (!res.headersSent) {
|
|
333
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
334
|
+
res.end(JSON.stringify({
|
|
335
|
+
error: err instanceof Error ? err.message : String(err),
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
})();
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
if (parsedUrl.pathname === "/connections/github/test" &&
|
|
343
|
+
req.method === "POST") {
|
|
344
|
+
void (async () => {
|
|
345
|
+
try {
|
|
346
|
+
const { handleGithubTest } = await import("./connectors/github.js");
|
|
347
|
+
const result = await handleGithubTest();
|
|
348
|
+
res.writeHead(result.status, {
|
|
349
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
350
|
+
});
|
|
351
|
+
res.end(result.body);
|
|
352
|
+
}
|
|
353
|
+
catch (err) {
|
|
354
|
+
if (!res.headersSent) {
|
|
355
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
356
|
+
res.end(JSON.stringify({
|
|
357
|
+
error: err instanceof Error ? err.message : String(err),
|
|
358
|
+
}));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
})();
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
if (parsedUrl.pathname === "/connections/github" && req.method === "DELETE") {
|
|
365
|
+
void (async () => {
|
|
366
|
+
try {
|
|
367
|
+
const { handleGithubDisconnect } = await import("./connectors/github.js");
|
|
368
|
+
const result = await handleGithubDisconnect();
|
|
369
|
+
res.writeHead(result.status, {
|
|
370
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
371
|
+
});
|
|
372
|
+
res.end(result.body);
|
|
373
|
+
}
|
|
374
|
+
catch (err) {
|
|
375
|
+
if (!res.headersSent) {
|
|
376
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
377
|
+
res.end(JSON.stringify({
|
|
378
|
+
error: err instanceof Error ? err.message : String(err),
|
|
379
|
+
}));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
})();
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
// ── Sentry MCP connector routes ─────────────────────────────────────
|
|
386
|
+
if (parsedUrl.pathname === "/connections/sentry/auth" &&
|
|
387
|
+
req.method === "GET") {
|
|
388
|
+
void (async () => {
|
|
389
|
+
try {
|
|
390
|
+
const { handleSentryAuthorize } = await import("./connectors/sentry.js");
|
|
391
|
+
const result = await handleSentryAuthorize();
|
|
392
|
+
if (result.redirect) {
|
|
393
|
+
res.writeHead(302, { Location: result.redirect });
|
|
394
|
+
res.end();
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
res.writeHead(result.status, {
|
|
398
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
399
|
+
});
|
|
400
|
+
res.end(result.body);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
catch (err) {
|
|
404
|
+
if (!res.headersSent) {
|
|
405
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
406
|
+
res.end(JSON.stringify({
|
|
407
|
+
error: err instanceof Error ? err.message : String(err),
|
|
408
|
+
}));
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
})();
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
if (parsedUrl.pathname === "/connections/sentry/callback" &&
|
|
415
|
+
req.method === "GET") {
|
|
416
|
+
void (async () => {
|
|
417
|
+
try {
|
|
418
|
+
const { handleSentryCallback } = await import("./connectors/sentry.js");
|
|
419
|
+
const code = parsedUrl.searchParams.get("code");
|
|
420
|
+
const state = parsedUrl.searchParams.get("state");
|
|
421
|
+
const error = parsedUrl.searchParams.get("error");
|
|
422
|
+
const result = await handleSentryCallback(code, state, error);
|
|
423
|
+
res.writeHead(result.status, {
|
|
424
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
425
|
+
});
|
|
426
|
+
res.end(result.body);
|
|
427
|
+
}
|
|
428
|
+
catch (err) {
|
|
429
|
+
if (!res.headersSent) {
|
|
430
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
431
|
+
res.end(JSON.stringify({
|
|
432
|
+
error: err instanceof Error ? err.message : String(err),
|
|
433
|
+
}));
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
})();
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
if (parsedUrl.pathname === "/connections/sentry/test" &&
|
|
440
|
+
req.method === "POST") {
|
|
441
|
+
void (async () => {
|
|
442
|
+
try {
|
|
443
|
+
const { handleSentryTest } = await import("./connectors/sentry.js");
|
|
444
|
+
const result = await handleSentryTest();
|
|
445
|
+
res.writeHead(result.status, {
|
|
446
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
447
|
+
});
|
|
448
|
+
res.end(result.body);
|
|
449
|
+
}
|
|
450
|
+
catch (err) {
|
|
451
|
+
if (!res.headersSent) {
|
|
452
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
453
|
+
res.end(JSON.stringify({
|
|
454
|
+
error: err instanceof Error ? err.message : String(err),
|
|
455
|
+
}));
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
})();
|
|
459
|
+
return true;
|
|
460
|
+
}
|
|
461
|
+
if (parsedUrl.pathname === "/connections/sentry" && req.method === "DELETE") {
|
|
462
|
+
void (async () => {
|
|
463
|
+
try {
|
|
464
|
+
const { handleSentryDisconnect } = await import("./connectors/sentry.js");
|
|
465
|
+
const result = await handleSentryDisconnect();
|
|
466
|
+
res.writeHead(result.status, {
|
|
467
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
468
|
+
});
|
|
469
|
+
res.end(result.body);
|
|
470
|
+
}
|
|
471
|
+
catch (err) {
|
|
472
|
+
if (!res.headersSent) {
|
|
473
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
474
|
+
res.end(JSON.stringify({
|
|
475
|
+
error: err instanceof Error ? err.message : String(err),
|
|
476
|
+
}));
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
})();
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
// ── Linear MCP connector routes ─────────────────────────────────────
|
|
483
|
+
if (parsedUrl.pathname === "/connections/linear/auth" &&
|
|
484
|
+
req.method === "GET") {
|
|
485
|
+
void (async () => {
|
|
486
|
+
try {
|
|
487
|
+
const { handleLinearAuthorize } = await import("./connectors/linear.js");
|
|
488
|
+
const result = await handleLinearAuthorize();
|
|
489
|
+
if (result.redirect) {
|
|
490
|
+
res.writeHead(302, { Location: result.redirect });
|
|
491
|
+
res.end();
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
res.writeHead(result.status, {
|
|
495
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
496
|
+
});
|
|
497
|
+
res.end(result.body);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
catch (err) {
|
|
501
|
+
if (!res.headersSent) {
|
|
502
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
503
|
+
res.end(JSON.stringify({
|
|
504
|
+
error: err instanceof Error ? err.message : String(err),
|
|
505
|
+
}));
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
})();
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
if (parsedUrl.pathname === "/connections/linear/callback" &&
|
|
512
|
+
req.method === "GET") {
|
|
513
|
+
void (async () => {
|
|
514
|
+
try {
|
|
515
|
+
const { handleLinearCallback } = await import("./connectors/linear.js");
|
|
516
|
+
const code = parsedUrl.searchParams.get("code");
|
|
517
|
+
const state = parsedUrl.searchParams.get("state");
|
|
518
|
+
const error = parsedUrl.searchParams.get("error");
|
|
519
|
+
const result = await handleLinearCallback(code, state, error);
|
|
520
|
+
res.writeHead(result.status, {
|
|
521
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
522
|
+
});
|
|
523
|
+
res.end(result.body);
|
|
524
|
+
}
|
|
525
|
+
catch (err) {
|
|
526
|
+
if (!res.headersSent) {
|
|
527
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
528
|
+
res.end(JSON.stringify({
|
|
529
|
+
error: err instanceof Error ? err.message : String(err),
|
|
530
|
+
}));
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
})();
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
if (parsedUrl.pathname === "/connections/linear/test" &&
|
|
537
|
+
req.method === "POST") {
|
|
538
|
+
void (async () => {
|
|
539
|
+
try {
|
|
540
|
+
const { handleLinearTest } = await import("./connectors/linear.js");
|
|
541
|
+
const result = await handleLinearTest();
|
|
542
|
+
res.writeHead(result.status, {
|
|
543
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
544
|
+
});
|
|
545
|
+
res.end(result.body);
|
|
546
|
+
}
|
|
547
|
+
catch (err) {
|
|
548
|
+
if (!res.headersSent) {
|
|
549
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
550
|
+
res.end(JSON.stringify({
|
|
551
|
+
error: err instanceof Error ? err.message : String(err),
|
|
552
|
+
}));
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
})();
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
if (parsedUrl.pathname === "/connections/linear" && req.method === "DELETE") {
|
|
559
|
+
void (async () => {
|
|
560
|
+
try {
|
|
561
|
+
const { handleLinearDisconnect } = await import("./connectors/linear.js");
|
|
562
|
+
const result = await handleLinearDisconnect();
|
|
563
|
+
res.writeHead(result.status, {
|
|
564
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
565
|
+
});
|
|
566
|
+
res.end(result.body);
|
|
567
|
+
}
|
|
568
|
+
catch (err) {
|
|
569
|
+
if (!res.headersSent) {
|
|
570
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
571
|
+
res.end(JSON.stringify({
|
|
572
|
+
error: err instanceof Error ? err.message : String(err),
|
|
573
|
+
}));
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
})();
|
|
577
|
+
return true;
|
|
578
|
+
}
|
|
579
|
+
// ── Slack connector routes ──────────────────────────────────────
|
|
580
|
+
if ((parsedUrl.pathname === "/connections/slack/auth" ||
|
|
581
|
+
parsedUrl.pathname === "/connections/slack/authorize") &&
|
|
582
|
+
req.method === "GET") {
|
|
583
|
+
void (async () => {
|
|
584
|
+
try {
|
|
585
|
+
const { handleSlackAuthorize } = await import("./connectors/slack.js");
|
|
586
|
+
const result = handleSlackAuthorize();
|
|
587
|
+
if (result.redirect) {
|
|
588
|
+
res.writeHead(302, { Location: result.redirect });
|
|
589
|
+
res.end();
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
res.writeHead(result.status, {
|
|
593
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
594
|
+
});
|
|
595
|
+
res.end(result.body);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
catch (err) {
|
|
599
|
+
if (!res.headersSent) {
|
|
600
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
601
|
+
res.end(JSON.stringify({
|
|
602
|
+
error: err instanceof Error ? err.message : String(err),
|
|
603
|
+
}));
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
})();
|
|
607
|
+
return true;
|
|
608
|
+
}
|
|
609
|
+
if (parsedUrl.pathname === "/connections/slack/test" &&
|
|
610
|
+
req.method === "POST") {
|
|
611
|
+
void (async () => {
|
|
612
|
+
try {
|
|
613
|
+
const { handleSlackTest } = await import("./connectors/slack.js");
|
|
614
|
+
const result = await handleSlackTest();
|
|
615
|
+
res.writeHead(result.status, {
|
|
616
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
617
|
+
});
|
|
618
|
+
res.end(result.body);
|
|
619
|
+
}
|
|
620
|
+
catch (err) {
|
|
621
|
+
if (!res.headersSent) {
|
|
622
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
623
|
+
res.end(JSON.stringify({
|
|
624
|
+
error: err instanceof Error ? err.message : String(err),
|
|
625
|
+
}));
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
})();
|
|
629
|
+
return true;
|
|
630
|
+
}
|
|
631
|
+
if (parsedUrl.pathname === "/connections/slack" && req.method === "DELETE") {
|
|
632
|
+
void (async () => {
|
|
633
|
+
try {
|
|
634
|
+
const { handleSlackDisconnect } = await import("./connectors/slack.js");
|
|
635
|
+
const result = handleSlackDisconnect();
|
|
636
|
+
res.writeHead(result.status, {
|
|
637
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
638
|
+
});
|
|
639
|
+
res.end(result.body);
|
|
640
|
+
}
|
|
641
|
+
catch (err) {
|
|
642
|
+
if (!res.headersSent) {
|
|
643
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
644
|
+
res.end(JSON.stringify({
|
|
645
|
+
error: err instanceof Error ? err.message : String(err),
|
|
646
|
+
}));
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
})();
|
|
650
|
+
return true;
|
|
651
|
+
}
|
|
652
|
+
// ── Discord connector routes ───────────────────────────────────
|
|
653
|
+
if ((parsedUrl.pathname === "/connections/discord/auth" ||
|
|
654
|
+
parsedUrl.pathname === "/connections/discord/authorize") &&
|
|
655
|
+
req.method === "GET") {
|
|
656
|
+
void (async () => {
|
|
657
|
+
try {
|
|
658
|
+
const { handleDiscordAuthorize } = await import("./connectors/discord.js");
|
|
659
|
+
const result = handleDiscordAuthorize();
|
|
660
|
+
if (result.redirect) {
|
|
661
|
+
res.writeHead(302, { Location: result.redirect });
|
|
662
|
+
res.end();
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
res.writeHead(result.status, {
|
|
666
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
667
|
+
});
|
|
668
|
+
res.end(result.body);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
catch (err) {
|
|
672
|
+
if (!res.headersSent) {
|
|
673
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
674
|
+
res.end(JSON.stringify({
|
|
675
|
+
error: err instanceof Error ? err.message : String(err),
|
|
676
|
+
}));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
})();
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
if (parsedUrl.pathname === "/connections/discord/callback" &&
|
|
683
|
+
req.method === "GET") {
|
|
684
|
+
void (async () => {
|
|
685
|
+
try {
|
|
686
|
+
const { handleDiscordCallback } = await import("./connectors/discord.js");
|
|
687
|
+
const code = parsedUrl.searchParams.get("code");
|
|
688
|
+
const state = parsedUrl.searchParams.get("state");
|
|
689
|
+
const error = parsedUrl.searchParams.get("error");
|
|
690
|
+
const result = await handleDiscordCallback(code, state, error);
|
|
691
|
+
res.writeHead(result.status, {
|
|
692
|
+
"Content-Type": result.contentType ?? "text/html",
|
|
693
|
+
});
|
|
694
|
+
res.end(result.body);
|
|
695
|
+
}
|
|
696
|
+
catch (err) {
|
|
697
|
+
if (!res.headersSent) {
|
|
698
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
699
|
+
res.end(JSON.stringify({
|
|
700
|
+
error: err instanceof Error ? err.message : String(err),
|
|
701
|
+
}));
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
})();
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
if (parsedUrl.pathname === "/connections/discord/test" &&
|
|
708
|
+
req.method === "POST") {
|
|
709
|
+
void (async () => {
|
|
710
|
+
try {
|
|
711
|
+
const { handleDiscordTest } = await import("./connectors/discord.js");
|
|
712
|
+
const result = await handleDiscordTest();
|
|
713
|
+
res.writeHead(result.status, {
|
|
714
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
715
|
+
});
|
|
716
|
+
res.end(result.body);
|
|
717
|
+
}
|
|
718
|
+
catch (err) {
|
|
719
|
+
if (!res.headersSent) {
|
|
720
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
721
|
+
res.end(JSON.stringify({
|
|
722
|
+
error: err instanceof Error ? err.message : String(err),
|
|
723
|
+
}));
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
})();
|
|
727
|
+
return true;
|
|
728
|
+
}
|
|
729
|
+
if (parsedUrl.pathname === "/connections/discord" &&
|
|
730
|
+
req.method === "DELETE") {
|
|
731
|
+
void (async () => {
|
|
732
|
+
try {
|
|
733
|
+
const { handleDiscordDisconnect } = await import("./connectors/discord.js");
|
|
734
|
+
const result = await handleDiscordDisconnect();
|
|
735
|
+
res.writeHead(result.status, {
|
|
736
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
737
|
+
});
|
|
738
|
+
res.end(result.body);
|
|
739
|
+
}
|
|
740
|
+
catch (err) {
|
|
741
|
+
if (!res.headersSent) {
|
|
742
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
743
|
+
res.end(JSON.stringify({
|
|
744
|
+
error: err instanceof Error ? err.message : String(err),
|
|
745
|
+
}));
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
})();
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
751
|
+
// ── Asana connector routes ─────────────────────────────────────
|
|
752
|
+
if ((parsedUrl.pathname === "/connections/asana/auth" ||
|
|
753
|
+
parsedUrl.pathname === "/connections/asana/authorize") &&
|
|
754
|
+
req.method === "GET") {
|
|
755
|
+
void (async () => {
|
|
756
|
+
try {
|
|
757
|
+
const { handleAsanaAuthorize } = await import("./connectors/asana.js");
|
|
758
|
+
const result = handleAsanaAuthorize();
|
|
759
|
+
if (result.redirect) {
|
|
760
|
+
res.writeHead(302, { Location: result.redirect });
|
|
761
|
+
res.end();
|
|
762
|
+
}
|
|
763
|
+
else {
|
|
764
|
+
res.writeHead(result.status, {
|
|
765
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
766
|
+
});
|
|
767
|
+
res.end(result.body);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
catch (err) {
|
|
771
|
+
if (!res.headersSent) {
|
|
772
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
773
|
+
res.end(JSON.stringify({
|
|
774
|
+
error: err instanceof Error ? err.message : String(err),
|
|
775
|
+
}));
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
})();
|
|
779
|
+
return true;
|
|
780
|
+
}
|
|
781
|
+
if (parsedUrl.pathname === "/connections/asana/callback" &&
|
|
782
|
+
req.method === "GET") {
|
|
783
|
+
void (async () => {
|
|
784
|
+
try {
|
|
785
|
+
const { handleAsanaCallback } = await import("./connectors/asana.js");
|
|
786
|
+
const code = parsedUrl.searchParams.get("code");
|
|
787
|
+
const state = parsedUrl.searchParams.get("state");
|
|
788
|
+
const error = parsedUrl.searchParams.get("error");
|
|
789
|
+
const result = await handleAsanaCallback(code, state, error);
|
|
790
|
+
res.writeHead(result.status, {
|
|
791
|
+
"Content-Type": result.contentType ?? "text/html",
|
|
792
|
+
});
|
|
793
|
+
res.end(result.body);
|
|
794
|
+
}
|
|
795
|
+
catch (err) {
|
|
796
|
+
if (!res.headersSent) {
|
|
797
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
798
|
+
res.end(JSON.stringify({
|
|
799
|
+
error: err instanceof Error ? err.message : String(err),
|
|
800
|
+
}));
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
})();
|
|
804
|
+
return true;
|
|
805
|
+
}
|
|
806
|
+
if (parsedUrl.pathname === "/connections/asana/test" &&
|
|
807
|
+
req.method === "POST") {
|
|
808
|
+
void (async () => {
|
|
809
|
+
try {
|
|
810
|
+
const { handleAsanaTest } = await import("./connectors/asana.js");
|
|
811
|
+
const result = await handleAsanaTest();
|
|
812
|
+
res.writeHead(result.status, {
|
|
813
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
814
|
+
});
|
|
815
|
+
res.end(result.body);
|
|
816
|
+
}
|
|
817
|
+
catch (err) {
|
|
818
|
+
if (!res.headersSent) {
|
|
819
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
820
|
+
res.end(JSON.stringify({
|
|
821
|
+
error: err instanceof Error ? err.message : String(err),
|
|
822
|
+
}));
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
})();
|
|
826
|
+
return true;
|
|
827
|
+
}
|
|
828
|
+
if (parsedUrl.pathname === "/connections/asana" && req.method === "DELETE") {
|
|
829
|
+
void (async () => {
|
|
830
|
+
try {
|
|
831
|
+
const { handleAsanaDisconnect } = await import("./connectors/asana.js");
|
|
832
|
+
const result = await handleAsanaDisconnect();
|
|
833
|
+
res.writeHead(result.status, {
|
|
834
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
835
|
+
});
|
|
836
|
+
res.end(result.body);
|
|
837
|
+
}
|
|
838
|
+
catch (err) {
|
|
839
|
+
if (!res.headersSent) {
|
|
840
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
841
|
+
res.end(JSON.stringify({
|
|
842
|
+
error: err instanceof Error ? err.message : String(err),
|
|
843
|
+
}));
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
})();
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
849
|
+
// ── GitLab connector routes ────────────────────────────────────
|
|
850
|
+
if ((parsedUrl.pathname === "/connections/gitlab/auth" ||
|
|
851
|
+
parsedUrl.pathname === "/connections/gitlab/authorize") &&
|
|
852
|
+
req.method === "GET") {
|
|
853
|
+
void (async () => {
|
|
854
|
+
try {
|
|
855
|
+
const { handleGitLabAuthorize } = await import("./connectors/gitlab.js");
|
|
856
|
+
const result = handleGitLabAuthorize();
|
|
857
|
+
if (result.redirect) {
|
|
858
|
+
res.writeHead(302, { Location: result.redirect });
|
|
859
|
+
res.end();
|
|
860
|
+
}
|
|
861
|
+
else {
|
|
862
|
+
res.writeHead(result.status, {
|
|
863
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
864
|
+
});
|
|
865
|
+
res.end(result.body);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
catch (err) {
|
|
869
|
+
if (!res.headersSent) {
|
|
870
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
871
|
+
res.end(JSON.stringify({
|
|
872
|
+
error: err instanceof Error ? err.message : String(err),
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
})();
|
|
877
|
+
return true;
|
|
878
|
+
}
|
|
879
|
+
if (parsedUrl.pathname === "/connections/gitlab/callback" &&
|
|
880
|
+
req.method === "GET") {
|
|
881
|
+
void (async () => {
|
|
882
|
+
try {
|
|
883
|
+
const { handleGitLabCallback } = await import("./connectors/gitlab.js");
|
|
884
|
+
const code = parsedUrl.searchParams.get("code");
|
|
885
|
+
const state = parsedUrl.searchParams.get("state");
|
|
886
|
+
const error = parsedUrl.searchParams.get("error");
|
|
887
|
+
const result = await handleGitLabCallback(code, state, error);
|
|
888
|
+
res.writeHead(result.status, {
|
|
889
|
+
"Content-Type": result.contentType ?? "text/html",
|
|
890
|
+
});
|
|
891
|
+
res.end(result.body);
|
|
892
|
+
}
|
|
893
|
+
catch (err) {
|
|
894
|
+
if (!res.headersSent) {
|
|
895
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
896
|
+
res.end(JSON.stringify({
|
|
897
|
+
error: err instanceof Error ? err.message : String(err),
|
|
898
|
+
}));
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
})();
|
|
902
|
+
return true;
|
|
903
|
+
}
|
|
904
|
+
if (parsedUrl.pathname === "/connections/gitlab/test" &&
|
|
905
|
+
req.method === "POST") {
|
|
906
|
+
void (async () => {
|
|
907
|
+
try {
|
|
908
|
+
const { handleGitLabTest } = await import("./connectors/gitlab.js");
|
|
909
|
+
const result = await handleGitLabTest();
|
|
910
|
+
res.writeHead(result.status, {
|
|
911
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
912
|
+
});
|
|
913
|
+
res.end(result.body);
|
|
914
|
+
}
|
|
915
|
+
catch (err) {
|
|
916
|
+
if (!res.headersSent) {
|
|
917
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
918
|
+
res.end(JSON.stringify({
|
|
919
|
+
error: err instanceof Error ? err.message : String(err),
|
|
920
|
+
}));
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
})();
|
|
924
|
+
return true;
|
|
925
|
+
}
|
|
926
|
+
if (parsedUrl.pathname === "/connections/gitlab" && req.method === "DELETE") {
|
|
927
|
+
void (async () => {
|
|
928
|
+
try {
|
|
929
|
+
const { handleGitLabDisconnect } = await import("./connectors/gitlab.js");
|
|
930
|
+
const result = await handleGitLabDisconnect();
|
|
931
|
+
res.writeHead(result.status, {
|
|
932
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
933
|
+
});
|
|
934
|
+
res.end(result.body);
|
|
935
|
+
}
|
|
936
|
+
catch (err) {
|
|
937
|
+
if (!res.headersSent) {
|
|
938
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
939
|
+
res.end(JSON.stringify({
|
|
940
|
+
error: err instanceof Error ? err.message : String(err),
|
|
941
|
+
}));
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
})();
|
|
945
|
+
return true;
|
|
946
|
+
}
|
|
947
|
+
// ── Notion routes ──────────────────────────────────────────────
|
|
948
|
+
if (parsedUrl.pathname === "/connections/notion/connect" &&
|
|
949
|
+
req.method === "POST") {
|
|
950
|
+
const chunks = [];
|
|
951
|
+
req.on("data", (c) => chunks.push(c));
|
|
952
|
+
req.on("end", () => {
|
|
953
|
+
void (async () => {
|
|
954
|
+
try {
|
|
955
|
+
const { handleNotionConnect } = await import("./connectors/notion.js");
|
|
956
|
+
const result = await handleNotionConnect(Buffer.concat(chunks).toString("utf-8"));
|
|
957
|
+
res.writeHead(result.status, {
|
|
958
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
959
|
+
});
|
|
960
|
+
res.end(result.body);
|
|
961
|
+
}
|
|
962
|
+
catch (err) {
|
|
963
|
+
if (!res.headersSent) {
|
|
964
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
965
|
+
res.end(JSON.stringify({
|
|
966
|
+
error: err instanceof Error ? err.message : String(err),
|
|
967
|
+
}));
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
})();
|
|
971
|
+
});
|
|
972
|
+
return true;
|
|
973
|
+
}
|
|
974
|
+
if (parsedUrl.pathname === "/connections/notion/test" &&
|
|
975
|
+
req.method === "POST") {
|
|
976
|
+
void (async () => {
|
|
977
|
+
try {
|
|
978
|
+
const { handleNotionTest } = await import("./connectors/notion.js");
|
|
979
|
+
const result = await handleNotionTest();
|
|
980
|
+
res.writeHead(result.status, {
|
|
981
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
982
|
+
});
|
|
983
|
+
res.end(result.body);
|
|
984
|
+
}
|
|
985
|
+
catch (err) {
|
|
986
|
+
if (!res.headersSent) {
|
|
987
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
988
|
+
res.end(JSON.stringify({
|
|
989
|
+
error: err instanceof Error ? err.message : String(err),
|
|
990
|
+
}));
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
})();
|
|
994
|
+
return true;
|
|
995
|
+
}
|
|
996
|
+
if (parsedUrl.pathname === "/connections/notion" && req.method === "DELETE") {
|
|
997
|
+
void (async () => {
|
|
998
|
+
try {
|
|
999
|
+
const { handleNotionDisconnect } = await import("./connectors/notion.js");
|
|
1000
|
+
const result = handleNotionDisconnect();
|
|
1001
|
+
res.writeHead(result.status, {
|
|
1002
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1003
|
+
});
|
|
1004
|
+
res.end(result.body);
|
|
1005
|
+
}
|
|
1006
|
+
catch (err) {
|
|
1007
|
+
if (!res.headersSent) {
|
|
1008
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1009
|
+
res.end(JSON.stringify({
|
|
1010
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1011
|
+
}));
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
})();
|
|
1015
|
+
return true;
|
|
1016
|
+
}
|
|
1017
|
+
// ── Confluence routes ───────────────────────────────────────────
|
|
1018
|
+
if (parsedUrl.pathname === "/connections/confluence/connect" &&
|
|
1019
|
+
req.method === "POST") {
|
|
1020
|
+
const chunks = [];
|
|
1021
|
+
req.on("data", (c) => chunks.push(c));
|
|
1022
|
+
req.on("end", () => {
|
|
1023
|
+
void (async () => {
|
|
1024
|
+
try {
|
|
1025
|
+
const { handleConfluenceConnect } = await import("./connectors/confluence.js");
|
|
1026
|
+
const result = await handleConfluenceConnect(Buffer.concat(chunks).toString("utf-8"));
|
|
1027
|
+
res.writeHead(result.status, {
|
|
1028
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1029
|
+
});
|
|
1030
|
+
res.end(result.body);
|
|
1031
|
+
}
|
|
1032
|
+
catch (err) {
|
|
1033
|
+
if (!res.headersSent) {
|
|
1034
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1035
|
+
res.end(JSON.stringify({
|
|
1036
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1037
|
+
}));
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
})();
|
|
1041
|
+
});
|
|
1042
|
+
return true;
|
|
1043
|
+
}
|
|
1044
|
+
if (parsedUrl.pathname === "/connections/confluence/test" &&
|
|
1045
|
+
req.method === "POST") {
|
|
1046
|
+
void (async () => {
|
|
1047
|
+
try {
|
|
1048
|
+
const { handleConfluenceTest } = await import("./connectors/confluence.js");
|
|
1049
|
+
const result = await handleConfluenceTest();
|
|
1050
|
+
res.writeHead(result.status, {
|
|
1051
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1052
|
+
});
|
|
1053
|
+
res.end(result.body);
|
|
1054
|
+
}
|
|
1055
|
+
catch (err) {
|
|
1056
|
+
if (!res.headersSent) {
|
|
1057
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1058
|
+
res.end(JSON.stringify({
|
|
1059
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1060
|
+
}));
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
})();
|
|
1064
|
+
return true;
|
|
1065
|
+
}
|
|
1066
|
+
if (parsedUrl.pathname === "/connections/confluence" &&
|
|
1067
|
+
req.method === "DELETE") {
|
|
1068
|
+
void (async () => {
|
|
1069
|
+
try {
|
|
1070
|
+
const { handleConfluenceDisconnect } = await import("./connectors/confluence.js");
|
|
1071
|
+
const result = handleConfluenceDisconnect();
|
|
1072
|
+
res.writeHead(result.status, {
|
|
1073
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1074
|
+
});
|
|
1075
|
+
res.end(result.body);
|
|
1076
|
+
}
|
|
1077
|
+
catch (err) {
|
|
1078
|
+
if (!res.headersSent) {
|
|
1079
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1080
|
+
res.end(JSON.stringify({
|
|
1081
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1082
|
+
}));
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
})();
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
1088
|
+
// ── Zendesk routes ──────────────────────────────────────────────
|
|
1089
|
+
if (parsedUrl.pathname === "/connections/zendesk/connect" &&
|
|
1090
|
+
req.method === "POST") {
|
|
1091
|
+
const chunks = [];
|
|
1092
|
+
req.on("data", (c) => chunks.push(c));
|
|
1093
|
+
req.on("end", () => {
|
|
1094
|
+
void (async () => {
|
|
1095
|
+
try {
|
|
1096
|
+
const { handleZendeskConnect } = await import("./connectors/zendesk.js");
|
|
1097
|
+
const result = await handleZendeskConnect(Buffer.concat(chunks).toString("utf-8"));
|
|
1098
|
+
res.writeHead(result.status, {
|
|
1099
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1100
|
+
});
|
|
1101
|
+
res.end(result.body);
|
|
1102
|
+
}
|
|
1103
|
+
catch (err) {
|
|
1104
|
+
if (!res.headersSent) {
|
|
1105
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1106
|
+
res.end(JSON.stringify({
|
|
1107
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1108
|
+
}));
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
})();
|
|
1112
|
+
});
|
|
1113
|
+
return true;
|
|
1114
|
+
}
|
|
1115
|
+
if (parsedUrl.pathname === "/connections/zendesk/test" &&
|
|
1116
|
+
req.method === "POST") {
|
|
1117
|
+
void (async () => {
|
|
1118
|
+
try {
|
|
1119
|
+
const { handleZendeskTest } = await import("./connectors/zendesk.js");
|
|
1120
|
+
const result = await handleZendeskTest();
|
|
1121
|
+
res.writeHead(result.status, {
|
|
1122
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1123
|
+
});
|
|
1124
|
+
res.end(result.body);
|
|
1125
|
+
}
|
|
1126
|
+
catch (err) {
|
|
1127
|
+
if (!res.headersSent) {
|
|
1128
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1129
|
+
res.end(JSON.stringify({
|
|
1130
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1131
|
+
}));
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
})();
|
|
1135
|
+
return true;
|
|
1136
|
+
}
|
|
1137
|
+
if (parsedUrl.pathname === "/connections/zendesk" &&
|
|
1138
|
+
req.method === "DELETE") {
|
|
1139
|
+
void (async () => {
|
|
1140
|
+
try {
|
|
1141
|
+
const { handleZendeskDisconnect } = await import("./connectors/zendesk.js");
|
|
1142
|
+
const result = handleZendeskDisconnect();
|
|
1143
|
+
res.writeHead(result.status, {
|
|
1144
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1145
|
+
});
|
|
1146
|
+
res.end(result.body);
|
|
1147
|
+
}
|
|
1148
|
+
catch (err) {
|
|
1149
|
+
if (!res.headersSent) {
|
|
1150
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1151
|
+
res.end(JSON.stringify({
|
|
1152
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1153
|
+
}));
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
})();
|
|
1157
|
+
return true;
|
|
1158
|
+
}
|
|
1159
|
+
// ── Intercom routes ─────────────────────────────────────────────
|
|
1160
|
+
if (parsedUrl.pathname === "/connections/intercom/connect" &&
|
|
1161
|
+
req.method === "POST") {
|
|
1162
|
+
const chunks = [];
|
|
1163
|
+
req.on("data", (c) => chunks.push(c));
|
|
1164
|
+
req.on("end", () => {
|
|
1165
|
+
void (async () => {
|
|
1166
|
+
try {
|
|
1167
|
+
const { handleIntercomConnect } = await import("./connectors/intercom.js");
|
|
1168
|
+
const result = await handleIntercomConnect(Buffer.concat(chunks).toString("utf-8"));
|
|
1169
|
+
res.writeHead(result.status, {
|
|
1170
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1171
|
+
});
|
|
1172
|
+
res.end(result.body);
|
|
1173
|
+
}
|
|
1174
|
+
catch (err) {
|
|
1175
|
+
if (!res.headersSent) {
|
|
1176
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1177
|
+
res.end(JSON.stringify({
|
|
1178
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1179
|
+
}));
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
})();
|
|
1183
|
+
});
|
|
1184
|
+
return true;
|
|
1185
|
+
}
|
|
1186
|
+
if (parsedUrl.pathname === "/connections/intercom/test" &&
|
|
1187
|
+
req.method === "POST") {
|
|
1188
|
+
void (async () => {
|
|
1189
|
+
try {
|
|
1190
|
+
const { handleIntercomTest } = await import("./connectors/intercom.js");
|
|
1191
|
+
const result = await handleIntercomTest();
|
|
1192
|
+
res.writeHead(result.status, {
|
|
1193
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1194
|
+
});
|
|
1195
|
+
res.end(result.body);
|
|
1196
|
+
}
|
|
1197
|
+
catch (err) {
|
|
1198
|
+
if (!res.headersSent) {
|
|
1199
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1200
|
+
res.end(JSON.stringify({
|
|
1201
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1202
|
+
}));
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
})();
|
|
1206
|
+
return true;
|
|
1207
|
+
}
|
|
1208
|
+
if (parsedUrl.pathname === "/connections/intercom" &&
|
|
1209
|
+
req.method === "DELETE") {
|
|
1210
|
+
void (async () => {
|
|
1211
|
+
try {
|
|
1212
|
+
const { handleIntercomDisconnect } = await import("./connectors/intercom.js");
|
|
1213
|
+
const result = handleIntercomDisconnect();
|
|
1214
|
+
res.writeHead(result.status, {
|
|
1215
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1216
|
+
});
|
|
1217
|
+
res.end(result.body);
|
|
1218
|
+
}
|
|
1219
|
+
catch (err) {
|
|
1220
|
+
if (!res.headersSent) {
|
|
1221
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1222
|
+
res.end(JSON.stringify({
|
|
1223
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1224
|
+
}));
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
})();
|
|
1228
|
+
return true;
|
|
1229
|
+
}
|
|
1230
|
+
// ── HubSpot routes ─────────────────────────────────────────────
|
|
1231
|
+
if (parsedUrl.pathname === "/connections/hubspot/connect" &&
|
|
1232
|
+
req.method === "POST") {
|
|
1233
|
+
const chunks = [];
|
|
1234
|
+
req.on("data", (c) => chunks.push(c));
|
|
1235
|
+
req.on("end", () => {
|
|
1236
|
+
void (async () => {
|
|
1237
|
+
try {
|
|
1238
|
+
const { handleHubSpotConnect } = await import("./connectors/hubspot.js");
|
|
1239
|
+
const result = await handleHubSpotConnect(Buffer.concat(chunks).toString("utf-8"));
|
|
1240
|
+
res.writeHead(result.status, {
|
|
1241
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1242
|
+
});
|
|
1243
|
+
res.end(result.body);
|
|
1244
|
+
}
|
|
1245
|
+
catch (err) {
|
|
1246
|
+
if (!res.headersSent) {
|
|
1247
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1248
|
+
res.end(JSON.stringify({
|
|
1249
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1250
|
+
}));
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
})();
|
|
1254
|
+
});
|
|
1255
|
+
return true;
|
|
1256
|
+
}
|
|
1257
|
+
if (parsedUrl.pathname === "/connections/hubspot/test" &&
|
|
1258
|
+
req.method === "POST") {
|
|
1259
|
+
void (async () => {
|
|
1260
|
+
try {
|
|
1261
|
+
const { handleHubSpotTest } = await import("./connectors/hubspot.js");
|
|
1262
|
+
const result = await handleHubSpotTest();
|
|
1263
|
+
res.writeHead(result.status, {
|
|
1264
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1265
|
+
});
|
|
1266
|
+
res.end(result.body);
|
|
1267
|
+
}
|
|
1268
|
+
catch (err) {
|
|
1269
|
+
if (!res.headersSent) {
|
|
1270
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1271
|
+
res.end(JSON.stringify({
|
|
1272
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1273
|
+
}));
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
})();
|
|
1277
|
+
return true;
|
|
1278
|
+
}
|
|
1279
|
+
if (parsedUrl.pathname === "/connections/hubspot" &&
|
|
1280
|
+
req.method === "DELETE") {
|
|
1281
|
+
void (async () => {
|
|
1282
|
+
try {
|
|
1283
|
+
const { handleHubSpotDisconnect } = await import("./connectors/hubspot.js");
|
|
1284
|
+
const result = handleHubSpotDisconnect();
|
|
1285
|
+
res.writeHead(result.status, {
|
|
1286
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1287
|
+
});
|
|
1288
|
+
res.end(result.body);
|
|
1289
|
+
}
|
|
1290
|
+
catch (err) {
|
|
1291
|
+
if (!res.headersSent) {
|
|
1292
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1293
|
+
res.end(JSON.stringify({
|
|
1294
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1295
|
+
}));
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
})();
|
|
1299
|
+
return true;
|
|
1300
|
+
}
|
|
1301
|
+
// ── Datadog routes ─────────────────────────────────────────────
|
|
1302
|
+
if (parsedUrl.pathname === "/connections/datadog/connect" &&
|
|
1303
|
+
req.method === "POST") {
|
|
1304
|
+
const chunks = [];
|
|
1305
|
+
req.on("data", (c) => chunks.push(c));
|
|
1306
|
+
req.on("end", () => {
|
|
1307
|
+
void (async () => {
|
|
1308
|
+
try {
|
|
1309
|
+
const { handleDatadogConnect } = await import("./connectors/datadog.js");
|
|
1310
|
+
const result = await handleDatadogConnect(Buffer.concat(chunks).toString("utf-8"));
|
|
1311
|
+
res.writeHead(result.status, {
|
|
1312
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1313
|
+
});
|
|
1314
|
+
res.end(result.body);
|
|
1315
|
+
}
|
|
1316
|
+
catch (err) {
|
|
1317
|
+
if (!res.headersSent) {
|
|
1318
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1319
|
+
res.end(JSON.stringify({
|
|
1320
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1321
|
+
}));
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
})();
|
|
1325
|
+
});
|
|
1326
|
+
return true;
|
|
1327
|
+
}
|
|
1328
|
+
if (parsedUrl.pathname === "/connections/datadog/test" &&
|
|
1329
|
+
req.method === "POST") {
|
|
1330
|
+
void (async () => {
|
|
1331
|
+
try {
|
|
1332
|
+
const { handleDatadogTest } = await import("./connectors/datadog.js");
|
|
1333
|
+
const result = await handleDatadogTest();
|
|
1334
|
+
res.writeHead(result.status, {
|
|
1335
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1336
|
+
});
|
|
1337
|
+
res.end(result.body);
|
|
1338
|
+
}
|
|
1339
|
+
catch (err) {
|
|
1340
|
+
if (!res.headersSent) {
|
|
1341
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1342
|
+
res.end(JSON.stringify({
|
|
1343
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1344
|
+
}));
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
})();
|
|
1348
|
+
return true;
|
|
1349
|
+
}
|
|
1350
|
+
if (parsedUrl.pathname === "/connections/datadog" &&
|
|
1351
|
+
req.method === "DELETE") {
|
|
1352
|
+
void (async () => {
|
|
1353
|
+
try {
|
|
1354
|
+
const { handleDatadogDisconnect } = await import("./connectors/datadog.js");
|
|
1355
|
+
const result = handleDatadogDisconnect();
|
|
1356
|
+
res.writeHead(result.status, {
|
|
1357
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1358
|
+
});
|
|
1359
|
+
res.end(result.body);
|
|
1360
|
+
}
|
|
1361
|
+
catch (err) {
|
|
1362
|
+
if (!res.headersSent) {
|
|
1363
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1364
|
+
res.end(JSON.stringify({
|
|
1365
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1366
|
+
}));
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
})();
|
|
1370
|
+
return true;
|
|
1371
|
+
}
|
|
1372
|
+
// ── PagerDuty routes ───────────────────────────────────────────
|
|
1373
|
+
if (parsedUrl.pathname === "/connections/pagerduty/connect" &&
|
|
1374
|
+
req.method === "POST") {
|
|
1375
|
+
const chunks = [];
|
|
1376
|
+
req.on("data", (c) => chunks.push(c));
|
|
1377
|
+
req.on("end", () => {
|
|
1378
|
+
void (async () => {
|
|
1379
|
+
try {
|
|
1380
|
+
const { handlePagerDutyConnect } = await import("./connectors/pagerduty.js");
|
|
1381
|
+
const result = await handlePagerDutyConnect(Buffer.concat(chunks).toString("utf-8"));
|
|
1382
|
+
res.writeHead(result.status, {
|
|
1383
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1384
|
+
});
|
|
1385
|
+
res.end(result.body);
|
|
1386
|
+
}
|
|
1387
|
+
catch (err) {
|
|
1388
|
+
if (!res.headersSent) {
|
|
1389
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1390
|
+
res.end(JSON.stringify({
|
|
1391
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1392
|
+
}));
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
})();
|
|
1396
|
+
});
|
|
1397
|
+
return true;
|
|
1398
|
+
}
|
|
1399
|
+
if (parsedUrl.pathname === "/connections/pagerduty/test" &&
|
|
1400
|
+
req.method === "POST") {
|
|
1401
|
+
void (async () => {
|
|
1402
|
+
try {
|
|
1403
|
+
const { handlePagerDutyTest } = await import("./connectors/pagerduty.js");
|
|
1404
|
+
const result = await handlePagerDutyTest();
|
|
1405
|
+
res.writeHead(result.status, {
|
|
1406
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1407
|
+
});
|
|
1408
|
+
res.end(result.body);
|
|
1409
|
+
}
|
|
1410
|
+
catch (err) {
|
|
1411
|
+
if (!res.headersSent) {
|
|
1412
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1413
|
+
res.end(JSON.stringify({
|
|
1414
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1415
|
+
}));
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
})();
|
|
1419
|
+
return true;
|
|
1420
|
+
}
|
|
1421
|
+
if (parsedUrl.pathname === "/connections/pagerduty" &&
|
|
1422
|
+
req.method === "DELETE") {
|
|
1423
|
+
void (async () => {
|
|
1424
|
+
try {
|
|
1425
|
+
const { handlePagerDutyDisconnect } = await import("./connectors/pagerduty.js");
|
|
1426
|
+
const result = handlePagerDutyDisconnect();
|
|
1427
|
+
res.writeHead(result.status, {
|
|
1428
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1429
|
+
});
|
|
1430
|
+
res.end(result.body);
|
|
1431
|
+
}
|
|
1432
|
+
catch (err) {
|
|
1433
|
+
if (!res.headersSent) {
|
|
1434
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1435
|
+
res.end(JSON.stringify({
|
|
1436
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1437
|
+
}));
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
})();
|
|
1441
|
+
return true;
|
|
1442
|
+
}
|
|
1443
|
+
// ── Stripe routes ───────────────────────────────────────────────
|
|
1444
|
+
if (parsedUrl.pathname === "/connections/stripe/connect" &&
|
|
1445
|
+
req.method === "POST") {
|
|
1446
|
+
let body = "";
|
|
1447
|
+
req.on("data", (chunk) => {
|
|
1448
|
+
body += chunk.toString();
|
|
1449
|
+
});
|
|
1450
|
+
req.on("end", () => {
|
|
1451
|
+
void (async () => {
|
|
1452
|
+
try {
|
|
1453
|
+
const { handleStripeConnect } = await import("./connectors/stripe.js");
|
|
1454
|
+
const result = await handleStripeConnect(body);
|
|
1455
|
+
res.writeHead(result.status, {
|
|
1456
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1457
|
+
});
|
|
1458
|
+
res.end(result.body);
|
|
1459
|
+
}
|
|
1460
|
+
catch (err) {
|
|
1461
|
+
if (!res.headersSent) {
|
|
1462
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1463
|
+
res.end(JSON.stringify({
|
|
1464
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1465
|
+
}));
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
})();
|
|
1469
|
+
});
|
|
1470
|
+
return true;
|
|
1471
|
+
}
|
|
1472
|
+
if (parsedUrl.pathname === "/connections/stripe/test" &&
|
|
1473
|
+
req.method === "POST") {
|
|
1474
|
+
void (async () => {
|
|
1475
|
+
try {
|
|
1476
|
+
const { handleStripeTest } = await import("./connectors/stripe.js");
|
|
1477
|
+
const result = await handleStripeTest();
|
|
1478
|
+
res.writeHead(result.status, {
|
|
1479
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1480
|
+
});
|
|
1481
|
+
res.end(result.body);
|
|
1482
|
+
}
|
|
1483
|
+
catch (err) {
|
|
1484
|
+
if (!res.headersSent) {
|
|
1485
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1486
|
+
res.end(JSON.stringify({
|
|
1487
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1488
|
+
}));
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
})();
|
|
1492
|
+
return true;
|
|
1493
|
+
}
|
|
1494
|
+
if (parsedUrl.pathname === "/connections/stripe" && req.method === "DELETE") {
|
|
1495
|
+
void (async () => {
|
|
1496
|
+
try {
|
|
1497
|
+
const { handleStripeDisconnect } = await import("./connectors/stripe.js");
|
|
1498
|
+
const result = handleStripeDisconnect();
|
|
1499
|
+
res.writeHead(result.status, {
|
|
1500
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1501
|
+
});
|
|
1502
|
+
res.end(result.body);
|
|
1503
|
+
}
|
|
1504
|
+
catch (err) {
|
|
1505
|
+
if (!res.headersSent) {
|
|
1506
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1507
|
+
res.end(JSON.stringify({
|
|
1508
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1509
|
+
}));
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
})();
|
|
1513
|
+
return true;
|
|
1514
|
+
}
|
|
1515
|
+
// ── Google Calendar routes ──────────────────────────────────────
|
|
1516
|
+
if (parsedUrl.pathname === "/connections/google-calendar/auth" &&
|
|
1517
|
+
req.method === "GET") {
|
|
1518
|
+
void (async () => {
|
|
1519
|
+
try {
|
|
1520
|
+
const { handleCalendarAuthRedirect } = await import("./connectors/googleCalendar.js");
|
|
1521
|
+
const result = handleCalendarAuthRedirect();
|
|
1522
|
+
if (result.redirect) {
|
|
1523
|
+
res.writeHead(302, { Location: result.redirect });
|
|
1524
|
+
res.end();
|
|
1525
|
+
}
|
|
1526
|
+
else {
|
|
1527
|
+
res.writeHead(result.status, {
|
|
1528
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1529
|
+
});
|
|
1530
|
+
res.end(result.body);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
catch (err) {
|
|
1534
|
+
if (!res.headersSent) {
|
|
1535
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1536
|
+
res.end(JSON.stringify({
|
|
1537
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1538
|
+
}));
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
})();
|
|
1542
|
+
return true;
|
|
1543
|
+
}
|
|
1544
|
+
if (parsedUrl.pathname === "/connections/google-calendar/callback" &&
|
|
1545
|
+
req.method === "GET") {
|
|
1546
|
+
void (async () => {
|
|
1547
|
+
try {
|
|
1548
|
+
const { handleCalendarCallback } = await import("./connectors/googleCalendar.js");
|
|
1549
|
+
const code = parsedUrl.searchParams.get("code");
|
|
1550
|
+
const state = parsedUrl.searchParams.get("state");
|
|
1551
|
+
const error = parsedUrl.searchParams.get("error");
|
|
1552
|
+
const result = await handleCalendarCallback(code, state, error);
|
|
1553
|
+
res.writeHead(result.status, {
|
|
1554
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1555
|
+
});
|
|
1556
|
+
res.end(result.body);
|
|
1557
|
+
}
|
|
1558
|
+
catch (err) {
|
|
1559
|
+
if (!res.headersSent) {
|
|
1560
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1561
|
+
res.end(JSON.stringify({
|
|
1562
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1563
|
+
}));
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
})();
|
|
1567
|
+
return true;
|
|
1568
|
+
}
|
|
1569
|
+
if (parsedUrl.pathname === "/connections/google-calendar/test" &&
|
|
1570
|
+
req.method === "POST") {
|
|
1571
|
+
void (async () => {
|
|
1572
|
+
try {
|
|
1573
|
+
const { handleCalendarTest } = await import("./connectors/googleCalendar.js");
|
|
1574
|
+
const result = await handleCalendarTest();
|
|
1575
|
+
res.writeHead(result.status, {
|
|
1576
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1577
|
+
});
|
|
1578
|
+
res.end(result.body);
|
|
1579
|
+
}
|
|
1580
|
+
catch (err) {
|
|
1581
|
+
if (!res.headersSent) {
|
|
1582
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1583
|
+
res.end(JSON.stringify({
|
|
1584
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1585
|
+
}));
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
})();
|
|
1589
|
+
return true;
|
|
1590
|
+
}
|
|
1591
|
+
if (parsedUrl.pathname === "/connections/google-calendar" &&
|
|
1592
|
+
req.method === "DELETE") {
|
|
1593
|
+
void (async () => {
|
|
1594
|
+
try {
|
|
1595
|
+
const { handleCalendarDisconnect } = await import("./connectors/googleCalendar.js");
|
|
1596
|
+
const result = await handleCalendarDisconnect();
|
|
1597
|
+
res.writeHead(result.status, {
|
|
1598
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1599
|
+
});
|
|
1600
|
+
res.end(result.body);
|
|
1601
|
+
}
|
|
1602
|
+
catch (err) {
|
|
1603
|
+
if (!res.headersSent) {
|
|
1604
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1605
|
+
res.end(JSON.stringify({
|
|
1606
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1607
|
+
}));
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
})();
|
|
1611
|
+
return true;
|
|
1612
|
+
}
|
|
1613
|
+
// ── Google Drive routes ─────────────────────────────────────────
|
|
1614
|
+
if (parsedUrl.pathname === "/connections/google-drive/auth" &&
|
|
1615
|
+
req.method === "GET") {
|
|
1616
|
+
void (async () => {
|
|
1617
|
+
try {
|
|
1618
|
+
const { handleDriveAuthRedirect } = await import("./connectors/googleDrive.js");
|
|
1619
|
+
const result = handleDriveAuthRedirect();
|
|
1620
|
+
if (result.redirect) {
|
|
1621
|
+
res.writeHead(302, { Location: result.redirect });
|
|
1622
|
+
res.end();
|
|
1623
|
+
}
|
|
1624
|
+
else {
|
|
1625
|
+
res.writeHead(result.status, {
|
|
1626
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1627
|
+
});
|
|
1628
|
+
res.end(result.body);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
catch (err) {
|
|
1632
|
+
if (!res.headersSent) {
|
|
1633
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1634
|
+
res.end(JSON.stringify({
|
|
1635
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1636
|
+
}));
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
})();
|
|
1640
|
+
return true;
|
|
1641
|
+
}
|
|
1642
|
+
if (parsedUrl.pathname === "/connections/google-drive/callback" &&
|
|
1643
|
+
req.method === "GET") {
|
|
1644
|
+
void (async () => {
|
|
1645
|
+
try {
|
|
1646
|
+
const { handleDriveCallback } = await import("./connectors/googleDrive.js");
|
|
1647
|
+
const code = parsedUrl.searchParams.get("code");
|
|
1648
|
+
const state = parsedUrl.searchParams.get("state");
|
|
1649
|
+
const error = parsedUrl.searchParams.get("error");
|
|
1650
|
+
const result = await handleDriveCallback(code, state, error);
|
|
1651
|
+
res.writeHead(result.status, {
|
|
1652
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1653
|
+
});
|
|
1654
|
+
res.end(result.body);
|
|
1655
|
+
}
|
|
1656
|
+
catch (err) {
|
|
1657
|
+
if (!res.headersSent) {
|
|
1658
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1659
|
+
res.end(JSON.stringify({
|
|
1660
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1661
|
+
}));
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
})();
|
|
1665
|
+
return true;
|
|
1666
|
+
}
|
|
1667
|
+
if (parsedUrl.pathname === "/connections/google-drive/test" &&
|
|
1668
|
+
req.method === "POST") {
|
|
1669
|
+
void (async () => {
|
|
1670
|
+
try {
|
|
1671
|
+
const { handleDriveTest } = await import("./connectors/googleDrive.js");
|
|
1672
|
+
const result = await handleDriveTest();
|
|
1673
|
+
res.writeHead(result.status, {
|
|
1674
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1675
|
+
});
|
|
1676
|
+
res.end(result.body);
|
|
1677
|
+
}
|
|
1678
|
+
catch (err) {
|
|
1679
|
+
if (!res.headersSent) {
|
|
1680
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1681
|
+
res.end(JSON.stringify({
|
|
1682
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1683
|
+
}));
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
})();
|
|
1687
|
+
return true;
|
|
1688
|
+
}
|
|
1689
|
+
if (parsedUrl.pathname === "/connections/google-drive" &&
|
|
1690
|
+
req.method === "DELETE") {
|
|
1691
|
+
void (async () => {
|
|
1692
|
+
try {
|
|
1693
|
+
const { handleDriveDisconnect } = await import("./connectors/googleDrive.js");
|
|
1694
|
+
const result = await handleDriveDisconnect();
|
|
1695
|
+
res.writeHead(result.status, {
|
|
1696
|
+
"Content-Type": result.contentType ?? "application/json",
|
|
1697
|
+
});
|
|
1698
|
+
res.end(result.body);
|
|
1699
|
+
}
|
|
1700
|
+
catch (err) {
|
|
1701
|
+
if (!res.headersSent) {
|
|
1702
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1703
|
+
res.end(JSON.stringify({
|
|
1704
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1705
|
+
}));
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
})();
|
|
1709
|
+
return true;
|
|
1710
|
+
}
|
|
1711
|
+
return false;
|
|
1712
|
+
}
|
|
1713
|
+
//# sourceMappingURL=connectorRoutes.js.map
|