1import type { ScriptProgressEvent, ScriptProgressStreamError, ThreadId } from "@t3tools/contracts";
2import * as Context from "effect/Context";
3import * as Effect from "effect/Effect";
4import * as Layer from "effect/Layer";
5import * as Stream from "effect/Stream";
6
7export class ScriptProgress extends Context.Service<
8 ScriptProgress,
9 {
10 readonly environmentForThread: (threadId: ThreadId) => Effect.Effect<Record<string, string>>;
11 readonly subscribe: (
12 threadId: ThreadId,
13 ) => Stream.Stream<ScriptProgressEvent, ScriptProgressStreamError>;
14 }
15>()("@t3tools/provider-core/server/ScriptProgress") {}
16
17export function withScriptProgressEnvironment(
18 environment: Record<string, string>,
19 progress: Readonly<Record<string, string>>,
20): Record<string, string>;
21export function withScriptProgressEnvironment(
22 environment: NodeJS.ProcessEnv,
23 progress: NodeJS.ProcessEnv,
24): NodeJS.ProcessEnv;
25export function withScriptProgressEnvironment(
26 environment: NodeJS.ProcessEnv,
27 progress: NodeJS.ProcessEnv,
28): NodeJS.ProcessEnv {
29 return {
30 ...environment,
31 ...progress,
32 ...(progress.NODE_OPTIONS
33 ? {
34 NODE_OPTIONS:
35 environment.NODE_OPTIONS === progress.NODE_OPTIONS ||
36 environment.NODE_OPTIONS?.startsWith(`${progress.NODE_OPTIONS} `)
37 ? environment.NODE_OPTIONS
38 : [progress.NODE_OPTIONS, environment.NODE_OPTIONS].filter(Boolean).join(" "),
39 }
40 : {}),
41 };
42}
43
44export const layerUnavailable = Layer.succeed(
45 ScriptProgress,
46 ScriptProgress.of({
47 environmentForThread: () => Effect.succeed({}),
48 subscribe: () => Stream.succeed({ type: "snapshot", streams: [] }),
49 }),
50);