@luckystack/core 0.6.7 → 0.7.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 +148 -107
- package/CLAUDE.md +245 -245
- package/LICENSE +21 -21
- package/README.md +93 -93
- package/dist/{chunk-WFABOO6J.js → chunk-AFG7KKMS.js} +3 -3
- package/dist/chunk-AFG7KKMS.js.map +1 -0
- package/dist/{chunk-3AWP2YEA.js → chunk-J3UOWYT4.js} +2 -28
- package/dist/chunk-J3UOWYT4.js.map +1 -0
- package/dist/{chunk-LU3IPFTR.js → chunk-LTCDQU5Z.js} +1 -1
- package/dist/chunk-LTCDQU5Z.js.map +1 -0
- package/dist/chunk-R7IRJFVC.js +67 -0
- package/dist/chunk-R7IRJFVC.js.map +1 -0
- package/dist/client.d.ts +3 -2
- package/dist/client.js +4 -4
- package/dist/client.js.map +1 -1
- package/dist/config-DZCzBNwP.d.ts +122 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +31 -0
- package/dist/eslint/index.js.map +1 -1
- package/dist/index.d.ts +21 -149
- package/dist/index.js +66 -70
- package/dist/index.js.map +1 -1
- package/dist/pageRouteValidation-sJJCX-YV.d.ts +270 -0
- package/dist/{projectConfig-XL5VB76A.js → projectConfig-DBLSQ3NY.js} +2 -2
- package/dist/{sentrySetup-4NTWLN2A.js → sentrySetup-MF6JSVWA.js} +3 -3
- package/dist/sentrySetup-MF6JSVWA.js.map +1 -0
- package/dist/{pageRouteValidation-gqktrJci.d.ts → sessionTypes-Dzen_rPK.d.ts} +23 -265
- package/docs/app-bootstrap.md +418 -418
- package/docs/config-registry.md +348 -348
- package/docs/csrf-config.md +88 -88
- package/docs/error-tracker-registry.md +194 -174
- package/docs/hooks.md +298 -298
- package/docs/rate-limit-strategy.md +170 -170
- package/docs/redis-adapter.md +111 -111
- package/docs/session-types.md +180 -180
- package/docs/socket-bootstrap.md +366 -366
- package/package.json +6 -2
- package/dist/chunk-3AWP2YEA.js.map +0 -1
- package/dist/chunk-LU3IPFTR.js.map +0 -1
- package/dist/chunk-WFABOO6J.js.map +0 -1
- /package/dist/{projectConfig-XL5VB76A.js.map → config.js.map} +0 -0
- /package/dist/{sentrySetup-4NTWLN2A.js.map → projectConfig-DBLSQ3NY.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,107 +1,148 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to `@luckystack/core` are documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
-
|
|
8
|
-
## [Unreleased]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
`
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
`
|
|
78
|
-
`
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@luckystack/core` are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.7.0] - 2026-07-16
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`registerSecretsResolvedListener` / `notifySecretsResolved` are now exported from
|
|
15
|
+
the client-safe `@luckystack/core/config` subpath** (they were already on the main
|
|
16
|
+
barrel). A project's `config.ts` — which is client-bundled, so it can only import from
|
|
17
|
+
`/config` — can now re-register env-derived slots the moment the secret manager
|
|
18
|
+
resolves. This closes a real defect (finding C-04): `config.ts` runs at module load,
|
|
19
|
+
*before* `resolveSecretsIfConfigured()`, so any slot derived from a secret-manager
|
|
20
|
+
pointer (`EMAIL_FROM`, `EXTERNAL_ORIGINS`, …) froze as the unresolved pointer —
|
|
21
|
+
measured live, CORS held `["ORIGINS_BASE_V1"]` while `process.env` already had the real
|
|
22
|
+
origin, so it would reject the very host the operator configured. `secretsResolved.ts`
|
|
23
|
+
imports nothing, so the subpath stays free of server deps (`configEntry.test.ts`).
|
|
24
|
+
|
|
25
|
+
- **Bun env auto-load guard.** Bun auto-loads `.env` files before any user code
|
|
26
|
+
runs; Node does not. That silently breaks two guarantees of `loadEnvFiles`:
|
|
27
|
+
`LUCKYSTACK_ENV_FILES` stops being an ambient-only override (a value set INSIDE
|
|
28
|
+
`.env` — exactly what `.env_template` shows commented — hijacks the file list),
|
|
29
|
+
and `.env.<mode>` / `.env.<mode>.local`, which the framework never loads, come
|
|
30
|
+
to outrank `.env` (verified under Bun 1.3.14: a key in `.env.development` beat
|
|
31
|
+
`.env`). Both failures were 100% silent. `loadEnvFiles` now detects the symptom
|
|
32
|
+
at boot — an env file already applied to `process.env` byte-for-byte before we
|
|
33
|
+
load it — and warns with the fix. It warns rather than throws: `bun install`
|
|
34
|
+
ignores `env = false` (oven-sh/bun#31450), so a postinstall boot would
|
|
35
|
+
otherwise be unfixably fatal. Node is never affected and never warns.
|
|
36
|
+
- **`bunfig.toml` with `env = false`** at the repo root and in the
|
|
37
|
+
`create-luckystack-app` template, disabling Bun's `.env` auto-load (requires
|
|
38
|
+
Bun >= 1.3.3) so `bun` and `node` load byte-identical values. The "a real
|
|
39
|
+
ambient env var wins over `.env`" contract (Docker/K8s/CI) is unchanged — that
|
|
40
|
+
is LuckyStack's own loader, not Bun's.
|
|
41
|
+
- **Timestamps in the built-in loggers.** The default `console.*` logger and
|
|
42
|
+
`createDevLogger` now prefix each line with an ISO-8601 UTC timestamp
|
|
43
|
+
(`[2026-07-13T15:20:01.123Z] Connected to Redis`), controlled by a new
|
|
44
|
+
`logging.timestamps` config key (default `true`; set `false` under a log
|
|
45
|
+
aggregator that stamps its own time). Only the message is prefixed — context /
|
|
46
|
+
error args stay separate. A registered custom logger owns its own formatting.
|
|
47
|
+
- **Decoupled secrets-resolved hook** (ADR 0026): `notifySecretsResolved(changedKeys?)`
|
|
48
|
+
+ `registerSecretsResolvedListener(fn)`. A secret resolver (e.g.
|
|
49
|
+
`@luckystack/secret-manager` via `onApplied: notifySecretsResolved`) fires it after
|
|
50
|
+
overwriting `process.env`; `redis.ts` self-registers a listener that EAGERLY REBUILDS +
|
|
51
|
+
registers the default client when a `REDIS_` credential changed, so Redis auth via a
|
|
52
|
+
secret-manager POINTER survives boot AND rotation with no hand-wiring. Generic — Prisma
|
|
53
|
+
pools / SDK clients can subscribe too. Also adds `rebuildDefaultRedisClient()` and an
|
|
54
|
+
optional structural `secretManager?` field on `ProjectConfig` (`SecretManagerConfigRef`)
|
|
55
|
+
so the server boot can detect a resolver.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- **`@luckystack/core/client` no longer reaches `node:async_hooks` in its built
|
|
60
|
+
chunk graph.** The browser-safe lazy capture path and the server-only
|
|
61
|
+
AsyncLocalStorage identity scope previously shared `errorTrackerRegistry.ts`;
|
|
62
|
+
tsup coalesced that dynamic capture path with the client logger and emitted a
|
|
63
|
+
static Node builtin import in a client-reached chunk. The identity scope now
|
|
64
|
+
lives in a dedicated server module, while capture fan-out remains browser-safe.
|
|
65
|
+
A post-tsup graph check rejects any Node builtin reachable from `dist/client.js`.
|
|
66
|
+
- **`Jsonify<T>` now preserves already-JSON-stable recursive values.** Prisma's
|
|
67
|
+
self-referential `JsonValue` previously recursed through the array branch until
|
|
68
|
+
TypeScript rendered `... N more ...`, producing malformed generated route types
|
|
69
|
+
for a Prisma `SessionLayout`. A non-distributive JSON-stability guard keeps the
|
|
70
|
+
value intact while `Date | null` still becomes `string | null`.
|
|
71
|
+
- **Redis secret-manager pointer boot** (ADR 0026): the default Redis client no longer
|
|
72
|
+
fails auth with a baked-in `REDIS_PASSWORD_V<n>` pointer when it was built (during an
|
|
73
|
+
early import) before secrets resolved. The framework EAGERLY REBUILDS + registers a
|
|
74
|
+
fresh client from the resolved env (`rebuildDefaultRedisClient()`), so the boot-UUID
|
|
75
|
+
write authenticates with the real password — no consumer code. **Correction over
|
|
76
|
+
0.6.3/0.6.4:** the rebuild logic was right but never TRIGGERED for a normal project (the
|
|
77
|
+
server-boot gate `getProjectConfig().secretManager?.url` is falsy — the scaffold doesn't
|
|
78
|
+
register `secretManager` into `projectConfig` — and bare `initSecretManager` wires no
|
|
79
|
+
`onApplied`). Core now publishes `notifySecretsResolved` onto a decoupled global-symbol
|
|
80
|
+
ARRAY (`Symbol.for('luckystack.secretsResolved.listeners')`) at module load, which
|
|
81
|
+
`@luckystack/secret-manager` fires automatically after every resolve — so the rebuild
|
|
82
|
+
happens at resolve time with zero consumer code, in prod and dev, and even survives a
|
|
83
|
+
dual `@luckystack/core` instance. (A short-lived 0.6.3/0.6.4 server-boot gate + a
|
|
84
|
+
`ProjectConfig.secretManager` field were vestigial once the channel existed and are
|
|
85
|
+
removed — the channel is the single trigger.)
|
|
86
|
+
- **CORE-2** — `tryCatchSync<T, P = void>` now mirrors `tryCatch`'s `P` default,
|
|
87
|
+
so a params-less call can pass only the result type (`tryCatchSync<URL>(() =>
|
|
88
|
+
new URL(raw))`) instead of failing with TS2558.
|
|
89
|
+
|
|
90
|
+
### Added
|
|
91
|
+
|
|
92
|
+
- **CORE-1** — `resetDefaultRedisClient()` drops + disconnects the cached lazy
|
|
93
|
+
default Redis client so the next resolve rebuilds it from current env. Call it
|
|
94
|
+
after `initSecretManager(...)` when `REDIS_PASSWORD`/`REDIS_HOST` were
|
|
95
|
+
secret-manager pointers at first import (the early function-injection scan may
|
|
96
|
+
have already built a client with the raw pointer value). The default client's
|
|
97
|
+
error handler also turns the resulting `WRONGPASS` into an actionable message
|
|
98
|
+
when the password still looks like an unresolved pointer.
|
|
99
|
+
|
|
100
|
+
## [0.6.0] - 2026-07-12
|
|
101
|
+
|
|
102
|
+
### Added
|
|
103
|
+
|
|
104
|
+
- `AuthConfig` slots for email-code login + 2FA (ADR 0024, all additive with
|
|
105
|
+
safe defaults): `emailCodeLogin` (false), `emailCodeTtlSeconds` (600),
|
|
106
|
+
`emailCodeLength` (6), `emailCodeMaxAttempts` (5), `twoFactor`
|
|
107
|
+
(`'disabled' | 'optional'`, default disabled), `twoFactorEmailFallback`
|
|
108
|
+
(true), `twoFactorChallengeTtlSeconds` (300), `twoFactorMaxAttempts` (5).
|
|
109
|
+
|
|
110
|
+
## [0.5.0] - 2026-07-11
|
|
111
|
+
|
|
112
|
+
### Changed
|
|
113
|
+
|
|
114
|
+
- **`@prisma/client` is now an OPTIONAL peer dependency** (ADR 0020, the ORM
|
|
115
|
+
choice). npm no longer auto-installs it; scaffolded projects get it via the
|
|
116
|
+
template's direct dependency when `orm: 'prisma'`. Non-scaffolded projects
|
|
117
|
+
that relied on peer auto-install must add `@prisma/client` to their own
|
|
118
|
+
`package.json`. The same demotion applies in `@luckystack/api`, `devkit`,
|
|
119
|
+
`server`, `sync`, and `login`.
|
|
120
|
+
- `@prisma/client` left the static-import position in `db.ts`: the default
|
|
121
|
+
resolver now lazy-`require()`s it on first access. When it is absent AND no
|
|
122
|
+
client was registered, DB access throws an actionable error pointing at
|
|
123
|
+
`luckystack/core/clients.ts` instead of a bare `ERR_MODULE_NOT_FOUND` at boot.
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
|
|
127
|
+
- `isPrismaClientResolvable()` — is a generated `@prisma/client` present?
|
|
128
|
+
- `registerDbHealthCheck` / `getDbHealthCheck` / `isDbHealthCheckRegistered` /
|
|
129
|
+
`resetDbHealthCheckForTests` (+ types `DbHealthCheck`, `DbHealthResult`) —
|
|
130
|
+
pluggable `/readyz` database probe; without one the server falls back to the
|
|
131
|
+
built-in Prisma ping when Prisma is present, else reports `'skipped'`.
|
|
132
|
+
|
|
133
|
+
## [0.1.5]
|
|
134
|
+
|
|
135
|
+
### Removed
|
|
136
|
+
|
|
137
|
+
- **`DNS` dropped from the env schema.** It was a reserved/legacy var that
|
|
138
|
+
conflated the backend origin (OAuth callback host) with the public origin
|
|
139
|
+
(where users browse). Projects now derive the backend origin from
|
|
140
|
+
`SERVER_IP`/`SERVER_PORT` and set the public origin via `app.publicUrl` (see the
|
|
141
|
+
scaffold's `config.ts`). Leftover `DNS=` lines in existing `.env` files are
|
|
142
|
+
harmless — the schema is `loose()`, so unknown keys pass through ignored.
|
|
143
|
+
|
|
144
|
+
## [0.1.0]
|
|
145
|
+
|
|
146
|
+
### Added
|
|
147
|
+
|
|
148
|
+
- Initial public release as part of the LuckyStack package split.
|