npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aventara/build

v1.0.0-rc.12

Published

Compiles an Aventara application's Contracts at build time, for serverless and edge cold starts.

Readme

@aventara/build

The aventara-build command compiles an Aventara application's Contracts when the project is built, so a serverless or edge function loads them at a cold start instead of compiling them. It is a development dependency: nothing in your deployed application imports it.

npm install --save-dev --save-exact @aventara/build@<your @aventara/core version>

aventara new and aventara init add it and run it from the project's aventara:prepare script, after the adapter's generate step:

aventara-prisma7-generate … && aventara-build

What it reads and writes

Run it from the project's root. It writes three files, in this order, each from what the one before wrote, so a fresh install is right on its first aventara:prepare. They go to the directory your configuration imports aventaraResources from, beside the discovery artifact: src/generated/aventara/ normally, src/aventara/ when aventara init found Prisma's client generated into src/generated (which prisma generate would empty). A configuration that imports no tree keeps src/generated/aventara/.

| File | What it holds | |---|---| | resources.generated.ts | aventaraResources: every Resource your src/resources/**/*.resource.ts files define, one resources tree per layer | | computed-fields.generated.ts | computedFields (typed AvComputedFields): which fields the configuration's write compute fills, read off its type | | contracts.generated.ts | aventaraContracts (typed AvPrebuiltContracts): the compiled Contracts |

The Resource tree

Each Resource's configuration lives in its own file under src/resources/, named <name>.resource.ts, as an exported defineResource(...) result. The build reads those files through TypeScript (it never runs them), takes every export whose type is a defineResource result, and writes the spreads you would otherwise write by hand:

// src/generated/aventara/resources.generated.ts (generated)
import { post } from "../../resources/post.resource.js";
import { session } from "../../resources/session.resource.js";

export const aventaraResources = {
  root: { ...post.root, ...session.root },
  client: { ...post.client },
} as const;

root is always there; application, client and agent only when some Resource gives that layer a block. The configuration takes the trees once, and a new Resource file needs no edit to it:

// src/aventara.config.ts
import { aventaraResources } from "./generated/aventara/resources.generated.js";

export const aventaraConfig = {
  api: "/api",
  exposed: true,
  resources: aventaraResources.root,
  client: { exposed: true, resources: aventaraResources.client },
} as const;

