| 1 | import * as Effect from "effect/Effect"; |
| 2 | import * as Result from "effect/Result"; |
| 3 | |
| 4 | /** |
| 5 | * Publishes every platform package at once, then the launcher, which must |
| 6 | * never be installable before the executables it points to. When one platform |
| 7 | * fails, the other uploads still finish rather than being interrupted: npm |
| 8 | * never accepts the same version twice, and an interrupted upload may already |
| 9 | * be live. The launcher is then skipped and the first failure is returned. |
| 10 | */ |
| 11 | export const publishPlatformsThenLauncher = <E, R>(input: { |
| 12 | readonly platformTarballs: ReadonlyArray<string>; |
| 13 | readonly launcherTarball: string; |
| 14 | readonly publish: (tarball: string) => Effect.Effect<void, E, R>; |
| 15 | }) => |
| 16 | Effect.gen(function* () { |
| 17 | const results = yield* Effect.all(input.platformTarballs.map(input.publish), { |
| 18 | concurrency: "unbounded", |
| 19 | mode: "result", |
| 20 | }); |
| 21 | const failed = results.find(Result.isFailure); |
| 22 | if (failed) { |
| 23 | return yield* Effect.fail(failed.failure); |
| 24 | } |
| 25 | yield* input.publish(input.launcherTarball); |
| 26 | }); |