railway-mcp
by jason-tan-swe
Verified
- src
import { z } from "zod";
/**
* NOTE: ALL NON-METAL RAILWAY REGIONS -- TODO: Update when they've fully migrated to metal đ
*/
export const RegionCodeSchema = z.enum([
"asia-southeast1",
"asia-southeast1-eqsg3a",
"europe-west4",
"europe-west4-drams3a",
"us-east4",
"us-east4-eqdc4a",
"us-west1",
"us-west2"
]);
// This creates the TypeScript type from the schema
export type RegionCode = z.infer<typeof RegionCodeSchema>;
export interface User {
id: string;
name: string | null;
email: string;
username: string | null;
}
// GraphQL Edge Types
export interface Edge<T> {
node: T;
}
export interface PageInfo {
hasNextPage: boolean;
hasPreviousPage: boolean;
startCursor?: string;
endCursor?: string;
}
export interface Connection<T> {
edges: Edge<T>[];
pageInfo: PageInfo;
}
// Project types
export interface Project {
id: string;
name: string;
description?: string;
environments: Connection<Environment>;
services: Connection<Service>;
teamId?: string;
baseEnvironmentId?: string;
createdAt: string;
updatedAt: string;
deletedAt?: string;
expiredAt?: string;
isPublic: boolean;
isTempProject: boolean;
prDeploys: boolean;
prEnvCopyVolData: boolean;
botPrEnvironments: boolean;
subscriptionType?: string;
subscriptionPlanLimit?: number;
}
export interface Environment {
id: string;
name: string;
projectId: string;
createdAt: string;
updatedAt: string;
deletedAt?: string;
isEphemeral: boolean;
unmergedChangesCount: number;
}
export interface Service {
id: string;
name: string;
projectId: string;
createdAt: string;
updatedAt: string;
deletedAt?: string;
icon?: string;
templateServiceId?: string;
templateThreadSlug?: string;
featureFlags: string[];
}
export const ServiceInstanceSchema = z.object({
id: z.string(),
serviceId: z.string(),
serviceName: z.string(),
environmentId: z.string(),
buildCommand: z.string().optional(),
startCommand: z.string().optional(),
rootDirectory: z.string().optional(),
region: RegionCodeSchema.optional(),
healthcheckPath: z.string().optional(),
sleepApplication: z.boolean().optional(),
numReplicas: z.number().optional(),
builder: z.string().optional(),
cronSchedule: z.string().optional(),
healthcheckTimeout: z.number().optional(),
isUpdatable: z.boolean().optional(),
railwayConfigFile: z.string().optional(),
restartPolicyType: z.string().optional(),
restartPolicyMaxRetries: z.number().optional(),
upstreamUrl: z.string().optional(),
watchPatterns: z.array(z.string()).optional()
});
export type ServiceInstance = z.infer<typeof ServiceInstanceSchema>;
export interface Deployment {
id: string;
status: string;
createdAt: string;
serviceId: string;
environmentId: string;
url?: string;
staticUrl?: string;
canRedeploy?: boolean;
canRollback?: boolean;
projectId: string;
meta?: Record<string, any>;
snapshotId?: string;
suggestAddServiceDomain?: boolean;
deploymentStopped?: boolean;
}
export interface DeploymentLog {
timestamp: string;
message: string;
severity: string;
attributes: {
key: string;
value: string;
}[];
type: 'build' | 'deployment';
}
export interface Variable {
name: string;
value: string;
serviceId?: string;
environmentId: string;
projectId: string;
}
// API Response types
export interface GraphQLResponse<T> {
data?: T;
errors?: {
message: string;
locations?: { line: number; column: number }[];
path?: string[];
}[];
}
export interface ProjectsResponse {
projects: Connection<Project>;
}
export interface ProjectResponse {
project: Project;
}
export interface ServicesResponse {
services: Connection<Service>;
}
export interface EnvironmentsResponse {
environments: Connection<Environment>;
}
export interface DeploymentsResponse {
deployments: Connection<Deployment>;
}
export interface VariablesResponse {
variables: Record<string, string>;
}
// API Input types
export interface ServiceCreateInput {
projectId: string;
name?: string;
source: {
repo?: string;
image?: string;
};
}
export interface VariableUpsertInput {
projectId: string;
environmentId: string;
serviceId?: string;
name: string;
value: string;
}
export interface VariableDeleteInput {
projectId: string;
environmentId: string;
serviceId?: string;
name: string;
}
export interface DeploymentTriggerInput {
commitSha?: string;
environmentId: string;
serviceId: string;
}
// Database types
export enum DatabaseType {
POSTGRES = 'postgres',
MYSQL = 'mysql',
MONGODB = 'mongodb',
REDIS = 'redis',
MINIO = 'minio',
SQLITE3 = 'sqlite3',
POCKETBASE = 'pocketbase',
CLICKHOUSE = 'clickhouse',
MARIADB = 'mariadb',
PGVECTOR = 'pgvector',
}
export interface DatabaseConfig {
source: string;
defaultName: string;
description: string;
category: string;
variables?: Record<string, string>;
port: number;
}
export const DATABASE_CONFIGS: Record<DatabaseType, DatabaseConfig> = {
[DatabaseType.POSTGRES]: {
source: 'ghcr.io/railwayapp-templates/postgres-ssl:15',
defaultName: 'PostgreSQL',
description: 'PostgreSQL database service',
category: 'SQL Databases',
port: 5432,
variables: {
// Variables for Railway
DATABASE_PUBLIC_URL: "postgresql://${{PGUSER}}:${{POSTGRES_PASSWORD}}@${{RAILWAY_TCP_PROXY_DOMAIN}}:${{RAILWAY_TCP_PROXY_PORT}}/${{PGDATABASE}}",
DATABASE_URL: "postgresql://${{PGUSER}}:${{POSTGRES_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:${{PGPORT}}/${{PGDATABASE}}",
PGDATA: "/var/lib/postgresql/data/pgdata", // for Volume Mounting in Railway
PGDATABASE: "${{POSTGRES_DB}}",
PGHOST: "${{RAILWAY_PRIVATE_DOMAIN}}",
PGPASSWORD: "${{POSTGRES_PASSWORD}}",
PGPORT: "5432",
PGUSER: "${{POSTGRES_USER}}",
// Docker variables
POSTGRES_DB: "postgres-db",
POSTGRES_PASSWORD: "postgres-password",
POSTGRES_USER: "postgres-user",
}
},
[DatabaseType.MYSQL]: {
source: 'mysql:latest',
defaultName: 'MySQL',
description: 'MySQL database service',
category: 'SQL Databases',
port: 3306,
variables: {
// Railway variables
MYSQLHOST: "${{RAILWAY_PRIVATE_DOMAIN}}",
MYSQLPASSWORD: "${{MYSQL_ROOT_PASSWORD}}",
MYSQLDATABASE: "${{MYSQL_DATABASE}}",
// Docker variables
MYSQL_DATABASE: "mysql-db",
MYSQL_PUBLIC_URL: "mysql://${{MYSQLUSER}}:${{MYSQL_ROOT_PASSWORD}}@${{RAILWAY_TCP_PROXY_DOMAIN}}:${{RAILWAY_TCP_PROXY_PORT}}/${{MYSQL_DATABASE}}",
MYSQL_URL: "mysql://${{MYSQLUSER}}:${{MYSQL_ROOT_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:${{MYSQLPORT}}/${{MYSQL_DATABASE}}",
MYSQL_ROOT_PASSWORD: "mysql-password",
MYSQLUSER: "root",
MYSQLPORT: "3306",
},
},
[DatabaseType.MONGODB]: {
source: 'mongo:7',
defaultName: 'MongoDB',
description: 'MongoDB NoSQL database service',
category: 'NoSQL Databases',
port: 27017,
variables: {
// Docker
MONGO_INITDB_ROOT_PASSWORD: "mongo-password",
MONGO_INITDB_ROOT_USERNAME: "mongo-user",
MONGO_PUBLIC_URL: "mongodb://${{MONGO_INITDB_ROOT_USERNAME}}:${{MONGO_INITDB_ROOT_PASSWORD}}@${{RAILWAY_TCP_PROXY_DOMAIN}}:${{RAILWAY_TCP_PROXY_PORT}}",
MONGO_URL: "mongodb://${{MONGO_INITDB_ROOT_USERNAME}}:${{MONGO_INITDB_ROOT_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:${{MONGO_PORT}}",
// Railway
MONGOHOST: "${{RAILWAY_PRIVATE_DOMAIN}}",
MONGOPASSWORD: "${{MONGO_INITDB_ROOT_PASSWORD}}",
MONGOPORT: "27017",
MONGOUSER: "${{MONGO_INITDB_ROOT_USERNAME}}",
},
},
[DatabaseType.REDIS]: {
source: 'bitnami/redis:7.2.5',
defaultName: 'Redis',
description: 'Redis in-memory data store',
category: 'In-Memory Stores',
port: 6379,
variables: {
// Docker
REDIS_PASSWORD: "redis-password",
REDIS_PORT: "6379",
REDISUSER: "default",
REDIS_RDB_POLICY: "3600#1 300#100 60#10000",
REDISPORT: "6379",
REDIS_AOF_ENABLED: "no",
// Railway
REDISPASSWORD: "${{REDIS_PASSWORD}}",
REDISHOST: "${{RAILWAY_PRIVATE_DOMAIN}}",
RAILWAY_RUN_UID: "0",
REDIS_PUBLIC_URL: "redis://${{REDISUSER}}:${{REDIS_PASSWORD}}@${{RAILWAY_TCP_PROXY_DOMAIN}}:${{RAILWAY_TCP_PROXY_PORT}}",
REDIS_URL: "redis://${{REDISUSER}}:${{REDIS_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:${{REDISPORT}}",
RAILWAY_RUN_AS_ROOT: "true",
},
},
[DatabaseType.MINIO]: {
source: 'minio:latest',
defaultName: 'MinIO',
description: 'MinIO object storage service',
category: 'Object Storage',
port: 9000,
},
[DatabaseType.SQLITE3]: {
source: 'sqlite:latest',
defaultName: 'SQLite',
description: 'SQLite relational database',
category: 'SQL Databases',
port: 5432,
},
[DatabaseType.POCKETBASE]: {
source: 'pocketbase/pocketbase:latest',
defaultName: 'PocketBase',
description: 'PocketBase lightweight, open-source, self-hosted backend',
category: 'SQL Databases',
port: 8080,
},
[DatabaseType.CLICKHOUSE]: {
source: 'clickhouse/clickhouse-server:23',
defaultName: 'ClickHouse',
description: 'ClickHouse column-oriented database',
category: 'Analytics Databases',
port: 8123,
},
[DatabaseType.MARIADB]: {
source: 'mariadb:10',
defaultName: 'MariaDB',
description: 'MariaDB relational database',
category: 'SQL Databases',
port: 3306,
},
[DatabaseType.PGVECTOR]: {
source: 'postgres:14',
defaultName: 'PGVector',
description: 'PGVector vector database',
category: 'Vector Databases',
port: 5432,
},
};
/**
* Input type for creating a service domain
*/
export interface ServiceDomainCreateInput {
/** ID of the environment */
environmentId: string;
/** ID of the service */
serviceId: string;
/** Custom domain name (optional) */
domain?: string;
/** Suffix for the domain (optional) */
suffix?: string;
/** Target port for the domain (optional) */
targetPort?: number;
}
/**
* Input type for updating a service domain
*/
export interface ServiceDomainUpdateInput {
/** ID of the domain to update */
id: string;
/** New target port for the domain */
targetPort: number;
}
/**
* Service domain model
*/
export interface ServiceDomain {
/** Unique identifier */
id: string;
/** Creation timestamp */
createdAt: string;
/** Deletion timestamp, null if not deleted */
deletedAt: string | null;
/** Full domain name */
domain: string;
/** ID of the environment */
environmentId: string;
/** ID of the project */
projectId: string;
/** ID of the service */
serviceId: string;
/** Suffix part of the domain (for service domains) */
suffix: string | null;
/** Target port the domain maps to */
targetPort: number | null;
/** Last update timestamp */
updatedAt: string;
}
/**
* Domain availability check result
*/
export interface DomainAvailabilityResult {
/** Whether the domain is available */
available: boolean;
/** Message explaining availability status */
message: string;
}
/**
* Result of listing domains for a service
*/
export interface DomainsListResult {
/** List of custom domains */
customDomains: ServiceDomain[];
/** List of service domains */
serviceDomains: ServiceDomain[];
}
/**
* TCP Proxy model
*/
export interface TcpProxy {
/** Unique identifier */
id: string;
/** Creation timestamp */
createdAt: string;
/** Deletion timestamp, null if not deleted */
deletedAt: string | null;
/** Domain for the TCP proxy */
domain: string;
/** ID of the environment */
environmentId: string;
/** ID of the service */
serviceId: string;
/** Container port that will be proxied */
applicationPort: number;
/** Proxy port that gets exposed */
proxyPort: number;
/** Last update timestamp */
updatedAt: string;
}
/**
* Input type for creating a TCP proxy
*/
export interface TcpProxyCreateInput {
/** ID of the environment */
environmentId: string;
/** ID of the service */
serviceId: string;
/** Container port that will be proxied */
applicationPort: number;
}
export interface Volume {
__typename?: string;
createdAt: string;
id: string;
name: string;
project: Project;
projectId: string;
volumeInstances: Connection<VolumeInstance[]>;
}
export interface VolumeCreateInput {
projectId: string; // Project to create volume in
serviceId: string; // Service to attach volume to
environmentId: string; // Environment to create volume in
mountPath: string; // Path to mount volume on
}
export interface VolumeUpdateInput {
name: string;
}
export interface VolumeInstance {
__typename?: string;
createdAt: string;
currentSizeMB?: number;
environmentId: string;
externalId?: string;
id: string;
mountPath?: string;
region?: string;
service: Service;
serviceId?: string;
sizeMB?: number;
state?: string;
type?: string;
volume: Volume;
volumeId: string;
}