Two files defining the same Resource stop the build, naming both: spread by hand, the later spread silently replaced the earlier block. The imports are spelled as your project spells its own, by the rule avclient follows for the client it writes: .js in an ES module under nodenext, none with module: "commonjs" or moduleResolution: "bundler", .ts with allowImportingTsExtensions. One difference: a CommonJS package under nodenext (Nest's CommonJS scaffold) gets no suffix either, as the scaffold writes its own imports there, because these files import values and the jest such a project tests with resolves no .js specifier to a .ts file. The tree is the same expression you would write, so it costs the same type checking. The files matched are src/resources/**/*.resource.ts; the pattern is not configurable yet.

The computed fields

The build reads which fields the configuration's compute.create and compute.update stages fill off the configuration's TypeScript type, after it wrote the tree, and writes them to computed-fields.generated.ts. The Prisma adapter's discovery artifact imports that file as its sibling (its generate step is given --config src/aventara.config.ts), so a variant's guards, pipes and filters, which run before compute, may leave exactly those fields out of a create. Where the configuration is not a literal (a wide AvConfig annotation, a conditional spread), the build prints where and the file states nothing (null): those stages may then leave any create field out. A server warns AVENTARA_STALE_GENERATED_TYPES at startup when the configuration computes other fields than the file says.

The Contracts

To compile the Contracts it runs two of your modules, in TypeScript or JavaScript, ES module or CommonJS:

| File | What it must export | |---|---| | src/aventara.config.ts | aventaraConfig (or a default export): the configuration as a plain value, without adapter | | src/aventara.adapter.ts | a default export: the adapter's description, describePrismaAdapter({ discovery, provider, driver }) for Prisma 7 |

It compiles the four Contracts with your project's own @aventara/core, from the configuration and the model the description holds, and writes src/generated/aventara/contracts.generated.ts, whose export aventaraContracts is typed AvPrebuiltContracts. It never constructs a database client and never connects to a database. The file is generated: keep it out of git, as the scaffold's .gitignore does, and never edit it.

A configuration that a server would refuse at startup fails the build instead: every CONFIG_… and COMPILER_… diagnostic is printed with its path and documentation link, nothing is written, and the command exits 1.

Because the build runs src/aventara.config.ts, everything it imports runs at build time too. Keep its top level free of side effects (no connection, no request). A value read from process.env is read when the build runs.

Before it runs them, the build reads the project's .env files into process.env, the same files avclient generate reads and with the same precedence: a variable already set in the environment wins, then .env.<mode>.local, .env.<mode>, .env.local and .env, where the mode is NODE_ENV (else development). So a module that reads DATABASE_URL when it is imported runs at build time as it does under next dev. A .env line that would be ignored (not a NAME=value assignment) fails the build, naming the file and the line.

Next.js projects

A project whose package.json depends on @aventara/next keeps everything Aventara in one folder, src/aventara/. The build runs src/aventara/config.ts and src/aventara/adapter.ts there instead of src/aventara.config.ts and src/aventara.adapter.ts, and a configuration that imports no Resource tree has its files in src/aventara/generated/. Every other project keeps the paths above.

--client

aventara-build --client

In a Next.js project, --client also writes the browser client, from the ClientContract the build has just compiled, so no running server is needed:

| File | What it holds | |---|---| | src/aventara/client.ts | avClient, the typed client calling the app's own api (/api) from the browser, and avHydrate; and every name avclient generate's AvClient.ts exports besides its default: AvClient, the Resource types, the enums, AvDecimal and the error classes | | src/aventara/universal.ts | avClient for both sides: in the browser it calls the app's own api, on the server it calls the app in process, through what ready() from @aventara/next registers in src/instrumentation.ts, with that request's state | | src/aventara/generated/ (the client's modules) | the same modules avclient generate writes for the same ClientContract, but with the app's own api as the entrypoint, and saying to regenerate them with aventara-build --client |

Import it as @/aventara/client in Client Components, and @/aventara/universal in code that runs on both sides (a TanStack Query queryFn prefetched on the server, for example). The files import nothing from @aventara/client or @aventara/next, so the app needs no generator at run time. avClient calls the API from the browser only: a call made on the server, while a Client Component renders there, is refused with a sentence pointing to @/aventara/server and @/aventara/universal. The universal avClient answers the same values on both sides; on a server where ready() has not run, a call is refused with a sentence naming src/instrumentation.ts and ready(). avHydrate revives data avDehydrate sent from the server (dates, bigints, byte arrays and decimals, a decimal as the client's own AvDecimal), for TanStack Query's deserializeData or an SWR fallback.

avclient generate stays the way to generate a client for a separate frontend. In a NestJS project --client is refused.

--check

aventara-build --check
aventara-build --check --client

Writes nothing. It exits 0 when the three files on disk are the ones a build would write now, and 1 on the first that is missing or stale, naming it (and, for the Contracts, the Resources whose configuration or model changed). With --client, the browser client's files are checked too, after the Contracts: a missing or stale file, or one an earlier ClientContract's client left, exits 1. Run it in CI before a deploy.

Using the file

Pass aventaraContracts as prebuilt where the framework is created, beside the adapter:

// a serverless or edge entry
import { createFramework } from "@aventara/core";
import { createPrismaAdapter } from "@aventara/prisma7-adapter";
import adapter from "./aventara.adapter.js";
import { aventaraConfig } from "./aventara.config.js";
import { aventaraContracts } from "./generated/aventara/contracts.generated.js";
import { prisma } from "./prisma.client.js";

export const framework = await createFramework({
  ...aventaraConfig,
  adapter: await createPrismaAdapter({ ...adapter, client: prisma }),
  prebuilt: aventaraContracts,
});

The framework uses the file only when it was compiled by the same @aventara/core, for the same protocol, from the same configuration and model. Otherwise it ignores the whole file, compiles at startup as it would without one, and warns once with AVENTARA_PREBUILT_STALE, naming what changed. A stale file never serves a wrong Contract; it only costs the startup time the file was meant to save.

A long-running server does not need the file. The Nest project aventara new writes compiles its Contracts at startup and passes no prebuilt.