| 1 | import * as Railway from "alchemy/Railway"; |
| 2 | import * as Redacted from "effect/Redacted"; |
| 3 | |
| 4 | export const VOLUME_PATH = "/data"; |
| 5 | export const MARKER_FILE = `${VOLUME_PATH}/hello.txt`; |
| 6 | export const MARKER = "hello-from-railway-worker"; |
| 7 | export const API_PORT = 3000; |
| 8 | export const SECRET_NAME = "RAILWAY_EXAMPLE_MARKER"; |
| 9 | export const OBJECT_KEY = "example.txt"; |
| 10 | export 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 | */ |
| 17 | export 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 | */ |
| 24 | export 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 | */ |
| 33 | export 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 | */ |
| 43 | export 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 | */ |
| 53 | export 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 | */ |
| 59 | export 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 | */ |
| 66 | export 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 | */ |
| 76 | export 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 | */ |
| 87 | export const Cache = Railway.Redis("Cache", { project: Site }); |
| 88 | |
| 89 | /** |
| 90 | * S3-compatible bucket. {@link Api} binds Put/Get/Head/List/Delete. |
| 91 | */ |
| 92 | export const Data = Railway.Bucket("Data", { project: Site }); |