1import * as connectivity from "@distilled.cloud/cloudflare/connectivity";
2import * as Effect from "effect/Effect";
3import * as Option from "effect/Option";
4import * as Stream from "effect/Stream";
5
6import * as Output from "../../Output.ts";
7import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
8import { formatVpcService, type Attributes } from "./VpcService.ts";
9
10export type VpcServiceLookupProps =
11 | {
12 /**
13 * The Cloudflare-assigned ID for the VPC service.
14 */
15 serviceId: string;
16 }
17 | {
18 /**
19 * The display name of the VPC service.
20 */
21 name: string;
22 };
23
24/**
25 * The resolved value of a {@link lookup} — the service's {@link Attributes}
26 * branded with the VpcService resource `Type`, so Worker binding
27 * classification treats it exactly like the managed resource.
28 */
29export interface VpcServiceLookup extends Attributes {
30 readonly Type: "Cloudflare.VpcService.VpcService";
31}
32
33const toLookup = (attrs: Attributes): VpcServiceLookup => ({
34 ...attrs,
35 Type: "Cloudflare.VpcService.VpcService",
36});
37
38/**
39 * Look up an existing Cloudflare VPC service (managed outside this stack)
40 * without managing its lifecycle — the data-source form (what Terraform
41 * calls a data source and Pulumi an invoke). Reads the service by
42 * `serviceId` or `name` and returns an `Output` of its {@link Attributes},
43 * resolved during plan/deploy and inert inside deployed bundles. Place it
44 * in a Worker's `env` to attach a `vpc_service` binding.
45 * **Example:** Look up by ID
46 * ```typescript
47 * const service = Cloudflare.VpcService.lookup({
48 * serviceId: "123e4567-e89b-12d3-a456-426614174000",
49 * });
50 * ```
51 *
52 * **Example:** Look up by name
53 * ```typescript
54 * const service = Cloudflare.VpcService.lookup({ name: "my-vpc-service" });
55 * ```
56 *
57 * **Example:** Bind to a Worker
58 * ```typescript
59 * const worker = yield* Cloudflare.Worker("Worker", {
60 * main: "./src/worker.ts",
61 * env: { VPC: Cloudflare.VpcService.lookup({ name: "my-vpc-service" }) },
62 * });
63 * ```
64 *
65 * @resource
66 * @product Workers VPC
67 * @category Network
68 */
69export const lookup = (props: VpcServiceLookupProps) =>
70 Output.fromEffect(
71 Effect.gen(function* () {
72 const { accountId } = yield* yield* CloudflareEnvironment;
73 if ("name" in props) {
74 const match = yield* connectivity.listDirectoryServices
75 .items({ accountId })
76 .pipe(
77 Stream.filter((s) => s.name === props.name),
78 Stream.runHead,
79 Effect.map(Option.getOrUndefined),
80 );
81 if (!match) {
82 return yield* Effect.die(`VPC service "${props.name}" not found`);
83 }
84 return toLookup(formatVpcService(match, accountId));
85 }
86 const result = yield* connectivity.getDirectoryService({
87 accountId,
88 serviceId: props.serviceId,
89 });
90 return toLookup(formatVpcService(result, accountId));
91 }).pipe(Effect.orDie),
92 );