Skip to content

Releases

v1.1.0

Choose a tag to compare

@chrischase011 chrischase011 released this 09 Nov 03:44

Added

  • Lifecycle hooks for singletons: an onInit() method runs once every singleton exists, before
    routes are built; onShutdown() runs when app.close() starts, once new connections are refused and while
    requests in flight finish.
    Factory providers take them as onInit and onShutdown options. OnInit and OnShutdown
    types for implements. runWorker() runs them too.
  • A new pubsub package: typed channels (defineChannel), publish, subscribe, on, and events()
    for sse(). Adapters for one process (memoryAdapter), every cluster() worker
    (clusterAdapter, through the primary) and Redis (redisAdapter for redis, ioredisAdapter
    for ioredis). 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 as sse(), as soon as shutdown starts: their
    signal aborts and sse() streams finish. Before, they held the shutdown until
    shutdownTimeout. A stream that ignores its signal still gets the full timeout.
  • When an onShutdown hook 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

Choose a tag to compare

@chrischase011 chrischase011 released this 05 Nov 06:25

Fixed

  • AVI203 missed a devDependency reached through an imports entry with only an "import"
    condition: imports were resolved as require would. 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 } from the workers package), or under another name
    (import { cluster as boot }). A re-export with export * is still not followed.
  • AVI203 took another package's export imported under the name cluster or runWorker for Avi.js's
    (import { createAvi as cluster } from the core package).
  • avi build, avi check, avi client, avi inject and avi-compile printed a stack trace for
    a tsconfig they cannot read. They now print Cannot read file '…/nope.json'. and exit with 1.
  • avi dev and avi build look 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 as joy / joy-to-the-world.

v1.0.1

Choose a tag to compare

@chrischase011 chrischase011 released this 05 Nov 05:02

Fixed

  • AVI203 missed a devDependency reached through an import cycle or a paths alias, so
    inject.gen.ts could 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:
    runWorker and cluster count when imported from Avi.js, listen unless the project defines
    it, and setInterval and setTimeout now count too.
  • The first avi build after 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 inject and avi-compile take -p for
    --project.
  • avi bogus and avi bogus --help say Unknown command "bogus" and exit with 2, and
    avi g widget foo says Unknown kind "widget".
  • npm create avi -- --help described avi new; it now prints its own usage.

v1.0.0

Choose a tag to compare

@chrischase011 chrischase011 released this 05 Nov 03:41

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 build with rc.6 or later takes the old .avi-build list as its own tsconfig's.
    With two tsconfigs sharing an outDir, that build may remove the other's output once; the
    other's next build writes it back.
  • A class that inherits static inject and takes more constructor arguments fails at startup
    (from rc.6). avi dev and avi build give it its own list; without them, add static 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 as setInterval, are not caught,
    and a top-level bus.listen(...) is flagged although it starts no server.
  • The devDependency check for inject.gen.ts follows relative imports only, not paths aliases,
    and can miss a devDependency reached through an import cycle.

v1.0.0-rc.6

v1.0.0-rc.6 Pre-release
Pre-release

Choose a tag to compare

@chrischase011 chrischase011 released this 05 Nov 03:06

Fixes from testing 1.0.0-rc.5.

Fixed

  • A class that inherits static inject but whose constructor takes more arguments got
    undefined for 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.ts imported 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, so fetch, api.events() and
    EventSource connected late on a quiet stream. A stream now starts with the comment : open.
  • avi build deleted another tsconfig's output when two shared an outDir, so
    avi build -p tsconfig.server.json && avi build -p tsconfig.worker.json left only the worker.
    .avi-build now 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 calling handle.restart() only in the primary, and says Windows may not spread
    connections evenly.

v1.0.0-rc.5

v1.0.0-rc.5 Pre-release
Pre-release

Choose a tag to compare

@chrischase011 chrischase011 released this 29 Oct 09:37

Fixes from testing 1.0.0-rc.4.

Fixed

  • inject.gen.ts imported other entry points: a worker or a seed script that registered or
    created an app was imported by the web app, so its code ran there, and a browser file calling
    navigator.serviceWorker.register crashed it. rc.4 guessed entry points by name, which also
    missed some (an app created in a helper, an aliased import). Now inject.gen.ts only 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 build threw a raw error when it could not write an output file; it now reports TS5033, as
    tsc does.
  • 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 build did 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 add import './inject.gen.js'.
  • Files compiled by avi dev were never cleaned, so a test deleted while it ran kept running in
    npm test. avi dev now adds what it compiles to the list avi build cleans from.
  • A watcher could still write a generated file after close().
  • avi inject --help and the other commands printed the full usage; they print their own now.
  • avi g --dry-run now ends with Dry run: nothing was written.
  • New projects' README lists npm run build and npm 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

