1import * as Railway from "alchemy/Railway";
2import * as Redacted from "effect/Redacted";
3
4export const VOLUME_PATH = "/data";
5export const MARKER_FILE = `${VOLUME_PATH}/hello.txt`;
6export const MARKER = "hello-from-railway-worker";
7export const API_PORT = 3000;
8export const SECRET_NAME = "RAILWAY_EXAMPLE_MARKER";
9export const OBJECT_KEY = "example.txt";
10export const REDIS_KEY = "example-marker";
11
12/**
13 * Parent Project every other resource shares. Name is generated.
14 * Production is `Site.environmentId` — do not recreate it as an
15 * Environment.
16 */
17export const Site = Railway.Project("Site");
18
19/**
20 * Extra staging environment. Production already exists on {@link Site}.
21 * Empty on create (no `sourceEnvironmentId`) so it does not clone
22 * Postgres / Redis / Services.
23 */
24export const Staging = Railway.Environment("Staging", {
25 project: Site,
26 name: "staging",
27});
28
29/**
30 * Shared project variable. {@link Api} pulls it into service env with
31 * `Railway.ref("shared", SECRET_NAME)` and reads it via `Config.String`.
32 */
33export const Marker = Railway.Variable("Marker", {
34 project: Site,
35 name: SECRET_NAME,
36 value: Redacted.make(MARKER),
37});
38
39/**
40 * Block disk {@link Worker} mounts at {@link VOLUME_PATH}. A Volume
41 * attaches to one Service.
42 */
43export const Disk = Railway.Volume("Disk", {
44 project: Site,
45 mountPath: VOLUME_PATH,
46});
47
48/**
49 * Official SSL Postgres. `public` (default) opens a TCP proxy for
50 * laptop access. In-Service connections use `{name}.railway.internal`
51 * via {@link Railway.ConnectPostgres}.
52 */
53export const Db = Railway.Postgres("Db", { project: Site });
54
55/**
56 * Official MySQL. Same shape as {@link Db}. In-Service connections
57 * use {@link Railway.ConnectMySQL}.
58 */
59export const Mysql = Railway.MySQL("Mysql", { project: Site });
60
61/**
62 * Railway variable-reference template (`${{Db.DATABASE_URL}}`). Stored
63 * unrendered; Railway interpolates it. Distinct from
64 * {@link Railway.ConnectPostgres}, which packs a typed URI.
65 */
66export const DatabaseUrl = Railway.Variable("DatabaseUrl", {
67 project: Site,
68 name: "APP_DATABASE_URL",
69 value: Railway.ref("Db", "DATABASE_URL"),
70});
71
72/**
73 * Canvas cron Function: inline TypeScript on the Bun function runtime.
74 * No HTTP domain. Distinct from the Effect-native Ping class.
75 */
76export const Cleanup = Railway.Function("Cleanup", {
77 project: Site,
78 source: `console.log("tick");`,
79 cronSchedule: "0 * * * *",
80});
81
82/**
83 * Redis. The stack attaches a {@link Railway.TcpProxy} so it's
84 * reachable on `*.proxy.rlwy.net`. {@link Api} binds
85 * {@link Railway.ReadWriteRedis}.
86 */
87export const Cache = Railway.Redis("Cache", { project: Site });
88
89/**
90 * S3-compatible bucket. {@link Api} binds Put/Get/Head/List/Delete.
91 */
92export const Data = Railway.Bucket("Data", { project: Site });