1import * as Data from "effect/Data";
2import type * as Effect from "effect/Effect";
3import type * as Redacted from "effect/Redacted";
4import * as Binding from "../Binding.ts";
5import type { RuntimeContext } from "../RuntimeContext.ts";
6import type { Mongo } from "./Mongo.ts";
7
8/**
9 * Bind a {@link Mongo} service to a Railway {@link Service} and obtain
10 * the Effect-native connection string for the MongoDB driver.
11 *
12 * `ConnectMongo` is the Context tag, the type, and the callable —
13 * `yield* Railway.ConnectMongo(Db)`. Provide {@link ConnectMongoHttp}.
14 *
15 * **Example:** Bind Mongo in a Service
16 * ```typescript
17 * import * as Redacted from "effect/Redacted";
18 *
19 * const conn = yield* Railway.ConnectMongo(Db);
20 *
21 * fetch: Effect.gen(function* () {
22 * const url = yield* conn.connectionString;
23 * const ping = yield* Railway.pingMongo(Redacted.value(url));
24 * });
25 * ```
26 *
27 * ### Variable references
28 * `ConnectMongo` packs a typed private URI onto the Service. To store
29 * Railway's template instead of a resolved URI (IaC `db.env.MONGO_URL`),
30 * pass `Railway.ref(Db, "MONGO_URL")` as a {@link Variable} `value` or
31 * `Service.env` entry.
32 *
33 * **Example:** Railway.ref
34 * ```typescript
35 * const db = yield* Railway.mongo("Db", { project: site });
36 * yield* Railway.Variable("MongoUrl", {
37 * project: site,
38 * service: api,
39 * name: "MONGO_URL",
40 * value: Railway.ref(db, "MONGO_URL"),
41 * });
42 * ```
43 *
44 * @binding
45 * @product MongoDB
46 * @category Storage & Databases
47 */
48export interface ConnectMongo extends Binding.Service<
49 ConnectMongo,
50 "Railway.ConnectMongo",
51 (mongo: Mongo) => Effect.Effect<ConnectMongoClient>
52> {}
53
54export const ConnectMongo = Binding.Service<ConnectMongo>(
55 "Railway.ConnectMongo",
56);
57
58export const connectEnvKeys = (mongo: Pick<Mongo, "LogicalId">) => {
59 const id = mongo.LogicalId.replaceAll(/[^a-zA-Z0-9]/g, "_").toUpperCase();
60 return {
61 pooled: `RAILWAY_MONGO_${id}_POOLED`,
62 direct: `RAILWAY_MONGO_${id}_DIRECT`,
63 };
64};
65
66export class MongoUrlMissing extends Data.TaggedError(
67 "Railway.MongoUrlMissing",
68)<{
69 name: string;
70}> {}
71
72export interface ConnectMongoClient {
73 /**
74 * Private (`{name}.railway.internal`) connection string. Pass this to
75 * the MongoDB driver from a {@link Service}.
76 */
77 connectionString: Effect.Effect<
78 Redacted.Redacted<string>,
79 MongoUrlMissing,
80 RuntimeContext
81 >;
82 /**
83 * Same private URI. Kept so callers matching the Postgres
84 * `ConnectPostgres` shape keep working.
85 */
86 directConnectionString: Effect.Effect<
87 Redacted.Redacted<string>,
88 MongoUrlMissing,
89 RuntimeContext
90 >;
91}