From 3726052307a869a64922ff10e71b16cc2206d64e Mon Sep 17 00:00:00 2001 From: James Long Date: Mon, 29 Jun 2026 16:50:59 -0400 Subject: [PATCH] refactor(opencode): use layer nodes in server tests (#34503) --- packages/opencode/test/fixture/workspace.ts | 32 +++++++++++-------- .../server/httpapi-instance-context.test.ts | 8 +---- .../httpapi-promptasync-context.test.ts | 8 +---- .../opencode/test/server/httpapi-sdk.test.ts | 22 ++++++------- .../test/server/httpapi-session.test.ts | 32 +++++++------------ .../opencode/test/server/httpapi-ui.test.ts | 25 ++++++++------- .../server/httpapi-workspace-routing.test.ts | 5 +-- .../test/server/httpapi-workspace.test.ts | 24 +++++++------- .../opencode/test/server/project-copy.test.ts | 5 +-- .../test/server/project-init-git.test.ts | 5 +-- .../opencode/test/server/session-list.test.ts | 21 ++++-------- 11 files changed, 83 insertions(+), 104 deletions(-) diff --git a/packages/opencode/test/fixture/workspace.ts b/packages/opencode/test/fixture/workspace.ts index 11fa48d5d5..cf75855715 100644 --- a/packages/opencode/test/fixture/workspace.ts +++ b/packages/opencode/test/fixture/workspace.ts @@ -1,5 +1,4 @@ -import { FetchHttpClient } from "effect/unstable/http" -import { Layer } from "effect" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { Database } from "@opencode-ai/core/database/database" import { FSUtil } from "@opencode-ai/core/fs-util" @@ -15,16 +14,21 @@ import { SessionPrompt } from "../../src/session/prompt" import { EventV2Bridge } from "../../src/event-v2-bridge" export const workspaceLayerWithRuntimeFlags = (overrides: Partial) => - Workspace.layer.pipe( - Layer.provide(Auth.defaultLayer), - Layer.provide(Session.defaultLayer), - Layer.provide(SessionPrompt.defaultLayer), - Layer.provide(Project.defaultLayer), - Layer.provide(Vcs.defaultLayer), - Layer.provide(Database.defaultLayer), - Layer.provide(EventV2Bridge.defaultLayer), - Layer.provide(FetchHttpClient.layer), - Layer.provide(FSUtil.defaultLayer), - Layer.provide(RuntimeFlags.layer(overrides)), - Layer.provide(LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]])), + AppNodeBuilder.build( + LayerNode.group([ + Workspace.node, + Auth.node, + Session.node, + SessionPrompt.node, + Project.node, + Vcs.node, + Database.node, + EventV2Bridge.node, + FSUtil.node, + InstanceStore.node, + ]), + [ + [InstanceStore.bootstrapNode, InstanceBootstrap.node], + [RuntimeFlags.node, RuntimeFlags.layer(overrides)], + ], ) diff --git a/packages/opencode/test/server/httpapi-instance-context.test.ts b/packages/opencode/test/server/httpapi-instance-context.test.ts index 07c722ff43..6a758cc41c 100644 --- a/packages/opencode/test/server/httpapi-instance-context.test.ts +++ b/packages/opencode/test/server/httpapi-instance-context.test.ts @@ -1,7 +1,6 @@ import { NodeHttpServer, NodeServices } from "@effect/platform-node" import { describe, expect } from "bun:test" import { Effect, Fiber, Layer, Schema } from "effect" -import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { HttpClient, HttpClientRequest, HttpRouter } from "effect/unstable/http" import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi" import * as Socket from "effect/unstable/socket/Socket" @@ -9,12 +8,9 @@ import { mkdir } from "node:fs/promises" import path from "node:path" import { registerAdapter } from "../../src/control-plane/adapters" import { WorkspaceV2 } from "@opencode-ai/core/workspace" -import { Ripgrep } from "@opencode-ai/core/ripgrep" import type { WorkspaceAdapter } from "../../src/control-plane/types" import { Workspace } from "../../src/control-plane/workspace" import { InstanceRef, WorkspaceRef } from "../../src/effect/instance-ref" -import { InstanceBootstrap } from "../../src/project/bootstrap" -import { InstanceStore } from "../../src/project/instance-store" import { Project } from "../../src/project/project" import { Session } from "../../src/session/session" import { disposeMiddleware, markInstanceForDisposal } from "../../src/server/routes/instance/httpapi/lifecycle" @@ -53,10 +49,8 @@ const it = testEffect( testStateLayer, NodeHttpServer.layerTest, NodeServices.layer, - LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]]), - Project.defaultLayer, workspaceLayer, - ).pipe(Layer.provide(Ripgrep.defaultLayer)), + ), ) const instanceContextTestLayer = Layer.mergeAll( diff --git a/packages/opencode/test/server/httpapi-promptasync-context.test.ts b/packages/opencode/test/server/httpapi-promptasync-context.test.ts index 8775cd1f70..c56ebcf3c1 100644 --- a/packages/opencode/test/server/httpapi-promptasync-context.test.ts +++ b/packages/opencode/test/server/httpapi-promptasync-context.test.ts @@ -10,19 +10,15 @@ import { NodeHttpServer, NodeServices } from "@effect/platform-node" import { describe, expect } from "bun:test" import { Deferred, Effect, Layer, Schema, Scope } from "effect" -import { LayerNode } from "@opencode-ai/core/effect/layer-node" import * as Stream from "effect/Stream" import { HttpClient, HttpRouter, HttpServerResponse } from "effect/unstable/http" import * as Socket from "effect/unstable/socket/Socket" import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi" import { mkdir } from "node:fs/promises" import { registerAdapter } from "../../src/control-plane/adapters" -import { Ripgrep } from "@opencode-ai/core/ripgrep" import type { WorkspaceAdapter } from "../../src/control-plane/types" import { Workspace } from "../../src/control-plane/workspace" import { InstanceRef, WorkspaceRef } from "../../src/effect/instance-ref" -import { InstanceBootstrap } from "../../src/project/bootstrap" -import { InstanceStore } from "../../src/project/instance-store" import { Project } from "../../src/project/project" import { Session } from "../../src/session/session" import { @@ -58,10 +54,8 @@ const it = testEffect( testStateLayer, NodeHttpServer.layerTest, NodeServices.layer, - LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]]), - Project.defaultLayer, workspaceLayer, - ).pipe(Layer.provide(Ripgrep.defaultLayer)), + ), ) const instanceContextTestLayer = Layer.mergeAll( diff --git a/packages/opencode/test/server/httpapi-sdk.test.ts b/packages/opencode/test/server/httpapi-sdk.test.ts index 79fdd41e6d..8fcd348b5b 100644 --- a/packages/opencode/test/server/httpapi-sdk.test.ts +++ b/packages/opencode/test/server/httpapi-sdk.test.ts @@ -5,13 +5,14 @@ import { Deferred, Effect, Layer } from "effect" import type * as Scope from "effect/Scope" import { HttpServer } from "effect/unstable/http" import { ChildProcessSpawner } from "effect/unstable/process" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" +import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { FSUtil } from "@opencode-ai/core/fs-util" import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner" -import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { Flag } from "@opencode-ai/core/flag/flag" import { createOpencodeClient } from "@opencode-ai/sdk/v2" import { validateSession } from "../../src/cli/tui/validate-session" -import { InstanceBootstrap } from "../../src/project/bootstrap-service" +import { InstanceBootstrap } from "../../src/project/bootstrap" import { InstanceStore } from "../../src/project/instance-store" import { MessageID, PartID, SessionID } from "../../src/session/schema" import { MessageV2 } from "../../src/session/message-v2" @@ -30,15 +31,13 @@ import { ModelV2 } from "@opencode-ai/core/model" import { Database } from "@opencode-ai/core/database/database" import { httpApiLayer } from "./httpapi-layer" -const noopBootstrap = Layer.succeed(InstanceBootstrap.Service, InstanceBootstrap.Service.of({ run: Effect.void })) +const noopBootstrapLayer = Layer.succeed(InstanceBootstrap.Service, InstanceBootstrap.Service.of({ run: Effect.void })) +const appLayer = AppNodeBuilder.build( + LayerNode.group([FSUtil.node, CrossSpawnSpawner.node, InstanceStore.node, Database.node, SessionNs.node]), + [[InstanceStore.bootstrapNode, noopBootstrapLayer]], +) const it = testEffect( - Layer.mergeAll( - FSUtil.defaultLayer, - CrossSpawnSpawner.defaultLayer, - LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, noopBootstrap]]), - Database.defaultLayer, - httpApiLayer, - ), + Layer.mergeAll(appLayer, httpApiLayer), ) const original = { @@ -56,6 +55,7 @@ type TestServices = | FSUtil.Service | ChildProcessSpawner.ChildProcessSpawner | InstanceStore.Service + | SessionNs.Service | HttpServer.HttpServer type TestScope = Scope.Scope | TestServices @@ -324,7 +324,7 @@ function seedMessage(directory: string, sessionID: string) { }) return { message, part } }), - ).pipe(Effect.provide(SessionNs.defaultLayer)), + ), ), ) } diff --git a/packages/opencode/test/server/httpapi-session.test.ts b/packages/opencode/test/server/httpapi-session.test.ts index 6515872fd8..ae7f4e7ee8 100644 --- a/packages/opencode/test/server/httpapi-session.test.ts +++ b/packages/opencode/test/server/httpapi-session.test.ts @@ -7,15 +7,15 @@ import path from "node:path" import { Cause, Config, Effect, Exit, Layer } from "effect" import { HttpClient, HttpClientRequest, HttpClientResponse, HttpRouter, HttpServer } from "effect/unstable/http" import { layerWebSocketConstructorGlobal } from "effect/unstable/socket/Socket" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" +import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner" import { Flag } from "@opencode-ai/core/flag/flag" -import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { Ripgrep } from "@opencode-ai/core/ripgrep" import { registerAdapter } from "../../src/control-plane/adapters" import type { WorkspaceAdapter } from "../../src/control-plane/types" import { Workspace } from "../../src/control-plane/workspace" -import { InstanceBootstrap } from "../../src/project/bootstrap" import { InstanceBootstrap as InstanceBootstrapService } from "../../src/project/bootstrap-service" import { InstanceStore } from "../../src/project/instance-store" import { Project } from "../../src/project/project" @@ -38,15 +38,14 @@ import { testProviderConfig } from "../lib/test-provider" import { pollWithTimeout, testEffect } from "../lib/effect" const originalWorkspaces = Flag.OPENCODE_EXPERIMENTAL_WORKSPACES -const workspaceLayer = Workspace.defaultLayer.pipe( - Layer.provide(LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]])), +const noopBootstrapLayer = Layer.succeed( + InstanceBootstrapService.Service, + InstanceBootstrapService.Service.of({ run: Effect.void }), +) +const appLayer = AppNodeBuilder.build( + LayerNode.group([InstanceStore.node, Project.node, Session.node, Workspace.node, Database.node, Ripgrep.node]), + [[InstanceStore.bootstrapNode, noopBootstrapLayer]], ) -const instanceStoreLayer = LayerNode.compile(InstanceStore.node, [ - [ - InstanceStore.bootstrapNode, - Layer.succeed(InstanceBootstrapService.Service, InstanceBootstrapService.Service.of({ run: Effect.void })), - ], -]) const servedRoutes: Layer.Layer = HttpRouter.serve( HttpApiApp.routes, { @@ -60,14 +59,7 @@ const httpApiLayer = servedRoutes.pipe( Layer.provideMerge(NodeServices.layer), ) const it = testEffect( - Layer.mergeAll( - instanceStoreLayer, - Project.defaultLayer, - Session.defaultLayer, - workspaceLayer, - Database.defaultLayer, - httpApiLayer, - ).pipe(Layer.provide(Ripgrep.defaultLayer)), + Layer.mergeAll(appLayer, httpApiLayer), ) function pathFor(path: string, params: Record) { @@ -433,7 +425,7 @@ describe("session HttpApi", () => { cwd: sessionDirectory, root: sessionDirectory, }) - }).pipe(Effect.provide(TestLLMServer.layer), Effect.provide(CrossSpawnSpawner.defaultLayer)), + }).pipe(Effect.provide(TestLLMServer.layer), Effect.provide(AppNodeBuilder.build(CrossSpawnSpawner.node))), ) it.instance( @@ -869,7 +861,7 @@ describe("session HttpApi", () => { pathSession: yield* createSession(), pathlessSession: yield* createSession(), } - }).pipe(Effect.provideService(TestInstance, { directory: currentDir }), Effect.provide(Session.defaultLayer)), + }).pipe(Effect.provideService(TestInstance, { directory: currentDir })), ) yield* clearSessionPath(pathlessSession.id) diff --git a/packages/opencode/test/server/httpapi-ui.test.ts b/packages/opencode/test/server/httpapi-ui.test.ts index 43d1d30a94..e90220817d 100644 --- a/packages/opencode/test/server/httpapi-ui.test.ts +++ b/packages/opencode/test/server/httpapi-ui.test.ts @@ -1,7 +1,8 @@ import { createHash } from "node:crypto" import { describe, expect } from "bun:test" import { Flag } from "@opencode-ai/core/flag/flag" -import { ConfigProvider, Effect, Layer } from "effect" +import { ConfigProvider, Effect, Layer, Option } from "effect" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { HttpClient, HttpClientRequest, @@ -39,7 +40,15 @@ const testStateLayer = Layer.effectDiscard( }), ) -const it = testEffect(Layer.mergeAll(testStateLayer, FSUtil.defaultLayer, RuntimeFlags.layer())) +const fsUtilLayer = AppNodeBuilder.build(FSUtil.node) +const it = testEffect(Layer.mergeAll(testStateLayer, fsUtilLayer, RuntimeFlags.layer())) + +function authConfigLayer(input?: { password?: string; username?: string }) { + return ServerAuth.Config.layer({ + password: input?.password === undefined ? Option.none() : Option.some(input.password), + username: input?.username ?? "opencode", + }) +} function restoreEnv(key: string, value: string | undefined) { if (value === undefined) { @@ -94,18 +103,12 @@ function uiApp(input?: { ) }), ).pipe( - Layer.provide(authorizationRouterMiddleware.layer.pipe(Layer.provide(ServerAuth.Config.defaultLayer))), + Layer.provide(authorizationRouterMiddleware.layer.pipe(Layer.provide(authConfigLayer(input)))), Layer.provide([ - FSUtil.defaultLayer, + fsUtilLayer, input?.client ?? httpClient(new Response("ui")), RuntimeFlags.layer({ disableEmbeddedWebUi: input?.disableEmbeddedWebUi ?? false }), HttpServer.layerServices, - ConfigProvider.layer( - ConfigProvider.fromUnknown({ - OPENCODE_SERVER_PASSWORD: input?.password, - OPENCODE_SERVER_USERNAME: input?.username, - }), - ), ]), ), { disableLogger: true }, @@ -141,7 +144,7 @@ function routeOrderingApp() { }), ).pipe( Layer.provide([ - FSUtil.defaultLayer, + fsUtilLayer, RuntimeFlags.layer({ disableEmbeddedWebUi: true }), httpClient(new Response("ui"), (request) => { proxiedUrl = request.url diff --git a/packages/opencode/test/server/httpapi-workspace-routing.test.ts b/packages/opencode/test/server/httpapi-workspace-routing.test.ts index 6b24744767..2f6195a87e 100644 --- a/packages/opencode/test/server/httpapi-workspace-routing.test.ts +++ b/packages/opencode/test/server/httpapi-workspace-routing.test.ts @@ -21,7 +21,6 @@ import type { WorkspaceAdapter } from "../../src/control-plane/types" import { Workspace } from "../../src/control-plane/workspace" import { WorkspaceTable } from "@opencode-ai/core/control-plane/workspace.sql" import { Database } from "@opencode-ai/core/database/database" -import { Ripgrep } from "@opencode-ai/core/ripgrep" import { Project } from "../../src/project/project" import { Session } from "../../src/session/session" import { WorkspacePaths } from "../../src/server/routes/instance/httpapi/groups/workspace" @@ -55,11 +54,9 @@ const it = testEffect( testStateLayer, NodeHttpServer.layerTest, NodeServices.layer, - Database.defaultLayer, - Project.defaultLayer, workspaceLayer, Socket.layerWebSocketConstructorGlobal, - ).pipe(Layer.provide(Ripgrep.defaultLayer)), + ), ) type ProxiedRequest = { diff --git a/packages/opencode/test/server/httpapi-workspace.test.ts b/packages/opencode/test/server/httpapi-workspace.test.ts index 4a19f6b75d..33f3920c2d 100644 --- a/packages/opencode/test/server/httpapi-workspace.test.ts +++ b/packages/opencode/test/server/httpapi-workspace.test.ts @@ -2,8 +2,9 @@ import { afterEach, describe, expect, mock } from "bun:test" import { mkdir } from "node:fs/promises" import path from "node:path" import { Effect, Layer, Stream } from "effect" -import { Flag } from "@opencode-ai/core/flag/flag" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" +import { Flag } from "@opencode-ai/core/flag/flag" import { registerAdapter } from "../../src/control-plane/adapters" import { WorkspaceV2 } from "@opencode-ai/core/workspace" import type { WorkspaceAdapter } from "../../src/control-plane/types" @@ -24,18 +25,19 @@ import { testEffect } from "../lib/effect" import { httpApiLayer, requestInDirectory } from "./httpapi-layer" const originalWorkspaces = Flag.OPENCODE_EXPERIMENTAL_WORKSPACES -const workspaceLayer = Workspace.defaultLayer.pipe( - Layer.provide(LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]])), +const appLayer = AppNodeBuilder.build( + LayerNode.group([ + Project.node, + Session.node, + Workspace.node, + InstanceStore.node, + Database.node, + Ripgrep.node, + ]), + [[InstanceStore.bootstrapNode, InstanceBootstrap.node]], ) const it = testEffect( - Layer.mergeAll( - Project.defaultLayer, - Session.defaultLayer, - workspaceLayer, - LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]]), - Database.defaultLayer, - httpApiLayer, - ).pipe(Layer.provide(Ripgrep.defaultLayer)), + Layer.mergeAll(appLayer, httpApiLayer), ) function request(path: string, directory: string, init: RequestInit = {}) { diff --git a/packages/opencode/test/server/project-copy.test.ts b/packages/opencode/test/server/project-copy.test.ts index 83f5173ed2..0f783622a6 100644 --- a/packages/opencode/test/server/project-copy.test.ts +++ b/packages/opencode/test/server/project-copy.test.ts @@ -2,6 +2,7 @@ import { afterEach, describe, expect } from "bun:test" import { $ } from "bun" import fs from "fs/promises" import path from "path" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { Effect, Layer } from "effect" import { HttpClientResponse } from "effect/unstable/http" @@ -21,10 +22,10 @@ afterEach(async () => { }) const noopBootstrap = Layer.succeed(InstanceBootstrap.Service, InstanceBootstrap.Service.of({ run: Effect.void })) -const testInstanceStore = LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, noopBootstrap]]) +const testInstanceStore = AppNodeBuilder.build(InstanceStore.node, [[InstanceStore.bootstrapNode, noopBootstrap]]) const it = testEffect( Layer.mergeAll( - LayerNode.compile(LayerNode.group([FSUtil.node, Database.node, Snapshot.node])), + AppNodeBuilder.build(LayerNode.group([FSUtil.node, Database.node, Snapshot.node])), testInstanceStore, httpApiLayer, ), diff --git a/packages/opencode/test/server/project-init-git.test.ts b/packages/opencode/test/server/project-init-git.test.ts index f469d8bb04..4474bea7d4 100644 --- a/packages/opencode/test/server/project-init-git.test.ts +++ b/packages/opencode/test/server/project-init-git.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect } from "bun:test" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { FSUtil } from "@opencode-ai/core/fs-util" import { Effect, Layer } from "effect" @@ -20,10 +21,10 @@ afterEach(async () => { }) const noopBootstrap = Layer.succeed(InstanceBootstrap.Service, InstanceBootstrap.Service.of({ run: Effect.void })) -const testInstanceStore = LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, noopBootstrap]]) +const testInstanceStore = AppNodeBuilder.build(InstanceStore.node, [[InstanceStore.bootstrapNode, noopBootstrap]]) const it = testEffect( - Layer.mergeAll(LayerNode.compile(LayerNode.group([FSUtil.node, Snapshot.node])), testInstanceStore, httpApiLayer), + Layer.mergeAll(AppNodeBuilder.build(LayerNode.group([FSUtil.node, Snapshot.node])), testInstanceStore, httpApiLayer), ) function request(directory: string, url: string, init: RequestInit = {}) { diff --git a/packages/opencode/test/server/session-list.test.ts b/packages/opencode/test/server/session-list.test.ts index 213e3cdce3..3d0e0ab12f 100644 --- a/packages/opencode/test/server/session-list.test.ts +++ b/packages/opencode/test/server/session-list.test.ts @@ -1,5 +1,7 @@ import { afterEach, describe, expect } from "bun:test" -import { Effect, Layer } from "effect" +import { Effect } from "effect" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" +import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { Database } from "@opencode-ai/core/database/database" import { SessionProjector } from "@opencode-ai/core/session/projector" import { Session as SessionNs } from "@/session/session" @@ -9,23 +11,12 @@ import path from "path" import { SessionTable } from "@opencode-ai/core/session/sql" import { eq } from "drizzle-orm" import { testEffect } from "../lib/effect" -import { EventV2Bridge } from "@/event-v2-bridge" -import { Storage } from "@/storage/storage" import { RuntimeFlags } from "@/effect/runtime-flags" -import { BackgroundJob } from "@/background/job" const layer = (experimentalWorkspaces: boolean) => - Layer.mergeAll( - Database.defaultLayer, - SessionNs.layer.pipe( - Layer.provide(EventV2Bridge.defaultLayer), - Layer.provide(Storage.defaultLayer), - Layer.provide(Database.defaultLayer), - Layer.provide(EventV2Bridge.defaultLayer), - Layer.provide(SessionProjector.defaultLayer), - Layer.provide(RuntimeFlags.layer({ experimentalWorkspaces })), - Layer.provide(BackgroundJob.defaultLayer), - ), + AppNodeBuilder.build( + LayerNode.group([Database.node, SessionNs.node, SessionProjector.node]), + [[RuntimeFlags.node, RuntimeFlags.layer({ experimentalWorkspaces })]], ) const it = testEffect(layer(false)) const itWorkspaces = testEffect(layer(true))