v1.0.0-rc.4 Pre-release
Pre-release

Choose a tag to compare

@chrischase011 chrischase011 released this 27 Oct 06:19

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 as app.module.ts or main.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.ts imported 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 undefined dependencies: 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, as constructor.length does.
  • An object with a description named like a type was taken for a token. Only classes,
    constructors, and createToken and defineConfig values 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 build removed any compiled-looking file without a source, including one written by hand,
    a bundler's assets and output compiled from outside include (a sibling shared/ 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.ts too, so avi inject --check passes and its
    services can take dependencies without static inject.
  • avi inject and avi client write next to the --project tsconfig, like avi dev.
    avi g no longer rewrites inject.gen.ts for line endings alone.
  • avi --version prints the version; avi g --help shows the generate usage; the hint for a
    missing -- names the next decorator during a release candidate.

Docs

  • Chapters 3, 8 and 16: an entry point or test that skips app.module.ts imports
    inject.gen.js itself. 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 next decorator during the release
    candidate.

v1.0.0-rc.3

v1.0.0-rc.3 Pre-release
Pre-release

Choose a tag to compare

@chrischase011 chrischase011 released this 27 Oct 04:35

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 dev and avi build read constructor types with
    the TypeScript compiler they already run and keep the lists in src/inject.gen.ts, a generated
    file like api.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>() with interface Db), are inferred; anything
    else gets a warning (AVI201). A static inject in 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 dev and avi build take --inject <file> and --no-inject. avi generate
    updates the file when it adds a class.
  • registerInjects() in core, what the generated file calls: it sets static inject on classes
    that have none.

Changed

  • The Injectable and Controller decorators accept a class with constructor parameters and no static inject:
    its list comes from inject.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 build never 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

v1.0.0-rc.2 Pre-release
Pre-release

Choose a tag to compare

@chrischase011 chrischase011 released this 27 Oct 02:55

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 build could 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 an outDir such 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 or node_modules, and
    not when the config has errors.
  • avi client, avi dev and avi build refuse to overwrite a file they did not generate, so a
    mistyped --out or --client cannot replace source code.
  • onUpgrade gives each connection its own signal. 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 than maxEventSize (default 1 MiB, a new client
    option) and a response that is not text/event-stream. A stream without line breaks grew memory
    without limit and took quadratic time.
  • APP now gives a read-only view with routes(), not the app: through app.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 dev and avi build take --root, like avi client.
  • --help works for every avi command and for npm 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 with info gets an Application failed to start error entry.
    AviFactory.create, as the templates use it, reported nothing before.

Fixed

  • Response types from handlers turned into any in a frontend compiled without Node types, such
    as a Vite app: a type imported node:stream. Only routes with a response schema kept theirs.
  • avi dev --client with a file outside the TypeScript program never compiled or started the app.
  • avi build exited 0 when the client could not be generated, leaving it stale.
  • app.get(APP) and defineHook({ inject: [APP] }) threw; supplied tokens now resolve there too.
  • The test client dropped headers given as a Headers object 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.
  • jsonLogger printed a plain-object cause, such as validation issues, as [object Object].
  • On Windows, stopping avi dev left 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 client no 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 generated main.ts; chapter 17 says
    to install every package from next during a release candidate; chapter 8 says response
    headers is a Headers; chapter 7's summary table covers failures and the test client.

v1.0.0-rc.1

v1.0.0-rc.1 Pre-release
Pre-release

Choose a tag to compare

@chrischase011 chrischase011 released this 27 Oct 01:10

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
    like ws. signal aborts when shutdown starts, so connections can close politely; any still
    open after shutdownTimeout are destroyed, and upgrades during shutdown get 503. Chapter 7
    shows WebSockets with ws.

Changed

  • avi dev runs the app with NODE_ENV=development unless you set it, so cluster() 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 defineFactory and ctx.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 client names a module it cannot read as forRoot(...) on one line, instead of quoting the
    whole call across several lines.