| 1 | // Test fixture: boots an RpcSpawner, POSTs once with the child entry given by |
| 2 | // the first CLI arg, and prints `PARENT_PID=<n>` and `CHILD_PID=<n>` lines to |
| 3 | // stdout so the test harness can observe them. Then idles until killed. |
| 4 | // Relative imports (not `@/` alias) so this file runs under both Bun and |
| 5 | // Node without a paths-aware loader. This fixture is excluded from the test |
| 6 | // project's typecheck (see tsconfig.test.json) because the relative path |
| 7 | // crosses composite-project boundaries. |
| 8 | import * as Deferred from "effect/Deferred"; |
| 9 | import * as Effect from "effect/Effect"; |
| 10 | import * as Layer from "effect/Layer"; |
| 11 | import * as FetchHttpClient from "effect/http/FetchHttpClient"; |
| 12 | import * as HttpBody from "effect/http/HttpBody"; |
| 13 | import * as HttpClient from "effect/http/HttpClient"; |
| 14 | import { layerServer, RpcSpawner } from "../../../src/Local/RpcSpawner.ts"; |
| 15 | import { PlatformServices } from "../../../src/Util/PlatformServices.ts"; |
| 16 | |
| 17 | const childEntry = process.argv[2]; |
| 18 | if (!childEntry) { |
| 19 | console.error("usage: rpc-spawner-parent.ts <child-entry-url>"); |
| 20 | process.exit(2); |
| 21 | } |
| 22 | |
| 23 | const program = Effect.gen(function* () { |
| 24 | const sp = yield* RpcSpawner; |
| 25 | const http = yield* HttpClient.HttpClient; |
| 26 | const res = yield* http |
| 27 | .post(sp.url, { |
| 28 | body: yield* HttpBody.json({ |
| 29 | serverEntryUrl: childEntry, |
| 30 | alchemyContext: { |
| 31 | dotAlchemy: "/tmp/.alchemy", |
| 32 | updateStateStore: false, |
| 33 | dev: true, |
| 34 | adopt: false, |
| 35 | }, |
| 36 | stack: { name: "test", stage: "dev" }, |
| 37 | }), |
| 38 | }) |
| 39 | .pipe(Effect.flatMap((res) => res.text)); |
| 40 | |
| 41 | // The child's pid is whatever owns the listening port returned in res. |
| 42 | // We surface it for the test harness via stdout. |
| 43 | console.log(`PARENT_PID=${process.pid}\n`); |
| 44 | console.log(`CHILD_URL=${res}\n`); |
| 45 | |
| 46 | const stop = yield* Deferred.make<void>(); |
| 47 | yield* Deferred.await(stop); |
| 48 | }); |
| 49 | |
| 50 | program |
| 51 | .pipe( |
| 52 | Effect.provide([ |
| 53 | Layer.provide( |
| 54 | layerServer({ profile: undefined, envFile: undefined }), |
| 55 | PlatformServices, |
| 56 | ), |
| 57 | FetchHttpClient.layer, |
| 58 | ]), |
| 59 | Effect.scoped, |
| 60 | Effect.runPromise, |
| 61 | ) |
| 62 | .catch((e) => { |
| 63 | console.error(e); |
| 64 | process.exit(1); |
| 65 | }); |