Skip to content

0. Getting started ​

Status: Runnable. Everything on this page works with the packages on npm.

This chapter creates an Avi.js project with npm create avi, tours the generated files and adds a feature with the CLI.

You need Node.js 22.12 or newer. Check with node --version.

Create a project ​

sh
npm create avi@latest my-api
cd my-api
npm install
npm run dev
text
Listening on http://localhost:3000

Open http://localhost:3000/users. npm run dev recompiles and restarts on every change.

Without a name, npm create avi@latest asks for the name and the template. There are two:

TemplateCommandFor
modular (default)npm create avi@latest my-apiFeature modules, decorators
minimalnpm create avi@latest my-api -- --template minimalPlain routes and services

Both run on the same engine; chapter 9 compares them.

What you get ​

The modular template:

text
my-api/
├── src/
│   ├── main.ts                    starts the app
│   ├── app.module.ts              the root module
│   ├── common/
│   │   └── health.controller.ts   GET /health
│   └── modules/users/
│       ├── users.module.ts
│       ├── users.controller.ts    GET /users, GET /users/:id, POST /users
│       ├── users.service.ts
│       ├── users.test.ts
│       └── dto/
├── package.json
└── tsconfig.json
ScriptWhat it does
npm run devCompile, then recompile and restart on every change
npm testCompile and run the tests with node --test
npm run buildCompile to dist/
npm startRun the compiled app
npm run checkCheck every static inject list against its class

Add a feature ​

The CLI creates files and registers them for you. One command gives you a module, a service and a controller with working CRUD routes:

sh
npx avi g resource posts

http://localhost:3000/posts now lists, creates, updates and deletes posts, kept in memory until you connect a database.

Instead of a resource, you can create the pieces one at a time and write the routes yourself:

sh
npx avi g module posts
npx avi g service posts
npx avi g controller posts
text
CREATE src/modules/posts/posts.module.ts
UPDATE src/app.module.ts
CREATE src/modules/posts/posts.service.ts
UPDATE src/modules/posts/posts.module.ts
CREATE src/modules/posts/posts.controller.ts
UPDATE src/modules/posts/posts.module.ts

npm run dev picks the change up, and http://localhost:3000/posts answers []. The controller injects the service it found next to it:

ts
@Controller('/posts')
export class PostsController {
  static inject = [PostsService] as const;

  constructor(private readonly posts: PostsService) {}

  @Get()
  findAll() {
    return this.posts.findAll();
  }
}

static inject lists the constructor's dependencies in order. That list is how Avi.js wires classes together without reflect-metadata, and TypeScript checks it against the constructor.

Add Avi.js to an existing project ​

sh
npm install @avijs/core
ts
import { createAvi, defineController } from '@avijs/core';

const app = createAvi().register({
  controllers: [
    defineController({
      routes: [{ method: 'GET', path: '/', handler: () => ({ hello: 'world' }) }],
    }),
  ],
});
await app.listen(3000);

Avi.js is ESM. Use "type": "module" and "module": "NodeNext" in tsconfig.json, and leave experimentalDecorators off: Avi.js uses standard decorators.

Next ​

Chapter 1: Your first app walks through a small app line by line. To work on Avi.js itself, see CONTRIBUTING.md.

Released under the MIT License.