oauth-callback 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +9 -5
- package/dist/mcp.js +9 -5
- package/dist/server.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/server.ts +12 -9
package/dist/index.js
CHANGED
|
@@ -718,6 +718,7 @@ class BaseCallbackServer {
|
|
|
718
718
|
successHtml;
|
|
719
719
|
errorHtml;
|
|
720
720
|
onRequest;
|
|
721
|
+
callbackReceived = false;
|
|
721
722
|
abortHandler;
|
|
722
723
|
signal;
|
|
723
724
|
setup(options) {
|
|
@@ -743,6 +744,7 @@ class BaseCallbackServer {
|
|
|
743
744
|
for (const [key, value] of url.searchParams)
|
|
744
745
|
params[key] = value;
|
|
745
746
|
listener.resolve(params);
|
|
747
|
+
this.callbackReceived = true;
|
|
746
748
|
return new Response(generateCallbackHTML(params, this.successHtml, this.errorHtml), {
|
|
747
749
|
status: 200,
|
|
748
750
|
headers: { "Content-Type": "text/html" }
|
|
@@ -751,18 +753,21 @@ class BaseCallbackServer {
|
|
|
751
753
|
async waitForCallback(path2, timeout) {
|
|
752
754
|
if (this.callbackListeners.has(path2))
|
|
753
755
|
return Promise.reject(new Error(`A listener for the path "${path2}" is already active.`));
|
|
756
|
+
let timeoutId;
|
|
754
757
|
try {
|
|
755
758
|
return await Promise.race([
|
|
756
759
|
new Promise((resolve, reject) => {
|
|
757
760
|
this.callbackListeners.set(path2, { resolve, reject });
|
|
758
761
|
}),
|
|
759
762
|
new Promise((_, reject) => {
|
|
760
|
-
setTimeout(() => {
|
|
763
|
+
timeoutId = setTimeout(() => {
|
|
761
764
|
reject(new Error(`OAuth callback timeout after ${timeout}ms waiting for ${path2}`));
|
|
762
765
|
}, timeout);
|
|
763
766
|
})
|
|
764
767
|
]);
|
|
765
768
|
} finally {
|
|
769
|
+
if (timeoutId)
|
|
770
|
+
clearTimeout(timeoutId);
|
|
766
771
|
this.callbackListeners.delete(path2);
|
|
767
772
|
}
|
|
768
773
|
}
|
|
@@ -792,11 +797,10 @@ class BunCallbackServer extends BaseCallbackServer {
|
|
|
792
797
|
async stopServer() {
|
|
793
798
|
if (!this.server)
|
|
794
799
|
return;
|
|
795
|
-
|
|
796
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
800
|
+
if (this.callbackReceived) {
|
|
801
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
797
802
|
}
|
|
798
|
-
|
|
799
|
-
this.server.stop();
|
|
803
|
+
this.server.stop(true);
|
|
800
804
|
this.server = undefined;
|
|
801
805
|
}
|
|
802
806
|
}
|
package/dist/mcp.js
CHANGED
|
@@ -738,6 +738,7 @@ class BaseCallbackServer {
|
|
|
738
738
|
successHtml;
|
|
739
739
|
errorHtml;
|
|
740
740
|
onRequest;
|
|
741
|
+
callbackReceived = false;
|
|
741
742
|
abortHandler;
|
|
742
743
|
signal;
|
|
743
744
|
setup(options) {
|
|
@@ -763,6 +764,7 @@ class BaseCallbackServer {
|
|
|
763
764
|
for (const [key, value] of url.searchParams)
|
|
764
765
|
params[key] = value;
|
|
765
766
|
listener.resolve(params);
|
|
767
|
+
this.callbackReceived = true;
|
|
766
768
|
return new Response(generateCallbackHTML(params, this.successHtml, this.errorHtml), {
|
|
767
769
|
status: 200,
|
|
768
770
|
headers: { "Content-Type": "text/html" }
|
|
@@ -771,18 +773,21 @@ class BaseCallbackServer {
|
|
|
771
773
|
async waitForCallback(path2, timeout) {
|
|
772
774
|
if (this.callbackListeners.has(path2))
|
|
773
775
|
return Promise.reject(new Error(`A listener for the path "${path2}" is already active.`));
|
|
776
|
+
let timeoutId;
|
|
774
777
|
try {
|
|
775
778
|
return await Promise.race([
|
|
776
779
|
new Promise((resolve, reject) => {
|
|
777
780
|
this.callbackListeners.set(path2, { resolve, reject });
|
|
778
781
|
}),
|
|
779
782
|
new Promise((_, reject) => {
|
|
780
|
-
setTimeout(() => {
|
|
783
|
+
timeoutId = setTimeout(() => {
|
|
781
784
|
reject(new Error(`OAuth callback timeout after ${timeout}ms waiting for ${path2}`));
|
|
782
785
|
}, timeout);
|
|
783
786
|
})
|
|
784
787
|
]);
|
|
785
788
|
} finally {
|
|
789
|
+
if (timeoutId)
|
|
790
|
+
clearTimeout(timeoutId);
|
|
786
791
|
this.callbackListeners.delete(path2);
|
|
787
792
|
}
|
|
788
793
|
}
|
|
@@ -812,11 +817,10 @@ class BunCallbackServer extends BaseCallbackServer {
|
|
|
812
817
|
async stopServer() {
|
|
813
818
|
if (!this.server)
|
|
814
819
|
return;
|
|
815
|
-
|
|
816
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
820
|
+
if (this.callbackReceived) {
|
|
821
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
817
822
|
}
|
|
818
|
-
|
|
819
|
-
this.server.stop();
|
|
823
|
+
this.server.stop(true);
|
|
820
824
|
this.server = undefined;
|
|
821
825
|
}
|
|
822
826
|
}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mHAAmH;IACnH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,oFAAoF;IACpF,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,iEAAiE;IACjE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACxE,4CAA4C;IAC5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mHAAmH;IACnH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,oFAAoF;IACpF,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,iEAAiE;IACjE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACxE,4CAA4C;IAC5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AA8RD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAKrD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oauth-callback",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Lightweight OAuth 2.0 callback handler for Node.js, Deno, and Bun with built-in browser flow and MCP SDK integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oauth",
|
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
"build": "bun run build:templates && bun build ./src/index.ts --outdir=./dist --target=node && bun build ./src/mcp.ts --outdir=./dist --target=node && tsc --declaration --emitDeclarationOnly --outDir ./dist",
|
|
105
105
|
"clean": "rm -rf dist",
|
|
106
106
|
"test": "bun test",
|
|
107
|
+
"test:login": "bun run scripts/test-login.ts",
|
|
107
108
|
"typecheck": "bun tsc -p tsconfig.json --noEmit",
|
|
108
109
|
"format": "bun prettier --write .",
|
|
109
110
|
"format:check": "bun prettier --check .",
|
package/src/server.ts
CHANGED
|
@@ -100,6 +100,7 @@ abstract class BaseCallbackServer implements CallbackServer {
|
|
|
100
100
|
protected successHtml?: string;
|
|
101
101
|
protected errorHtml?: string;
|
|
102
102
|
protected onRequest?: (req: Request) => void;
|
|
103
|
+
protected callbackReceived = false;
|
|
103
104
|
private abortHandler?: () => void;
|
|
104
105
|
private signal?: AbortSignal;
|
|
105
106
|
|
|
@@ -142,6 +143,7 @@ abstract class BaseCallbackServer implements CallbackServer {
|
|
|
142
143
|
|
|
143
144
|
// Resolve the promise for the waiting listener.
|
|
144
145
|
listener.resolve(params);
|
|
146
|
+
this.callbackReceived = true;
|
|
145
147
|
|
|
146
148
|
return new Response(
|
|
147
149
|
generateCallbackHTML(params, this.successHtml, this.errorHtml),
|
|
@@ -164,6 +166,8 @@ abstract class BaseCallbackServer implements CallbackServer {
|
|
|
164
166
|
new Error(`A listener for the path "${path}" is already active.`),
|
|
165
167
|
);
|
|
166
168
|
|
|
169
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
170
|
+
|
|
167
171
|
try {
|
|
168
172
|
// Race a promise that waits for the callback against a promise that rejects on timeout.
|
|
169
173
|
return await Promise.race([
|
|
@@ -173,7 +177,7 @@ abstract class BaseCallbackServer implements CallbackServer {
|
|
|
173
177
|
}),
|
|
174
178
|
// This promise rejects after the specified timeout.
|
|
175
179
|
new Promise<CallbackResult>((_, reject) => {
|
|
176
|
-
setTimeout(() => {
|
|
180
|
+
timeoutId = setTimeout(() => {
|
|
177
181
|
reject(
|
|
178
182
|
new Error(
|
|
179
183
|
`OAuth callback timeout after ${timeout}ms waiting for ${path}`,
|
|
@@ -183,8 +187,9 @@ abstract class BaseCallbackServer implements CallbackServer {
|
|
|
183
187
|
}),
|
|
184
188
|
]);
|
|
185
189
|
} finally {
|
|
186
|
-
// CRITICAL: Always clean up the listener to prevent memory leaks
|
|
187
|
-
//
|
|
190
|
+
// CRITICAL: Always clean up the listener and timeout to prevent memory leaks
|
|
191
|
+
// and allow the process to exit cleanly.
|
|
192
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
188
193
|
this.callbackListeners.delete(path);
|
|
189
194
|
}
|
|
190
195
|
}
|
|
@@ -225,13 +230,11 @@ class BunCallbackServer extends BaseCallbackServer {
|
|
|
225
230
|
|
|
226
231
|
protected async stopServer(): Promise<void> {
|
|
227
232
|
if (!this.server) return;
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
233
|
+
// Brief delay to allow response bytes to flush to the client
|
|
234
|
+
if (this.callbackReceived) {
|
|
235
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
231
236
|
}
|
|
232
|
-
//
|
|
233
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
234
|
-
this.server.stop();
|
|
237
|
+
this.server.stop(true); // Force close connections
|
|
235
238
|
this.server = undefined;
|
|
236
239
|
}
|
|
237
240
|
}
|