Repository navigation
feat(foundry): Hook on/off/emit, single registry, server:start hook - #17
Merged
Merged
Conversation
Hook API - `Hook.on(name, positions)` registers (merging positions), `Hook.off(name?, pos?)` removes, and `Hook.emit(name, pos, ...args)` calls a position and returns its result (a Promise for async hooks). `emit` is a no-op when nothing is registered, so call sites drop the `if (Hook.has(...))` guard. `Hook.all()` lists hooks. - `get()` only retrieves now. Deprecated aliases keep working: `set` -> `on`, `unset` -> `off`, `getAll` -> `all`, and `get(name, pos, ...args)` (which called the hook) -> `emit`. server:start hook - The Express and H3 drivers emit `server:start` once listening, after the startup banner and any tunnel: `after` always, then `tunneled` only when a tunnel is open. Payloads are `ServerStartInfo` / `TunneledServerStartInfo` from @arkstack/contract (host, port, scheme, secure, browsable url, tunnelUrl). `tunnelUrl` is the URL the tunnel actually opened. A failing listener is logged, never stops the server, and doesn't skip the other position. Fixes - @arkstack/common shipped its own copy of Hook, a second registry, so hooks registered through one import never fired for code reading the other. The Express auth middleware read common's, so `middleware:auth` hooks registered as documented (via foundry) never ran on Express. common now re-exports foundry's Hook and types. Typed hook names must be declared by augmenting HookRegistry on @arkstack/foundry. - `shutdown` checked for a `before` hook but called `after`. - `unset(name)` for an unregistered name cleared every hook. - H3's auth middleware now awaits its hooks, as Express already did. - A failing Express `after` middleware exited the process: Logger.error exits by default, and the post-response handler didn't pass false.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reworks
Hookinto anon/off/emitAPI, adds aserver:starthook to both drivers (with atunneledposition), and fixes several hook bugs. The biggest one meantmiddleware:authhooks registered as documented never ran on Express.Hook API
on(name, positions)registers and merges positions.off(name?, pos?)removes.all()lists.emit(name, pos, ...args)calls a position and returns its result: a Promise for async hooks, unlikeEventEmitter.emit()'s boolean. It's a no-op when nothing is registered, so call sites drop theif (Hook.has(...))guard.get()only retrieves now. Previously,get(name, pos, ...args)called the hook when given arguments, so a zero-argument hook couldn't be triggered through it.set→on,unset→off,getAll→all, and calling throughget→emit.server:starthookBoth drivers emit
server:startonce the server is listening, after the startup banner and once any tunnel is open. It fires in development and production.afteralways runs, withServerStartInfo:host,port,scheme,secure, a browsableurl, andtunnelUrl.tunneledruns next, only when a tunnel is open, withTunneledServerStartInfo(wheretunnelUrl: string).tunnelUrlis the URL the tunnel actually opened. The original draft readTUNNEL_URLbefore ngrok set it, so it wasundefinedunderark dev -t.@arkstack/contract, replacing per-driverdev:serverdeclarations.Fixes
Each has a test that I confirmed fails on the previous code.
Hookregistries.@arkstack/commonshipped its own copy ofHook(a separate staticMap). The Express auth middleware readcommon's, somiddleware:authhooks registered via@arkstack/foundry(as the docs say) never ran on Express.commonnow re-exports foundry'sHookand types.shutdownchecked for abeforehook but calledafter.unset(name)with an unregistered name cleared every hook.aftermiddleware exited the process.Logger.errorexits by default, and the post-response handler didn't passexit = false.Breaking
TypeScript doesn't merge module augmentations through a re-export. Code that declared typed hook names by augmenting
HookRegistryon@arkstack/commonmust move that to@arkstack/foundry; thecommonaugmentation now silently does nothing. arcstack's own declarations are moved. This is noted in the CHANGELOG and the hooks guide.Tests & docs
emitwith arguments, with none, async, and on missing hooks;off, and the shared registry;server:starton both drivers (local url, opened vs preset tunnel, banner-then-hook order,tunneledfiring/not firing, failure isolation), using a fake app / mockedserve()and mocked ngrok, with no real ports;after-middleware crash.main.server:start, deprecations);foundryREADME holds the API;commonREADME points to it; overview and auth guide updated; CHANGELOG under Unreleased.This branch also carries
ee31e839 style(catalog): standardize quotes in catalog entries.