@zerotal/core 1.5.0 → 1.5.1
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 +19 -0
- package/package.json +1 -1
- package/src/helpers/index.ts +5 -7
- package/src/support/env.ts +31 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,25 @@ follows the Zerotal monorepo's unified versioning.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [1.5.1] — 2026-08-15
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **Every development-only surface switched itself off under `zt serve`.**
|
|
16
|
+
`devSurfacesEnabled()` asked `Bun.env["APP_ENV"]` whether this was a development
|
|
17
|
+
environment — but `setAppEnv()` replaces that with the runtime mode before the app is
|
|
18
|
+
created, so it was asking whether `"web"` is development. The answer is no. An app with
|
|
19
|
+
`APP_ENV=development` in its `.env` therefore got **production error pages** from a plain
|
|
20
|
+
`bun zt serve`: no stack trace, no dev overlay.
|
|
21
|
+
|
|
22
|
+
It reads `deployEnv()` now, which is where the deployment name survives. Production and
|
|
23
|
+
staging are unaffected — both still fail closed, and an unset value still fails closed.
|
|
24
|
+
|
|
25
|
+
This is the third instance of one mistake. The weak-`APP_KEY` refusal and the ORM's N+1
|
|
26
|
+
detector had exactly the same bug, both fixed in 1.5.0. Reading `APP_ENV` to decide
|
|
27
|
+
anything about the _deployment_ is wrong once the app has booted; `deployEnv()` is the
|
|
28
|
+
answer.
|
|
29
|
+
|
|
11
30
|
## [1.5.0] — 2026-08-15
|
|
12
31
|
|
|
13
32
|
### Added
|
package/package.json
CHANGED
package/src/helpers/index.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { join } from "node:path";
|
|
24
24
|
import { ConfigError } from "../errors/ConfigError.ts";
|
|
25
|
-
import { DEPLOY_ENV_VAR } from "../support/env.ts";
|
|
25
|
+
import { DEPLOY_ENV_VAR, RUNTIME_MODES as _RUNTIME_MODES } from "../support/env.ts";
|
|
26
26
|
|
|
27
27
|
// ── basePath() ────────────────────────────────────────────────────────────────
|
|
28
28
|
|
|
@@ -65,9 +65,6 @@ export function basePath(...segments: string[]): string {
|
|
|
65
65
|
* setAppEnv(process.argv[2]);
|
|
66
66
|
* const { default: app } = await import('./bootstrap/app.ts');
|
|
67
67
|
*/
|
|
68
|
-
/** Runtime-mode values that Application understands natively — never remapped. */
|
|
69
|
-
const _RUNTIME_MODES = new Set(["web", "worker", "console", "test", "testing", "repl"]);
|
|
70
|
-
|
|
71
68
|
export function setAppEnv(command?: string): void {
|
|
72
69
|
const normalizedCommand = (command ?? "").toLowerCase();
|
|
73
70
|
const current = Bun.env["APP_ENV"];
|
|
@@ -79,10 +76,11 @@ export function setAppEnv(command?: string): void {
|
|
|
79
76
|
// quietly answering no — including the weak-`APP_KEY` refusal and the ORM's
|
|
80
77
|
// N+1 detector. `deployEnv()` reads this back; see {@link DEPLOY_ENV_VAR}.
|
|
81
78
|
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
79
|
+
// The guard is what protects a re-entrant call: `current` is only ever written
|
|
80
|
+
// when it is a genuine deployment name, so a second `setAppEnv` — which sees the
|
|
81
|
+
// runtime mode this one just wrote — cannot stamp `"web"` over `"production"`.
|
|
84
82
|
if (current && !_RUNTIME_MODES.has(current.toLowerCase())) {
|
|
85
|
-
environment[DEPLOY_ENV_VAR]
|
|
83
|
+
environment[DEPLOY_ENV_VAR] = current;
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
if (["serve", "start", "s", "dev", "d"].includes(normalizedCommand)) {
|
package/src/support/env.ts
CHANGED
|
@@ -53,6 +53,22 @@ export const DEV_WORKER_ENV_VAR = "ZT_DEV";
|
|
|
53
53
|
*/
|
|
54
54
|
export const DEPLOY_ENV_VAR = "ZT_APP_ENV";
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* The values of `APP_ENV` that name a runtime *mode* rather than a deployment.
|
|
58
|
+
* `setAppEnv()` writes these; {@link deployEnv} recognises them to know whether
|
|
59
|
+
* `APP_ENV` still holds the deployment name.
|
|
60
|
+
*
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export const RUNTIME_MODES: ReadonlySet<string> = new Set([
|
|
64
|
+
"web",
|
|
65
|
+
"worker",
|
|
66
|
+
"console",
|
|
67
|
+
"test",
|
|
68
|
+
"testing",
|
|
69
|
+
"repl",
|
|
70
|
+
]);
|
|
71
|
+
|
|
56
72
|
/**
|
|
57
73
|
* The deployment name this process was started with — `production`, `staging`,
|
|
58
74
|
* `local`, whatever the operator set — as opposed to the runtime *mode*.
|
|
@@ -72,7 +88,16 @@ export const DEPLOY_ENV_VAR = "ZT_APP_ENV";
|
|
|
72
88
|
* @internal
|
|
73
89
|
*/
|
|
74
90
|
export function deployEnv(): string {
|
|
75
|
-
|
|
91
|
+
const current = Bun.env["APP_ENV"] ?? "";
|
|
92
|
+
// If `APP_ENV` still holds a deployment name, it has not been overwritten yet —
|
|
93
|
+
// or something set it deliberately since — so it is the freshest answer. Only
|
|
94
|
+
// once it holds a runtime mode is the preserved copy the better one.
|
|
95
|
+
//
|
|
96
|
+
// Preferring the preserved copy unconditionally made it sticky for the life of
|
|
97
|
+
// the process: anything that set `APP_ENV` afterwards was ignored, which is
|
|
98
|
+
// wrong in itself and which leaked between test files sharing one process.
|
|
99
|
+
if (current && !RUNTIME_MODES.has(current.toLowerCase())) return current;
|
|
100
|
+
return Bun.env[DEPLOY_ENV_VAR] ?? current;
|
|
76
101
|
}
|
|
77
102
|
|
|
78
103
|
/**
|
|
@@ -101,7 +126,11 @@ export function deployEnv(): string {
|
|
|
101
126
|
*/
|
|
102
127
|
export function devSurfacesEnabled(): boolean {
|
|
103
128
|
if (Bun.env[DEV_WORKER_ENV_VAR] === "1") return true;
|
|
104
|
-
|
|
129
|
+
// `deployEnv()`, not `Bun.env["APP_ENV"]` — by the time anything asks, `setAppEnv()`
|
|
130
|
+
// has replaced that with the runtime mode, and `isDevSurfaceAllowed("web")` is false.
|
|
131
|
+
// An app with `APP_ENV=development` in its `.env` was therefore getting production
|
|
132
|
+
// error pages from a plain `zt serve`.
|
|
133
|
+
return isDevSurfaceAllowed(deployEnv());
|
|
105
134
|
}
|
|
106
135
|
|
|
107
136
|
/**
|