Turbocache

Runnable Server is a great way to build a scalable admin tool. You can connect many clients, for example, a user-service
and an email-service
that can stream their actions to a central location using the Runnable SDK. This is great for services not exposed to the public internet and for services that may be deployed with multiple instances.
You can deploy runnable as a dockerized container.
docker pull ghcr.io/kineticio/runnable:latest
docker pull ghcr.io/kineticio/runnable:latest
Pin Version
It is recommended to pin to a particular version. You can find the latest package version here.
Environment Variable | Description | How to Generate |
---|---|---|
RUNNABLE_BASE_URL | The base URL for your Runnable instance. This has a default of /admin for Runnable Mini, but should override to be / . | Should just provide '/' |
RUNNABLE_SECRET | A secret key used for encrypting the user's cookie session. | Run openssl rand -hex 32 in your terminal |
RUNNABLE_AUTH_SECRET | A secret key used during the handshake between a Runnable Server and Runnable SDK Client. | Run openssl rand -hex 32 in your terminal |
RUNNABLE_AUTH_PROVIDER_GOOGLE_CLIENT_ID | The client ID for the Google authentication provider. | Generated by Google. |
RUNNABLE_AUTH_PROVIDER_GOOGLE_CLIENT_SECRET | The client secret for the Google authentication provider. | Generated by Google. |
RUNNABLE_AUTH_PROVIDER_GOOGLE_HOSTNAME | The hostname for the Google authentication provider. | E.g. https://admin.company-name.com |
RUNNABLE_AUTH_PROVIDER_GOOGLE_HD | The hosted domain for the Google authentication provider. Setting this will limit the email domain allowed to login. | Provided by Google. |
With npm
npm install -D @runnablejs/sdk
npm install -D @runnablejs/sdk
or with yarn
yarn add -D @runnablejs/sdk
yarn add -D @runnablejs/sdk
or with pnpm
pnpm add -D @runnablejs/sdk
pnpm add -D @runnablejs/sdk
// index.ts
import { userInfo } from 'node:os';
import { RunnableWs } from '@runnablejs/sdk';
import { getUsers, getTeams, assignTeam } from './db';
import { auth } from './auth';
new RunnableWs(actions, {
// Your admin portal. This can be a staging, development, or local URL.
runnableHost: 'wss://admin.company-name.com',
// Some domain displayed to the user and used to dedupe among multiple instances of the same server.
namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
// Can be a custom logger or defaults to console.
logger: console,
// Shared auth token between Runnable client nad Runnable server.
token: process.env.RUNNABLE_AUTH_SECRET,
}).start();
// index.ts
import { userInfo } from 'node:os';
import { RunnableWs } from '@runnablejs/sdk';
import { getUsers, getTeams, assignTeam } from './db';
import { auth } from './auth';
new RunnableWs(actions, {
// Your admin portal. This can be a staging, development, or local URL.
runnableHost: 'wss://admin.company-name.com',
// Some domain displayed to the user and used to dedupe among multiple instances of the same server.
namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
// Can be a custom logger or defaults to console.
logger: console,
// Shared auth token between Runnable client nad Runnable server.
token: process.env.RUNNABLE_AUTH_SECRET,
}).start();
Create the providers for the RunnableWorkflows
.
// actions.provider.ts
import { FactoryProvider, Provider } from '@nestjs/common';
import { RunnableWorkflows, RunnableAppContext } from '@runnablejs/express';
import { AppService } from './app.service';
export const ActionsProvider: FactoryProvider<RunnableWorkflows> = {
provide: 'RUNNABLE_ACTIONS',
inject: [DatabaseService],
useFactory: (database: DatabaseService) => ({
assign_user_to_team: {
// ...
},
create_user: {
// ...
},
}),
};
// actions.provider.ts
import { FactoryProvider, Provider } from '@nestjs/common';
import { RunnableWorkflows, RunnableAppContext } from '@runnablejs/express';
import { AppService } from './app.service';
export const ActionsProvider: FactoryProvider<RunnableWorkflows> = {
provide: 'RUNNABLE_ACTIONS',
inject: [DatabaseService],
useFactory: (database: DatabaseService) => ({
assign_user_to_team: {
// ...
},
create_user: {
// ...
},
}),
};
Create the module for the Actions
.
// actions.module.ts
import { Module } from '@nestjs/common';
import { ActionsProvider } from './actions.provider';
@Module({
imports: [DatabaseModule],
providers: [ActionsProvider],
})
export class ActionsModule {}
// actions.module.ts
import { Module } from '@nestjs/common';
import { ActionsProvider } from './actions.provider';
@Module({
imports: [DatabaseModule],
providers: [ActionsProvider],
})
export class ActionsModule {}
Start your Next.js application with Actions
.
// main.ts
import { installRunnable } from '@runnablejs/express';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Setup Runnable
const actions = app.get('RUNNABLE_ACTIONS');
const config = new RunnableWs(actions, {
// Your admin portal. This can be a staging, development, or local URL.
runnableHost: 'wss://admin.company-name.com',
// Some domain displayed to the user and used to dedupe among multiple instances of the same server.
namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
// Can be a custom logger or defaults to console.
logger: app.get(Logger),
// Shared auth token between Runnable client nad Runnable server.
token: process.env.RUNNABLE_AUTH_SECRET,
}).start();
await app.listen(3000);
}
bootstrap();
// main.ts
import { installRunnable } from '@runnablejs/express';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Setup Runnable
const actions = app.get('RUNNABLE_ACTIONS');
const config = new RunnableWs(actions, {
// Your admin portal. This can be a staging, development, or local URL.
runnableHost: 'wss://admin.company-name.com',
// Some domain displayed to the user and used to dedupe among multiple instances of the same server.
namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
// Can be a custom logger or defaults to console.
logger: app.get(Logger),
// Shared auth token between Runnable client nad Runnable server.
token: process.env.RUNNABLE_AUTH_SECRET,
}).start();
await app.listen(3000);
}
bootstrap();