Installation
Get up and running with Vla in minutes. This guide will walk you through installation, basic setup, and your first Action.
Installation
Section titled “Installation”Install Vla using your preferred package manager:
npm install vlapnpm add vlayarn add vlabun add vlaBasic Setup
Section titled “Basic Setup”Vla works with any server-side JavaScript framework. The basic setup involves:
- Creating a Kernel
- Setting up the Kernel for invocation
- Creating your first classes
1. Create a Kernel
Section titled “1. Create a Kernel”The Kernel is Vla’s dependency injection container. Create one in a central location:
import { Vla } from "vla"
export const kernel = new Vla.Kernel()Then setup the Kernel for invocation, so Vla knows what request context it’s in.
For any framework that supports middleware to wrap a request, often with a next() function:
import { Vla } from "vla"import { kernel } from "./data/kernel"
const app = express() // or anything else
app.use((req, res, next) => { return Vla.withKernel(kernel.scoped(), () => next())})Next.js has no middleware, but we can pass React’s cache() into Vla, so it can create a new scope
for every request.
import { cache } from "react"import { Vla } from "vla"
export const kernel = new Vla.Kernel()
Vla.setInvokeKernelProvider( cache(() => kernel.scoped()))And import it in your layout:
import "../data/kernel"
export default function RootLayout() { //}SvelteKit has “Hooks” that work like middleware:
import type { Handle } from "@sveltejs/kit"import { Vla } from "vla"import { kernel } from "./data/kernel"
export const handle: Handle = async ({ event, resolve }) => { return Vla.withKernel(kernel.scoped(), () => { return resolve(event) })}Tanstack Start support global request middleware:
import { createMiddleware, createStart } from "@tanstack/react-start"import { Vla } from "vla"import { kernel } from "./data/kernel"
const vlaMiddleware = createMiddleware().server(async ({ next }) => { return Vla.withKernel(kernel.scoped(), () => next())})
export const startInstance = createStart(() => { return { requestMiddleware: [vlaMiddleware], }})Most server-side frameworks or libraries support middleware in some way. You can call Vla.withKernel() inside your middleware
import { Vla } from "vla"import { kernel } from "./data/kernel"
export function middleware((req, res, next)) { const scoped = kernel.scoped() return Vla.withKernel(scoped, () => next())}If you do not have requests and don’t need separate scopes per request, you can set a global kernel:
import { Vla } from "vla"
export const kernel = new Vla.Kernel()Vla.setGlobalInvokeKernel(kernel.scoped())2. Write your First Action
Section titled “2. Write your First Action”Actions are entry points to your data layer. They’re invoked from your framework’s route handlers, server actions, or API endpoints.
import { Vla } from "vla"
export class GetUser extends Vla.Action { repo = this.inject(UserRepo)
async handle(params: YourFrameworkParams) { return this.repo.findById(params.id) }}
class UserRepo extends Vla.Repo { db = this.inject(Db)
findById = this.memo((id: string) => { return this.db.users[id] })}
class Db extends Vla.Resource { // Mock database for this example db = { users: { } }
static readonly unwrap = "db"}3. Invoke Actions in Your Framework
Section titled “3. Invoke Actions in Your Framework”Actions can be invoked from anywhere in your application:
import { GetUser } from "@/data/users.actions"
export default async function UserPage({ params }) { const user = await GetUser.invoke(params)
return ( <div> <h1>{user.name}</h1> <p>{user.email}</p> </div> )}import { GetUser } from "$lib/data/users.actions"import type { PageServerLoad } from "./$types"
export const load: PageServerLoad = async ({ params }) => { const user = await GetUser.invoke(params) return { user }}Tanstack Start support global request middleware:
import { createFileRoute } from "@tanstack/react-router"import { createServerFn } from "@tanstack/react-start"import { GetUser } from "@/data/users.actions"
const getUserFn = createServerFn({ method: "GET" }).handler(async () => { const user = await GetUser.invoke(params) return { user }})
export const Route = createFileRoute("/")({ component: Home, loader: () => getUserFn(),})
function Home() { const { user } = Route.useLoaderData()}import express from "express"import { GetUser } from "@/data/users.actions"
const app = express()
app.get('/users/:id', async (req, res) => { const user = await GetUser.invoke(req.params) res.json(user)})Next Steps
Section titled “Next Steps”Now that you have Vla set up, learn about:
- Adding Actions - Follow a step by step guide to work with Actions, Services, Repos and Resources
- Why Vla? - Learn more about the benefits of using Vla in your app