nestjs-web-repl 2.1.0 → 2.1.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.
Files changed (2) hide show
  1. package/README.md +32 -94
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -26,6 +26,10 @@ running server.
26
26
  npm install nestjs-web-repl
27
27
  ```
28
28
 
29
+ > **Upgrading from 1.x?** The `forRoot`/`forRootAsync` API is deprecated. v2 uses
30
+ > `register`/`registerAsync` — see [Quick start](#quick-start) and
31
+ > [Securing it](#securing-it).
32
+
29
33
  ## Quick start
30
34
 
31
35
  ```ts
@@ -157,6 +161,22 @@ WebReplModule.registerAsync({
157
161
  });
158
162
  ```
159
163
 
164
+ ### How the browser UI authenticates
165
+
166
+ Your guard runs in front of all three routes — the UI page, the SSE stream, and
167
+ the command POST. The bundled UI sends only what a browser attaches
168
+ automatically on a **same-origin** request: **cookies**. It sets no
169
+ `Authorization` header, and the SSE stream uses `EventSource`, which cannot send
170
+ custom headers at all. So protect these routes with **cookie/session** auth (or a
171
+ network-level control such as an IP allowlist, mTLS, or a VPN). A
172
+ bearer-token / `Authorization`-header guard rejects the UI — it still works for
173
+ direct `curl` clients, where you set the header yourself, but the browser cannot.
174
+
175
+ The UI is served from the same origin it calls, so a logged-in session cookie
176
+ rides along on the page load, the SSE connection, and every command. One caveat:
177
+ the UI sends no CSRF token, so authenticate off the session itself rather than
178
+ requiring a CSRF token on these routes.
179
+
160
180
  ## Adapter / multi-instance
161
181
 
162
182
  If you run more than one instance of your app (multiple processes, pods,
@@ -188,10 +208,10 @@ solves this with an **ownership + fan-out** protocol:
188
208
  never preempted this way. Takeover loses that channel's in-memory
189
209
  variables (the dead owner's session is gone) but restores availability
190
210
  instead of leaving the channel wedged fleet-wide (see
191
- [Limitations](#limitations-v1)).
211
+ [Limitations](#limitations)).
192
212
  - Because ownership is decided by whichever instance's `onCmd` handler runs
193
213
  first, two instances racing to claim the same brand-new channel at the
194
- same instant resolve **last-claim-wins** (see [Limitations](#limitations-v1)).
214
+ same instant resolve **last-claim-wins** (see [Limitations](#limitations)).
195
215
 
196
216
  By default this coordination happens via `InMemoryWebReplAdapter`, which only
197
217
  works within a single process (fine for local dev / single-instance
@@ -299,27 +319,6 @@ and `WEB_REPL_OPTIONS` (the DI token for the resolved options, useful when
299
319
  injecting them into a sibling-registered controller subclass), plus the types
300
320
  `WebReplAdapter`, `WebReplModuleOptions`, `WebReplModuleExtras`,
301
321
  `WebReplAdapterConfig`, `WebReplEvent`, `SseEventType`.
302
-
303
- ## Migrating from 1.x → 2.0
304
-
305
- - `WebReplModule.forRoot(...)` → `WebReplModule.register(...)`.
306
- - `WebReplModule.forRootAsync(...)` → `WebReplModule.registerAsync(...)`.
307
- - `adapter` is no longer an option resolved by `useFactory`; it's a static
308
- "extra" passed alongside the options (or alongside `useFactory`/`inject` for
309
- the async form), and now also accepts `{ useClass, imports? }` or
310
- `{ useFactory, inject?, imports? }` in addition to a ready instance — see
311
- [Adapter / multi-instance](#adapter--multi-instance).
312
- - `registerController: false` is gone. To run your own guarded controller
313
- instead of the default, subclass `WebReplController`, add `@UseGuards(...)`,
314
- and pass it as the `controller` extra to `register`/`registerAsync` — see
315
- [Securing it](#securing-it). Unlike the old `registerController` flag, this
316
- works identically for both the sync and async form.
317
- - A disabled module (`enabled: false`) now still registers the
318
- controller/service, but every route 404s and the module never subscribes to
319
- the adapter — it no longer silently registers nothing. If you were relying
320
- on a disabled module contributing zero routes/providers to the Nest module
321
- graph, that is no longer the case.
322
-
323
322
  ## AI skill
324
323
 
325
324
  This package ships a [Claude Code](https://claude.com/claude-code) skill that
@@ -335,7 +334,7 @@ agent picks it up on its next session. The command never clobbers a modified
335
334
  skill file silently — if you have edited it, re-run with `--force` to refresh it
336
335
  after upgrading the package.
337
336
 
338
- ## Limitations (v1)
337
+ ## Limitations
339
338
 
340
339
  - **Monaco loads from a CDN** (`cdn.jsdelivr.net`) inside the `/ui` page — the
341
340
  *browser* needs internet access to load the editor; the server side has no
@@ -383,11 +382,10 @@ We tell you this because the honest thing to do is let you judge the code on
383
382
  its merits rather than guess at its origins. If you are skeptical of AI-written
384
383
  code, here is what to actually look at:
385
384
 
386
- - **The tests.** 100 automated tests, including a two-instance end-to-end test
387
- that proves cross-instance command routing and output fan-out, and an
385
+ - **The tests.** A thorough automated suite, including a two-instance end-to-end
386
+ test that proves cross-instance command routing and output fan-out, and an
388
387
  execution-proof test that resolves a real provider through the live REPL
389
- context. `npm test`, `npm run build`, and `npx tsc -p tsconfig.build.json
390
- --noEmit` are all green.
388
+ context. `npm test`, `npm run build`, and the typecheck all run green in CI.
391
389
  - **The commit history.** The real TDD trail is preserved — failing test,
392
390
  implementation, fixes — including several rounds where review caught genuine
393
391
  defects (the trickiest: `node:repl` completion detection on modern Node, and
@@ -399,72 +397,6 @@ code, here is what to actually look at:
399
397
 
400
398
  AI assistance does not exempt the code from scrutiny — it raises the bar for
401
399
  it. Issues and fixes are welcome from anyone who finds something we missed.
402
-
403
- ## AI usage & training
404
-
405
- The source here is published so people and their tools can **use** it — read
406
- it, run it, debug against it, integrate it. It is not offered as training data.
407
- [`robots.txt`](./robots.txt) and [`ai.txt`](./ai.txt) record a request that AI
408
- model *training* crawlers (GPTBot, ClaudeBot, CCBot, Google-Extended, and
409
- others) not ingest this repository. Those files are advisory — they express
410
- intent and do not, and cannot, technically enforce anything, nor do they bind
411
- GitHub's own hosting. Using an AI coding assistant to help you *work with* this
412
- library is entirely fine and expected.
413
-
414
- ## Releasing
415
-
416
- Releases are **fully automated**. Merging a PR to `main` with releasable
417
- [Conventional Commits](https://www.conventionalcommits.org/) triggers
418
- `.github/workflows/release.yml`, which runs the full test suite and then
419
- [semantic-release](https://semantic-release.gitbook.io/):
420
-
421
- | Commit type | Version bump |
422
- | ---------------------- | ----------------- |
423
- | `fix:` | patch (x.y.**z**) |
424
- | `feat:` | minor (x.**y**.0) |
425
- | `feat!:` / `BREAKING CHANGE:` in body | major (**x**.0.0) |
426
- | `docs:` `chore:` `test:` `ci:` `refactor:` | no release |
427
-
428
- It computes the next version, updates `CHANGELOG.md`, publishes to npm
429
- (**tokenless via OIDC trusted publishing, with provenance attached
430
- automatically**), tags the commit, cuts a GitHub Release, and commits the
431
- version/changelog bump back to `main` as `chore(release): x.y.z [skip ci]`.
432
- Do not bump `version` in `package.json` by hand.
433
-
434
- ### One-time bootstrap (maintainer, once)
435
-
436
- npm's OIDC trusted publishing cannot perform a package's *first* publish, so a
437
- maintainer does this once:
438
-
439
- 1. **Create the package on npm with a placeholder:**
440
- ```bash
441
- npm login
442
- npm version 0.0.0 --no-git-tag-version # temp, do not commit
443
- npm publish --access public
444
- git checkout -- package.json # restore working version
445
- ```
446
- Do **not** create a git tag for `0.0.0`; with no tags semantic-release's
447
- first automated release is `1.0.0`.
448
- 2. **Register the Trusted Publisher** at
449
- `https://www.npmjs.com/package/nestjs-web-repl/access` → *Trusted Publishers*
450
- → GitHub Actions: owner `p-dim-popov`, repository `nestjs-web-repl`, workflow
451
- `release.yml` (leave environment blank). After this, no token is needed.
452
- 3. (Optional, after `1.0.0` ships) `npm deprecate nestjs-web-repl@0.0.0 "placeholder"`.
453
-
454
- ### Verifying the first real release
455
-
456
- After the bootstrap, the next merge to `main` containing a `feat:`/`fix:` commit
457
- should produce `1.0.0`. Confirm:
458
-
459
- - `npm view nestjs-web-repl version` → `1.0.0`
460
- - the npm package page shows a provenance / "Published via GitHub Actions" badge
461
- - a `v1.0.0` git tag and a matching GitHub Release with generated notes exist
462
- - `CHANGELOG.md` and a `chore(release): 1.0.0` commit are on `main`
463
- - the `release.yml` run is green
464
-
465
- If the publish step fails with an auth error, the Trusted Publisher registration
466
- (step 2) is missing or its repo/workflow fields don't match exactly.
467
-
468
400
  ## Contributing
469
401
 
470
402
  Contributions are welcome — see [`CONTRIBUTING.md`](./CONTRIBUTING.md). AI-
@@ -472,6 +404,12 @@ assisted PRs are fine; we just ask you to disclose the assistance and to
472
404
  understand what you submit. Agents working in this repo should start with
473
405
  [`AGENTS.md`](./AGENTS.md).
474
406
 
407
+ PRs merge as a single squash commit whose message is the **PR title and
408
+ description**, and that commit drives an automated release. Write the PR title as
409
+ a [Conventional Commit](https://www.conventionalcommits.org/) (`feat:`, `fix:`,
410
+ `docs:`, …) so the version bump is correct; put any `BREAKING CHANGE:` note in the
411
+ description.
412
+
475
413
  ## License
476
414
 
477
415
  [MIT](./LICENSE) © Petar Popov
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestjs-web-repl",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Expose a live NestJS REPL over the network (HTTP + SSE + Monaco UI).",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",