| 1 | import * as Effect from "effect/Effect"; |
| 2 | import type { Input } from "../../Input.ts"; |
| 3 | import * as Output from "../../Output.ts"; |
| 4 | import { sha256 } from "../../Util/sha256.ts"; |
| 5 | |
| 6 | /** |
| 7 | * Lift a script-name input (a literal, an Output, or a Config/Effect-valued |
| 8 | * name) into an Output so it can feed plan-time derivations. |
| 9 | * |
| 10 | * @internal |
| 11 | */ |
| 12 | export const asScriptNameOutput = ( |
| 13 | scriptName: Input<string>, |
| 14 | ): Output.Output<string> => |
| 15 | Output.asOutput( |
| 16 | (Effect.isEffect(scriptName) |
| 17 | ? scriptName.pipe(Effect.orDie) |
| 18 | : scriptName) as string | Output.Output<string> | Effect.Effect<string>, |
| 19 | ); |
| 20 | |
| 21 | /** |
| 22 | * Derive an account-global Workflow name from a resolved host Worker name and |
| 23 | * exported class. |
| 24 | * |
| 25 | * @internal |
| 26 | */ |
| 27 | export const generateWorkflowName = Effect.fn(function* ( |
| 28 | scriptName: string, |
| 29 | className: string, |
| 30 | ) { |
| 31 | const base = `${scriptName}-${className}` |
| 32 | .toLowerCase() |
| 33 | .replaceAll(/[^a-z0-9-]/g, "-"); |
| 34 | const hash = yield* sha256(base); |
| 35 | const suffix = `-${hash.slice(0, 8)}`; |
| 36 | // Trim trailing dashes left by mid-name truncation so the result never |
| 37 | // contains a `--` seam. |
| 38 | const head = base.slice(0, 64 - suffix.length).replace(/-+$/, ""); |
| 39 | return `${head}${suffix}`; |
| 40 | }); |
| 41 | |
| 42 | /** |
| 43 | * Derive an account-global Workflow name when the host Worker name may still |
| 44 | * be an unresolved input. |
| 45 | * |
| 46 | * @internal |
| 47 | */ |
| 48 | export const makeWorkflowName = ( |
| 49 | scriptName: Input<string>, |
| 50 | className: string, |
| 51 | ): Output.Output<string> => |
| 52 | asScriptNameOutput(scriptName).pipe( |
| 53 | Output.mapEffect((scriptName) => |
| 54 | generateWorkflowName(scriptName, className), |
| 55 | ), |
| 56 | ); |