NestJS
Configure Aviato through Nest modules, injected plugins, and decorated service methods.
Nest modules, dependency injection and decorators for the Aviato TypeScript SDK. Requires NestJS 12, Node.js 22.22.1 or newer, and an existing Aviato agent. Installing this package does not install the agent.
npm install @getaviato/nestjs @getaviato/sdkShips ESM JavaScript and declarations. Node 22.22.1+ also supports loading the
package from CommonJS Nest applications. Enable experimentalDecorators and
emitDecoratorMetadata in your TypeScript configuration, as in a standard Nest app.
Configure once
import { Injectable, Module } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AviatoModule, AviatoAction, type ActionContext } from '@getaviato/nestjs';
@Injectable()
class CustomerActions {
@AviatoAction({ collection: 'customers', name: 'Confirm selection', scope: 'single' })
async confirm(context: ActionContext) {
const records = await context.getRecords();
return records.length === 1
? context.success('Customer selected')
: context.error('Select one customer you can read');
}
}
@Module({
imports: [AviatoModule.forRoot({ secret: process.env.AVIATO_PLUGIN_SECRET! })],
providers: [CustomerActions],
})
class AppModule {}
const app = await NestFactory.create(AppModule, { rawBody: true });
await app.listen(3000);rawBody: true is required for signature verification. Keep Nest's built-in body
parser enabled. Express and Fastify are supported. Their parser limits apply before
the SDK's 10 MiB limit; configure them separately if your payloads exceed the host's
defaults. Configure AVIATO_PLUGIN_URL=http://your-app:3000/aviato and the same
AVIATO_PLUGIN_SECRET on the agent. A Nest global prefix is included in this URL:
app.setGlobalPrefix('api') means /api/aviato.
Set path: 'internal/aviato' to change the controller mount. Paths contain literal
segments, not route patterns. Async configuration uses the same static path option:
AviatoModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
path: 'internal/aviato',
useFactory: (config: ConfigService) => ({
secret: config.getOrThrow<string>('AVIATO_PLUGIN_SECRET'),
}),
});Import the root configuration exactly once. It exports a global AviatoPlugin
provider. Register decorated classes in any feature module's providers; discovery
runs at application bootstrap. Dependencies are ordinary Nest constructor injections.
Plugins through Nest providers
Use forFeature in your domain module to build integrations with injected configuration:
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AviatoModule, StripePlugin } from '@getaviato/nestjs';
@Module({
imports: [AviatoModule.forFeature({
imports: [ConfigModule],
providers: [{
provide: StripePlugin,
inject: [ConfigService],
useFactory: (config: ConfigService) =>
new StripePlugin({
credentialEnv: config.get<string>('STRIPE_WIDGET_ENV') ?? 'STRIPE_WIDGET_KEY',
readOnly: true,
}).invoices({
collection: 'customers',
name: 'billing',
customerId: { field: 'stripe_customer_id' },
}),
}],
plugins: [StripePlugin],
})],
})
export class BillingModule {}plugins is an explicit list of provider tokens implementing IntegrationPlugin.
Nothing is exposed merely because it is injectable. Each listed integration is
registered through the underlying SDK's use() method. useValue, useClass,
useFactory (including async factories), and useExisting are standard Nest providers.
For an existing plugin exported by another module, reuse its instance:
AviatoModule.forFeature({
imports: [ExistingBillingModule], // exports BillingIntegration
providers: [{ provide: 'AVIATO_BILLING', useExisting: BillingIntegration }],
plugins: ['AVIATO_BILLING'],
});You can also list BillingIntegration directly in plugins when the imported module
exports it. Parent module providers are not implicitly visible inside forFeature;
export them from an imported module or declare them in its providers option.
To reuse a plugin elsewhere, own and export it from your billing module, then import
that module into forFeature.
Construct the complete widget declaration in the constructor or factory, before
registration. Registration snapshots and validates widgets; later builder mutations
are not applied unless you explicitly call AviatoPlugin.use() again. Request-scoped
plugin dependencies are rejected at startup. Multiple plugins follow Nest dependency
initialization order, so use unique collection/name pairs across feature modules.
The underlying SDK replaces widgets with the same key; do not rely on import order
for overrides.
For prebuilt integrations, forRoot({ secret, plugins: [stripe] }) is also available.
An integration implements widgets(); it does not install new provider execution
code into the agent. The Stripe credential itself stays in the customer agent's
environment. Configure a restricted key with Read/None permissions. Only its
environment-variable name belongs in Nest configuration.
Decorators and the full SDK
| Decorator | Method arguments | Returns |
|---|---|---|
@AviatoAction(options) | ActionContext | Action result or undefined |
@AviatoComputedField(options) | records, caller context | One JSON value per record |
@AviatoHook(options) | hook context | Rejection, changed values, or undefined |
@AviatoSegment(options) | caller context | Filter or record IDs |
@AviatoSearch(options) | query, caller context | Filter |
@AviatoChart(options) | filter, caller context | Vega-Lite specification |
@AviatoWriteOverride(options) | value, record, caller context | Record patch |
Options match the SDK definition, excluding the decorated callback. Methods may return promises. One Aviato decorator is allowed per method. Duplicate decorated keys fail at startup, except hooks, which may compose. Handlers must be singleton providers with singleton dependencies; request-scoped and transient handlers are rejected. Symbol-named methods are not discovered; use ordinary named methods.
Inject AviatoPlugin for custom datasources, summaries, relation hints, dynamic forms,
widgets and other SDK features. Register these in onModuleInit() before bootstrap.
Use the core SDK's types and ui helpers from @getaviato/sdk. An instance method
used as a dynamic form callback must be bound to its service when registered.
The HTTP controller participates in Nest's global guards, interceptors and filters.
Allow the signed Aviato endpoint through any browser-session-only guard using your
application's guard configuration. SDK signature verification remains mandatory.
Decorated provider methods are ordinary service calls: controller pipes, method guards
and interceptors are not automatically applied to them. Use ActionContext for the
Aviato caller, not Nest's request-scoped REQUEST token. Direct database or service
calls do not inherit Aviato record permissions; use context.getRecords() or
context.data for governed access.
See the TypeScript SDK for the underlying APIs and Stripe widgets for agent-side credentials and permissions.
For customer support data, Zendesk widgets provide a typed
ZendeskPlugin with user profiles, requested-ticket lists, and individual tickets.
Its OAuth scopes are verified by the customer agent before each data request.