@parix/cli 0.1.7 → 0.1.8
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/cli.cjs +8 -2
- package/dist/cli.js +8 -2
- package/dist/commands/auth.cjs +3 -0
- package/dist/commands/auth.js +3 -0
- package/dist/lib/loopback-server.cjs +25 -3
- package/dist/lib/loopback-server.js +25 -3
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -25,8 +25,14 @@ async function main() {
|
|
|
25
25
|
.addCommand((0, tb_1.createTbCommand)());
|
|
26
26
|
await program.parseAsync(process.argv);
|
|
27
27
|
}
|
|
28
|
-
main()
|
|
28
|
+
main()
|
|
29
|
+
.then(() => {
|
|
30
|
+
// CLIs that open HTTP servers / use undici fetch can leave sockets that keep
|
|
31
|
+
// Node alive after the command is done. Exit explicitly once work is finished.
|
|
32
|
+
process.exit(process.exitCode ?? 0);
|
|
33
|
+
})
|
|
34
|
+
.catch((error) => {
|
|
29
35
|
const message = error instanceof Error ? error.message : String(error);
|
|
30
36
|
prompts_1.log.error(message);
|
|
31
|
-
process.
|
|
37
|
+
process.exit(1);
|
|
32
38
|
});
|
package/dist/cli.js
CHANGED
|
@@ -23,8 +23,14 @@ async function main() {
|
|
|
23
23
|
.addCommand(createTbCommand());
|
|
24
24
|
await program.parseAsync(process.argv);
|
|
25
25
|
}
|
|
26
|
-
main()
|
|
26
|
+
main()
|
|
27
|
+
.then(() => {
|
|
28
|
+
// CLIs that open HTTP servers / use undici fetch can leave sockets that keep
|
|
29
|
+
// Node alive after the command is done. Exit explicitly once work is finished.
|
|
30
|
+
process.exit(process.exitCode ?? 0);
|
|
31
|
+
})
|
|
32
|
+
.catch((error) => {
|
|
27
33
|
const message = error instanceof Error ? error.message : String(error);
|
|
28
34
|
log.error(message);
|
|
29
|
-
process.
|
|
35
|
+
process.exit(1);
|
|
30
36
|
});
|
package/dist/commands/auth.cjs
CHANGED
|
@@ -69,6 +69,9 @@ async function handleLogin(options) {
|
|
|
69
69
|
waitSpinner.start('Waiting for browser callback');
|
|
70
70
|
const callbackResult = await loopbackServer.waitForResult();
|
|
71
71
|
waitSpinner.stop('Received browser callback');
|
|
72
|
+
// Shut down the loopback server before token exchange so browser keep-alive
|
|
73
|
+
// sockets cannot keep the process open after sign-in completes.
|
|
74
|
+
await loopbackServer.close().catch(() => { });
|
|
72
75
|
const tokenSet = await (0, oauth_api_1.exchangeAuthorizationCode)({
|
|
73
76
|
baseUrl,
|
|
74
77
|
code: callbackResult.code,
|
package/dist/commands/auth.js
CHANGED
|
@@ -66,6 +66,9 @@ async function handleLogin(options) {
|
|
|
66
66
|
waitSpinner.start('Waiting for browser callback');
|
|
67
67
|
const callbackResult = await loopbackServer.waitForResult();
|
|
68
68
|
waitSpinner.stop('Received browser callback');
|
|
69
|
+
// Shut down the loopback server before token exchange so browser keep-alive
|
|
70
|
+
// sockets cannot keep the process open after sign-in completes.
|
|
71
|
+
await loopbackServer.close().catch(() => { });
|
|
69
72
|
const tokenSet = await exchangeAuthorizationCode({
|
|
70
73
|
baseUrl,
|
|
71
74
|
code: callbackResult.code,
|
|
@@ -37,6 +37,8 @@ async function startLoopbackServer(options) {
|
|
|
37
37
|
rejectResult = reject;
|
|
38
38
|
});
|
|
39
39
|
server.on('request', (request, response) => {
|
|
40
|
+
// One-shot OAuth loopback: do not keep browser sockets alive after the response.
|
|
41
|
+
response.setHeader('connection', 'close');
|
|
40
42
|
const requestUrl = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
41
43
|
if (requestUrl.pathname === '/favicon.ico') {
|
|
42
44
|
response.writeHead(204);
|
|
@@ -120,17 +122,37 @@ function listen(server, port) {
|
|
|
120
122
|
}
|
|
121
123
|
function closeServer(server) {
|
|
122
124
|
return new Promise((resolve, reject) => {
|
|
125
|
+
let settled = false;
|
|
126
|
+
const finish = (error) => {
|
|
127
|
+
if (settled) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
settled = true;
|
|
131
|
+
if (error) {
|
|
132
|
+
reject(error);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
resolve();
|
|
136
|
+
};
|
|
123
137
|
server.close((error) => {
|
|
124
138
|
if (error) {
|
|
125
139
|
if ('code' in error && error.code === 'ERR_SERVER_NOT_RUNNING') {
|
|
126
|
-
|
|
140
|
+
finish();
|
|
127
141
|
return;
|
|
128
142
|
}
|
|
129
|
-
|
|
143
|
+
finish(error);
|
|
130
144
|
return;
|
|
131
145
|
}
|
|
132
|
-
|
|
146
|
+
finish();
|
|
133
147
|
});
|
|
148
|
+
// `server.close()` waits for existing connections. Browsers often keep the
|
|
149
|
+
// loopback socket open via HTTP keep-alive, which would hang login forever
|
|
150
|
+
// after the session is already stored. Force those sockets closed (Node >= 18.2).
|
|
151
|
+
server.closeAllConnections();
|
|
152
|
+
// Last resort: never let close block the CLI indefinitely.
|
|
153
|
+
setTimeout(() => {
|
|
154
|
+
finish();
|
|
155
|
+
}, 250).unref();
|
|
134
156
|
});
|
|
135
157
|
}
|
|
136
158
|
function buildHtml(title, message) {
|
|
@@ -34,6 +34,8 @@ export async function startLoopbackServer(options) {
|
|
|
34
34
|
rejectResult = reject;
|
|
35
35
|
});
|
|
36
36
|
server.on('request', (request, response) => {
|
|
37
|
+
// One-shot OAuth loopback: do not keep browser sockets alive after the response.
|
|
38
|
+
response.setHeader('connection', 'close');
|
|
37
39
|
const requestUrl = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
38
40
|
if (requestUrl.pathname === '/favicon.ico') {
|
|
39
41
|
response.writeHead(204);
|
|
@@ -117,17 +119,37 @@ function listen(server, port) {
|
|
|
117
119
|
}
|
|
118
120
|
function closeServer(server) {
|
|
119
121
|
return new Promise((resolve, reject) => {
|
|
122
|
+
let settled = false;
|
|
123
|
+
const finish = (error) => {
|
|
124
|
+
if (settled) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
settled = true;
|
|
128
|
+
if (error) {
|
|
129
|
+
reject(error);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
resolve();
|
|
133
|
+
};
|
|
120
134
|
server.close((error) => {
|
|
121
135
|
if (error) {
|
|
122
136
|
if ('code' in error && error.code === 'ERR_SERVER_NOT_RUNNING') {
|
|
123
|
-
|
|
137
|
+
finish();
|
|
124
138
|
return;
|
|
125
139
|
}
|
|
126
|
-
|
|
140
|
+
finish(error);
|
|
127
141
|
return;
|
|
128
142
|
}
|
|
129
|
-
|
|
143
|
+
finish();
|
|
130
144
|
});
|
|
145
|
+
// `server.close()` waits for existing connections. Browsers often keep the
|
|
146
|
+
// loopback socket open via HTTP keep-alive, which would hang login forever
|
|
147
|
+
// after the session is already stored. Force those sockets closed (Node >= 18.2).
|
|
148
|
+
server.closeAllConnections();
|
|
149
|
+
// Last resort: never let close block the CLI indefinitely.
|
|
150
|
+
setTimeout(() => {
|
|
151
|
+
finish();
|
|
152
|
+
}, 250).unref();
|
|
131
153
|
});
|
|
132
154
|
}
|
|
133
155
|
function buildHtml(title, message) {
|