@luckystack/server 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/index.js +18 -3
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.3] - 2026-07-20
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Stale-port bug class after a dev auto-increment hop.** When the dev server
|
|
15
|
+
auto-incremented off a busy port (`:80` → `:81`), the bind-address registry
|
|
16
|
+
still held the INTENDED port, so `checkOrigin`'s same-origin CORS entry pointed
|
|
17
|
+
at a port nothing listened on. `listenLuckyStackServer` now re-registers the
|
|
18
|
+
ACTUALLY-bound port inside the listen callback, so every `getBindAddress()`
|
|
19
|
+
reader (CORS foremost) sees reality.
|
|
20
|
+
- **OAuth now targets the actually-bound port after a hop.** The `/auth/api/<provider>`
|
|
21
|
+
authorize route rewrites a `localhost` OAuth `redirect_uri` to the port the
|
|
22
|
+
server bound (via core's `resolveDevCallbackUrl`), matching the token-exchange
|
|
23
|
+
side in `@luckystack/login` — so the OAuth round-trip reaches the live dev
|
|
24
|
+
server even after an auto-increment hop, instead of a frozen dead port.
|
|
25
|
+
- **Loud OAuth port-drift warning on a hop.** The framework auto-targets the bound
|
|
26
|
+
port for OAuth, but a provider console still exact-matches its registered
|
|
27
|
+
redirect URI — so the server now warns (naming both ports) to add the bound port
|
|
28
|
+
to the provider's authorized redirect URIs, or pin the port with
|
|
29
|
+
`SERVER_PORT_AUTO_INCREMENT=0`.
|
|
30
|
+
|
|
10
31
|
## [0.7.1] - 2026-07-18
|
|
11
32
|
|
|
12
33
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
|
|
8
8
|
// src/createServer.ts
|
|
9
9
|
import http from "http";
|
|
10
|
-
import { registerBindAddress, writeBootUuid, getLogger as getLogger13, getProjectConfig as getProjectConfig15, tryCatch as tryCatch10, isProduction as isProduction2, resolveEnvKey as resolveEnvKey5, dispatchHook as dispatchHook8 } from "@luckystack/core";
|
|
10
|
+
import { registerBindAddress, writeBootUuid, getLogger as getLogger13, getProjectConfig as getProjectConfig15, tryCatch as tryCatch10, tryCatchSync as tryCatchSync2, isProduction as isProduction2, resolveEnvKey as resolveEnvKey5, dispatchHook as dispatchHook8 } from "@luckystack/core";
|
|
11
11
|
|
|
12
12
|
// src/httpHandler.ts
|
|
13
13
|
import { randomUUID } from "crypto";
|
|
@@ -457,7 +457,8 @@ import {
|
|
|
457
457
|
dispatchHook as dispatchHook2,
|
|
458
458
|
getLogger,
|
|
459
459
|
getProjectConfig as getProjectConfig5,
|
|
460
|
-
resolveClientIp
|
|
460
|
+
resolveClientIp,
|
|
461
|
+
resolveDevCallbackUrl
|
|
461
462
|
} from "@luckystack/core";
|
|
462
463
|
|
|
463
464
|
// src/httpRoutes/sessionCookie.ts
|
|
@@ -561,7 +562,11 @@ var handleAuthApiRoute = async ({
|
|
|
561
562
|
);
|
|
562
563
|
const authParams = new URLSearchParams({
|
|
563
564
|
client_id: provider.clientID,
|
|
564
|
-
|
|
565
|
+
//? In dev, target the port the server ACTUALLY bound (auto-increment may
|
|
566
|
+
//? have moved it off the frozen `oauthCallbackBase` port). The token
|
|
567
|
+
//? exchange applies the SAME rewrite, so the two redirect_uri values stay
|
|
568
|
+
//? byte-identical as OAuth requires. Prod / non-localhost: unchanged.
|
|
569
|
+
redirect_uri: resolveDevCallbackUrl(provider.callbackURL),
|
|
565
570
|
scope: provider.scope.join(" "),
|
|
566
571
|
response_type: "code",
|
|
567
572
|
prompt: "select_account"
|
|
@@ -2365,10 +2370,20 @@ var listenLuckyStackServer = (httpServer, ip, port, callback) => new Promise((re
|
|
|
2365
2370
|
httpServer.once("error", onError);
|
|
2366
2371
|
httpServer.listen(attemptPort, ip, () => {
|
|
2367
2372
|
httpServer.off("error", onError);
|
|
2373
|
+
registerBindAddress({ ip, port: attemptPort });
|
|
2368
2374
|
if (!isProduction2 && process.env.NODE_ENV !== "test") {
|
|
2369
2375
|
writeDevServerInfo(ip, attemptPort);
|
|
2370
2376
|
process.once("exit", clearDevServerInfo);
|
|
2371
2377
|
}
|
|
2378
|
+
if (attemptPort !== startPort && !isProduction2) {
|
|
2379
|
+
const configuredCallbackBase = tryCatchSync2(() => getProjectConfig15().oauthCallbackBase)[1] ?? "";
|
|
2380
|
+
const callbackPort = /:(\d+)(?:\/|$)/.exec(configuredCallbackBase)?.[1];
|
|
2381
|
+
if (callbackPort && callbackPort !== String(attemptPort)) {
|
|
2382
|
+
getLogger13().warn(
|
|
2383
|
+
`OAuth port drift: the server bound :${String(attemptPort)} but your OAuth callback base is configured for :${callbackPort} (${configuredCallbackBase}). The framework now auto-targets :${String(attemptPort)} for OAuth so the callback reaches THIS server \u2014 but your provider (Google/GitHub/\u2026) still exact-matches its registered redirect URI, so add :${String(attemptPort)} to the authorized redirect URIs, OR set SERVER_PORT_AUTO_INCREMENT=0 to pin :${callbackPort} (stop whatever holds it) instead of hopping.`
|
|
2384
|
+
);
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2372
2387
|
const config = getProjectConfig15();
|
|
2373
2388
|
if (config.logging.socketStartup || config.logging.devLogs) {
|
|
2374
2389
|
getLogger13().info(`Server is running on http://${ip}:${String(attemptPort)}/`);
|