Skip to main content


Library for creating and working with papi handlers. More on papi feature you can find here


You need to install @tramvai/papi

npm i @tramvai/papi


Library mostly provides strong typings to papi handlers and most of the logic of integration it to the tramvai app is done by @tramvai/module-server




  • path - specifies the path of url that current papi should handle. Required when specifying papi in tramvai DI, and not used when specified through file api.
  • method - specified HTTP-method that is acceptable by current papi. By default, it equals to "all"
  • handler - see handler
  • deps - any DI deps that papi may require
  • options - additional options that controls how current papi works
    • timeout - timeout for executing current papi. If timeout exceeded request is resolved with Execution timeout error.


Function that handles actual request and should return. It accepts the details of the request and should return the response

Details of the request are passed with first parameter when handler is called. You can see available properties in typings when specifying papi method. It should provide most of the data that might be required to handle the request.

Additionally, though this passed data that bounded to papi method:

  • deps - resolved deps that were specified when defining papi method. Deps are resolved with Child DI Container, so do not use it for creating caches as it won't work.
  • log - instance of LOGGER_TOKEN bounded with current papi method


Type guard to check is passed object is papi handler

How to

Create simple papi

import { createPapiMethod } from '@tramvai/papi';

export const papi = createPapiMethod({
// will handle requests to `/app/papi/my/papi` (actual url depends on setup)
path: '/my/papi',
// only requests with GET http method will be handled
method: 'get',
// function to return response to the client
async handler() {
return 'test';

Use parameters of the request

import { createPapiMethod } from '@tramvai/papi';

export const papi = createPapiMethod({
async handler({ query, cookies }) {
const { a, b } = query;
const { testCookie } = cookie;

return {

Settings headers and status

It can be done with responseManager

import { createPapiMethod } from '@tramvai/papi';

export const papi = createPapiMethod({
async handler({ responseManager }) {
responseManager.setHeader('content-type', 'text/html');

return `<html>...</html>`;

Use deps

import { createPapiMethod } from '@tramvai/papi';

export const papi = createPapiMethod({
async handler() {
const { cookieManager } = this.deps;

cookieManager.set({ name: 'b', value: 'abc', expires: 35 });

return "response";
deps: {

Use cache with deps

Deps are resolved with ChildContainer that means they are getting resolved on every request in order to provide request specific info. To use any of deps that should outlive scope of the request you should use provider that was initialized with scope=SINGLETON

For example, if you want to use some papi specific cache you should create new token and provide the cache instance with that token and with option scope: Scope.SINGLETON

import { createToken, Scope, provide } from '@tinkoff/dippy'
import { createApp } from '@tramvai/core';
import { createPapiMethod } from '@tramvai/papi';
import { Cache, CREATE_CACHE_TOKEN } from '@tramvai/tokens-common';

export const PAPI_CACHE_TOKEN = createToken<Cache<string>>('app papi cache');

const app = createApp({
// ...,
providers: [
// ...,
scope: Scope.SINGLETON,
useFactory: ({ createCache }) => {
return createCache('memory');
deps: {

export const papi = createPapiMethod({
async handler({ query }) {
const { cacheKey } = query;
const { cache } = this.deps;

if (cache.has(cacheKey)) {
return cache.get(cacheKey);

const result = heavyComputation();

cache.set(cacheKey, result);

return result;
deps: {