1import { Query, type UnwrapPlan } from "@distilled.cloud/core/query";
2import { Railway, type Region } from "@distilled.cloud/railway";
3import * as Data from "effect/Data";
4import * as Effect from "effect/Effect";
5import { resolveWorkspace } from "./Environment.ts";
6
7const regionFields = <E>(region: Query<Region, E>) => ({
8 id: region.id,
9 name: region.name,
10 region: region.region,
11});
12type RegionsResultItem = UnwrapPlan<ReturnType<typeof regionFields>>;
13
14const readRegions = Query.fn((projectId?: string) =>
15 Railway.regions(projectId === undefined ? {} : { projectId }).pipe(
16 Query.map(regionFields),
17 ),
18);
19
20export type CatalogKind = "region" | "workspace";
21
22export class CatalogNotFound extends Data.TaggedError(
23 "Railway.CatalogNotFound",
24)<{
25 kind: CatalogKind;
26 ref: string;
27}> {}
28
29const notFound = (kind: CatalogKind, ref: string) =>
30 new CatalogNotFound({ kind, ref });
31
32/**
33 * Current token workspace (`me.workspace ?? me.workspaces[0]`).
34 * Feeds `projectCreate({ input: { workspaceId } })`. Not a resource.
35 */
36export const currentWorkspace = resolveWorkspace;
37
38/**
39 * List Railway regions via `regions`. Pass `projectId` to scope the
40 * catalog to a project; omit it for the workspace default set.
41 */
42export const listRegions = Effect.fn(function* (projectId?: string) {
43 const regions = yield* readRegions(projectId);
44 return regions ?? [];
45});
46
47/**
48 * Resolve a Railway region by code (`us-west2`, `us-east4`, …), display
49 * name, or id.
50 */
51export const findRegion = (ref: string) =>
52 Effect.gen(function* () {
53 const regions = yield* listRegions();
54 const found = regions.find(
55 (item) => item.region === ref || item.name === ref || item.id === ref,
56 );
57 if (found === undefined) {
58 return yield* notFound("region", ref);
59 }
60 return found;
61 });
62
63export type RailwayRegion = RegionsResultItem;
64
65/**
66 * Workspace audit logs. Query-only — Railway has no audit-log
67 * create/update/delete, so this is not a resource.
68 */
69export {
70 AuditLog,
71 getAuditLog,
72 listAuditLogEventTypes,
73 listAuditLogs,
74 type AuditLogEntry,
75 type AuditLogEnvironment,
76 type AuditLogEventType,
77 type AuditLogProject,
78 type ListAuditLogsOptions,
79} from "./AuditLog.ts";