Repository navigation
Releases
v1.1.0
Added
- Lifecycle hooks for singletons: an
onInit()method runs once every singleton exists, before
routes are built;onShutdown()runs whenapp.close()starts, once new connections are refused and while
requests in flight finish.
Factory providers take them asonInitandonShutdownoptions.OnInitandOnShutdown
types forimplements.runWorker()runs them too. - A new
pubsubpackage: typed channels (defineChannel),publish,subscribe,on, andevents()
forsse(). Adapters for one process (memoryAdapter), everycluster()worker
(clusterAdapter, through the primary) and Redis (redisAdapterforredis,ioredisAdapter
forioredis). Slow subscribers are dropped after a buffer (1 000 messages by default). - Tutorial chapter 18: real-time updates with pub/sub.
Changed
app.close()ends open streaming responses, such assse(), as soon as shutdown starts: their
signalaborts andsse()streams finish. Before, they held the shutdown until
shutdownTimeout. A stream that ignores its signal still gets the full timeout.- When an
onShutdownhook or a provider's dispose fails,app.close()still closes the server
and disposes the other providers, then rejects with the errors. - Calling
app.close()again while it runs waits for the first call instead of starting a second
shutdown.
v1.0.2
Fixed
- AVI203 missed a devDependency reached through an
importsentry with only an"import"
condition: imports were resolved asrequirewould. Each is now resolved as its file loads it. - AVI203 missed a cluster or worker started through
import * as workers, through a project file
that re-exports it by name (export { cluster } fromthe workers package), or under another name
(import { cluster as boot }). A re-export withexport *is still not followed. - AVI203 took another package's export imported under the name
clusterorrunWorkerfor Avi.js's
(import { createAvi as cluster }from the core package). avi build,avi check,avi client,avi injectandavi-compileprinted a stack trace for
a tsconfig they cannot read. They now printCannot read file '…/nope.json'.and exit with 1.avi devandavi buildlook up fewer modules on large projects.
Changed
- New projects' tests, the examples and the docs use Joy instead of Grace as a sample name. The
auth-api example's member signs in asjoy/joy-to-the-world.
v1.0.1
Fixed
- AVI203 missed a devDependency reached through an import cycle or a
pathsalias, so
inject.gen.tscould import a file a production install cannot load. It now follows every
import that resolves to a project file. - AVI203 flagged a class next to a top-level call of the project's own
listen, such as an event
bus's, so the class got no list and failed at startup. It now looks at what a call resolves to:
runWorkerandclustercount when imported from Avi.js,listenunless the project defines
it, andsetIntervalandsetTimeoutnow count too. - The first
avi buildafter upgrading to 1.0.0 could remove another tsconfig's output, read from
the list earlier versions wrote. That list now only gets replaced: nothing on it is removed. avi build,avi dev,avi check,avi client,avi injectandavi-compiletake-pfor
--project.avi bogusandavi bogus --helpsayUnknown command "bogus"and exit with 2, and
avi g widget foosaysUnknown kind "widget".npm create avi -- --helpdescribedavi new; it now prints its own usage.
v1.0.0
The first stable release. The code is 1.0.0-rc.6's;
Stability and versions says what 1.x promises.
Upgrading from a release candidate
- An
sse()stream starts with the comment: open(from rc.6). Clients skip comments; a test
that compares a stream's body text needs the extra line. - The first
avi buildwith rc.6 or later takes the old.avi-buildlist as its own tsconfig's.
With two tsconfigs sharing anoutDir, that build may remove the other's output once; the
other's next build writes it back. - A class that inherits
static injectand takes more constructor arguments fails at startup
(from rc.6).avi devandavi buildgive it its own list; without them, addstatic inject.
Known limitations
- AVI203 recognizes values that start something by the call's name (
listen,runWorker,
cluster,new Worker). Other top-level side effects, such assetInterval, are not caught,
and a top-levelbus.listen(...)is flagged although it starts no server. - The devDependency check for
inject.gen.tsfollows relative imports only, notpathsaliases,
and can miss a devDependency reached through an import cycle.
v1.0.0-rc.6
Fixes from testing 1.0.0-rc.5.
Fixed
- A class that inherits
static injectbut whose constructor takes more arguments got
undefinedfor the extra ones. The app now fails to start with
Child inherits a dependency list for 1 constructor argument from Base, but takes 2. A
shorter list of the class's own still passes, since the parameters left out may be optional.
New in the di package:checkInjectList. inject.gen.tsimported files it must not: a file whose exported value starts a server or worker
(export const server = app.listen(3000)), a file that re-exports a devDependency, and a file
that reaches a devDependency through another file of the project. Their classes now get AVI203.sse()sent no headers until the source's first event, sofetch,api.events()and
EventSourceconnected late on a quiet stream. A stream now starts with the comment: open.avi builddeleted another tsconfig's output when two shared anoutDir, so
avi build -p tsconfig.server.json && avi build -p tsconfig.worker.jsonleft only the worker.
.avi-buildnow keeps one list per tsconfig, and reads the list earlier versions wrote.- Docs: chapter 10 describes the runtime list check and the AVI203 cases as they are; chapter 16
shows callinghandle.restart()only in the primary, and says Windows may not spread
connections evenly.
v1.0.0-rc.5
Fixes from testing 1.0.0-rc.4.
Fixed
inject.gen.tsimported other entry points: a worker or a seed script thatregistered or
created an app was imported by the web app, so its code ran there, and a browser file calling
navigator.serviceWorker.registercrashed it. rc.4 guessed entry points by name, which also
missed some (an app created in a helper, an aliased import). Nowinject.gen.tsonly imports
files that just declare things; a class in a file with top-level code, or one that imports a
devDependency, gets the new AVI203 warning instead. AVI202 is gone.avi buildthrew a raw error when it could not write an output file; it now reports TS5033, as
tscdoes.- A list function that failed because a class did not exist yet was dropped, so the next app
reported the wrong error; it stays queued and applies once the class exists. avi builddid not remove stale output after a folder was renamed by case only, on Windows
and macOS.- The up-to-date check took some different files for equal (template literals, escaped quotes,
commas inside strings); it compares tokens now. - A class with an optional constructor parameter failed to start: the runtime check compared the
list with the constructor's length, which counts optional parameters. A list may now leave them
out, as the type check already allowed. A class with no list at all still fails, and the error
now says to addimport './inject.gen.js'. - Files compiled by
avi devwere never cleaned, so a test deleted while it ran kept running in
npm test.avi devnow adds what it compiles to the listavi buildcleans from. - A watcher could still write a generated file after
close(). avi inject --helpand the other commands printed the full usage; they print their own now.avi g --dry-runnow ends withDry run: nothing was written.- New projects' README lists
npm run buildandnpm run check. - Docs: chapter 16 says to install the workers package at the same version as the core package, chapter
3 shows the generated file as it is, and the README gives TypeScript 5.8 as the minimum.
v1.0.0-rc.4
The fourth release candidate for Avi.js 1.0, on npm's next tag; latest stays on 0.7.0. Install every Avi.js package from next during the release candidate, so they share one core.
Fixes from testing 1.0.0-rc.3: a correctness review of the new dependency lists, a new-user run of
every chapter from npm, the real app on generated lists, and deeper fuzzing.
Fixed
- A class declared in a file that imports
inject.gen.ts, such asapp.module.tsormain.ts,
crashed the app at startup (Cannot access ... before initialization), and so did a test that
registered a feature module before the lists loaded. The generated file now registers a function
(registerInjects(() => [...])) that runs when the app starts, and controllers read their list
then instead of when their module loads. inject.gen.tsimported every file with a class, so a seed script or a test helper ran when the
app started. Only files the app loads are read now: those its entry points (AviFactory.create,
register,createAvi,runWorker,cluster) import. With no entry point, nothing is
inferred and AVI202 says why.- A subclass of an abstract base had
undefineddependencies: abstract classes were skipped. They
get lists now, which subclasses without a constructor inherit. - An optional or defaulted constructor parameter was inferred as required, so startup failed when
nothing provided it. Lists stop at the first one, asconstructor.lengthdoes. - An object with a
descriptionnamed like a type was taken for a token. Only classes,
constructors, andcreateTokenanddefineConfigvalues are. - The up-to-date check ignored commas and spaces inside strings, so
[A, B]matched[AB]and a
changed list could stay stale. Only formatting is ignored now. avi buildremoved any compiled-looking file without a source, including one written by hand,
a bundler's assets and output compiled from outsideinclude(a siblingshared/folder).
It now records what it writes and removes only what an earlier build wrote and this one did not.- A class with no dependency list now says so, and how to fix it, instead of "static inject lists
0"; counts read "1 constructor argument" and "1 dependency list". - The minimal template ships
src/inject.gen.tstoo, soavi inject --checkpasses and its
services can take dependencies withoutstatic inject. avi injectandavi clientwrite next to the--projecttsconfig, likeavi dev.
avi gno longer rewritesinject.gen.tsfor line endings alone.avi --versionprints the version;avi g --helpshows the generate usage; the hint for a
missing--names thenextdecorator during a release candidate.
Docs
- Chapters 3, 8 and 16: an entry point or test that skips
app.module.tsimports
inject.gen.jsitself. Chapter 10 explains which files are read, and AVI202. Chapter 0's
script table and summary note, chapter 9's minimal tree and chapter 17's CLI list are corrected. - README: the status badge, the packages table (client, workers) and the
nextdecorator during the release
candidate.
v1.0.0-rc.3
The third release candidate for Avi.js 1.0, on npm's next tag; latest stays on 0.7.0. Install every Avi.js package from next during the release candidate, so they share one core.
Added
- Dependency lists without
static inject.avi devandavi buildread constructor types with
the TypeScript compiler they already run and keep the lists insrc/inject.gen.ts, a generated
file likeapi.gen.ts, which the app module imports first. It is plain code, so any test runner
works, and it changes only when a constructor does. Classes, and tokens named like their type
(PrismaClient,Config,createToken<Db>()withinterface Db), are inferred; anything
else gets a warning (AVI201). Astatic injectin the class wins, so both styles mix. New
modular projects use it and their classes list nothing. avi inject [--check | --watch]writes the file once, checks it in CI, or watches without
compiling.avi devandavi buildtake--inject <file>and--no-inject.avi generate
updates the file when it adds a class.registerInjects()in core, what the generated file calls: it setsstatic injecton classes
that have none.
Changed
- The
InjectableandControllerdecorators accept a class with constructor parameters and nostatic inject:
its list comes frominject.gen.ts. A written list is still type-checked against the
constructor. Startup still fails, now with how to fix it, when a class has no list at all.
Fixed
avi buildnever removed stale files when the project path ran through a link above the project,
such as macOS/var(a link to/private/var) or a Windows short name, as CI runners use. The
safety check compared whole paths; it now compares the path inside the project, and expected
outputs by their place in the output folder.
v1.0.0-rc.2
The second release candidate for Avi.js 1.0, on npm's next tag; latest stays on 0.7.0. Install every Avi.js package from next during the release candidate, so they share one core.
Fixes from testing 1.0.0-rc.1: a correctness review, a security review, a new-user run of every
chapter from npm, deeper fuzzing and a stress run.
Security
avi buildcould delete files outside the project, or folders that were never build output. The
output folder was emptied after a string check, so a link in its path (a symlink or junction an
untrusted checkout can carry) led the delete elsewhere, and anoutDirsuch as.git,public
or one set by an extended config was wiped. It now deletes nothing on the first build in a
folder, only marks it, and later removes only compiled files (.js,.d.ts,.map) the build
no longer emits, in a real folder inside the project that is not hidden ornode_modules, and
not when the config has errors.avi client,avi devandavi buildrefuse to overwrite a file they did not generate, so a
mistyped--outor--clientcannot replace source code.onUpgradegives each connection its ownsignal. All connections shared one, so listeners
added per connection, as chapter 7 shows, were kept for the life of the app: about 10 KB per
closed connection.api.events()refuses an event or line larger thanmaxEventSize(default 1 MiB, a new client
option) and a response that is nottext/event-stream. A stream without line breaks grew memory
without limit and took quadratic time.APPnow gives a read-only view withroutes(), not the app: throughapp.get()a module could
read providers it was never given, or close the app.
Added
OpenApiModule.forRoot({ guards, middleware })protects the document, and
openapi: { exclude: true }leaves a route out of it.avi devandavi buildtake--root, likeavi client.--helpworks for everyavicommand and fornpm create avi; an unknown option prints the
usage instead of a stack trace.- A startup failure that is not shown in a terminal prints one line on stderr, with the failing step
and the reason; a logger withinfogets anApplication failed to starterror entry.
AviFactory.create, as the templates use it, reported nothing before.
Fixed
- Response types from handlers turned into
anyin a frontend compiled without Node types, such
as a Vite app: a type importednode:stream. Only routes with a response schema kept theirs. avi dev --clientwith a file outside the TypeScript program never compiled or started the app.avi buildexited 0 when the client could not be generated, leaving it stale.app.get(APP)anddefineHook({ inject: [APP] })threw; supplied tokens now resolve there too.- The test client dropped headers given as a
Headersobject or as[name, value]pairs. - Config errors redacted variable names and allowed values (
Expected "[redacted]"). Only text
holding the received value is redacted now; a missing variable's message is shown as is. jsonLoggerprinted a plain-objectcause, such as validation issues, as[object Object].- On Windows, stopping
avi devleft the app running and its port taken. npm create avi my-app --template minimal, without--, made a modular app: npm swallows the
flag. A stray argument is now an error that says to put options after--.- A module made by another copy of the core package is named as such in the error. Packages now
depend on each other with^ranges, so npm can share one core across 1.x versions. avi clientno longer warns about modules made by a library, such as
OpenApiModule.forRoot(...): they have no app routes, like library modules referenced by name.- A failed
cluster()start printed its reason twice. - Generated tests no longer add a second error when their setup fails.
Docs
- Chapter 12 shows options with
AviFactory.create, as in the generatedmain.ts; chapter 17 says
to install every package fromnextduring a release candidate; chapter 8 says response
headersis aHeaders; chapter 7's summary table covers failures and the test client.
v1.0.0-rc.1
The first release candidate for Avi.js 1.0, published on npm's next tag; latest stays on 0.7.0 until 1.0.0. Until then, the stable API only gets fixes.
The first release candidate for 1.0. From here, the stable API only gets fixes until 1.0.0; see
the new chapter 17 for what 1.x promises.
Added
onUpgrade(req, socket, head, signal): hands upgrade requests, such as WebSockets, to a library
likews.signalaborts when shutdown starts, so connections can close politely; any still
open aftershutdownTimeoutare destroyed, and upgrades during shutdown get503. Chapter 7
shows WebSockets withws.
Changed
avi devruns the app withNODE_ENV=developmentunless you set it, socluster()stays in one
process during development, as chapter 16 says. It used to start a worker per core.
Docs
- A pass over every chapter against the final API: examples use
defineFactoryandctx.need,
the pipeline example no longer overwrites the built-in request id, chapter 9 shows the minimal
template as generated, chapter 2 says repeated slashes in route definitions are collapsed, and
several imports, file trees and version banners are corrected. - Chapter 17, Stability and versions: what semver covers in 1.x, what is experimental or internal,
deprecations, supported Node.js and TypeScript versions, release channels. - Chapter 10 marks manifests as experimental.
- Chapter 12 explains that rate limits use fixed windows, and the burst that allows.
Fixed
avi clientnames a module it cannot read asforRoot(...)on one line, instead of quoting the
whole call across several lines.