diff --git a/.changeset/rename-client-react.md b/.changeset/rename-client-react.md new file mode 100644 index 0000000..c1ba7db --- /dev/null +++ b/.changeset/rename-client-react.md @@ -0,0 +1,9 @@ +--- +"stack-effect": patch +--- + +rename `client` target kind to `client-react` and prefix client module IDs with `react` + +- `http-api-client` becomes `http-api-react-client` +- `http-rpc-client` becomes `http-rpc-react-client` +- `ws-presence-client` becomes `ws-presence-react-client` diff --git a/AGENTS.md b/AGENTS.md index 059e279..8f62333 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -44,7 +44,7 @@ bun run start -- init smoke-app --yes --root "$TMP_REPO" bun run start -- add --yes --root "$TMP_REPO" --target package/domain --modules domain-api --dry-run # 3) Optional negative test: cross-target implication should fail in non-interactive mode -bun run start -- add --yes --root "$TMP_REPO" --target client/web --modules http-api-client --dry-run +bun run start -- add --yes --root "$TMP_REPO" --target client-react/web --modules http-api-react-client --dry-run ``` Notes: diff --git a/apps/cli/e2e/add.test.ts b/apps/cli/e2e/add.test.ts index 15df467..64e3610 100644 --- a/apps/cli/e2e/add.test.ts +++ b/apps/cli/e2e/add.test.ts @@ -57,9 +57,9 @@ describe("add", () => { "--root", root, "--target", - "client/web", + "client-react/web", "--modules", - "http-api-client", + "http-api-react-client", ); yield* cli.expectExitCode(1); yield* cli.expectOutputContaining("implies"); @@ -140,9 +140,9 @@ describe("add", () => { "--root", root, "--target", - "client/web", + "client-react/web", "--modules", - "http-api-client", + "http-api-react-client", "--dry-run", ); yield* cli.expectExitCode(0); diff --git a/apps/cli/e2e/matrix.test.ts b/apps/cli/e2e/matrix.test.ts index c4729e0..c0b909d 100644 --- a/apps/cli/e2e/matrix.test.ts +++ b/apps/cli/e2e/matrix.test.ts @@ -25,7 +25,7 @@ interface MatrixEntry { */ const defaultTargetNames = new Map([ ["server", "api"], - ["client", "web"], + ["client-react", "web"], ["cli", "app"], ["package", "domain"], // fallback; overridden by identity modules ]); @@ -105,7 +105,7 @@ const matrix = Effect.runSync( // Separate entries that have cross-target implications (client modules) const singleTargetEntries = matrix.filter( - (e) => !e.target.startsWith("client"), + (e) => !e.target.startsWith("client-react"), ); // --------------------------------------------------------------------------- @@ -116,7 +116,7 @@ const buildFullStackMatrix = Effect.gen(function* () { const catalog = yield* CatalogService; const clientModules = yield* catalog.getSupportedModules( - TargetKind.make("client"), + TargetKind.make("client-react"), ); return Arr.map(clientModules, (clientMod) => { @@ -132,7 +132,7 @@ const buildFullStackMatrix = Effect.gen(function* () { label: `full-stack: ${clientMod.id} → server [${serverModuleIds.join(", ")}]`, serverTarget: `server/${defaultTargetNames.get("server")}`, serverModules: serverModuleIds, - clientTarget: `client/${defaultTargetNames.get("client")}`, + clientTarget: `client-react/${defaultTargetNames.get("client-react")}`, clientModules: [clientMod.id], }; } @@ -279,7 +279,7 @@ describe("matrix", () => { "--root", root, "--target", - `client/${defaultTargetNames.get("client")}`, + `client-react/${defaultTargetNames.get("client-react")}`, "--modules", allClientModules.join(","), ); diff --git a/apps/cli/src/commands/add.ts b/apps/cli/src/commands/add.ts index 5f5499b..94a565b 100644 --- a/apps/cli/src/commands/add.ts +++ b/apps/cli/src/commands/add.ts @@ -26,7 +26,7 @@ interface CollectedTarget { const targetFlag = Flag.string("target").pipe( Flag.optional, Flag.withDescription( - "Target identity as /, e.g. client/web", + "Target identity as /, e.g. client-react/web", ), ); diff --git a/packages/catalog/src/registry/modules/client.ts b/packages/catalog/src/registry/modules/client.ts index 6a106f3..5aeae5c 100644 --- a/packages/catalog/src/registry/modules/client.ts +++ b/packages/catalog/src/registry/modules/client.ts @@ -28,10 +28,10 @@ import { */ export const clientModules: ReadonlyArray = [ { - id: ModuleId.make("http-api-client"), + id: ModuleId.make("http-api-react-client"), title: "HTTP API Client", description: "REST API client with Effect Atom and typed HttpApiClient", - supportedOn: [{ _tag: "kind", kind: TargetKind.make("client") }], + supportedOn: [{ _tag: "kind", kind: TargetKind.make("client-react") }], dependencies: [ { _tag: "required-module", @@ -89,10 +89,10 @@ export const clientModules: ReadonlyArray = [ ], }, { - id: ModuleId.make("http-rpc-client"), + id: ModuleId.make("http-rpc-react-client"), title: "HTTP RPC Client", description: "RPC streaming client with tick atom and UI", - supportedOn: [{ _tag: "kind", kind: TargetKind.make("client") }], + supportedOn: [{ _tag: "kind", kind: TargetKind.make("client-react") }], dependencies: [ { _tag: "required-module", @@ -155,10 +155,10 @@ export const clientModules: ReadonlyArray = [ ], }, { - id: ModuleId.make("chat-client"), + id: ModuleId.make("chat-react-client"), title: "Chat Client", description: "AI chat UI with streaming, tool calls, and state machine", - supportedOn: [{ _tag: "kind", kind: TargetKind.make("client") }], + supportedOn: [{ _tag: "kind", kind: TargetKind.make("client-react") }], dependencies: [ { _tag: "required-module", @@ -225,10 +225,10 @@ export const clientModules: ReadonlyArray = [ ], }, { - id: ModuleId.make("ws-presence-client"), + id: ModuleId.make("ws-presence-react-client"), title: "WebSocket Presence Client", description: "Real-time presence UI with WebSocket RPC", - supportedOn: [{ _tag: "kind", kind: TargetKind.make("client") }], + supportedOn: [{ _tag: "kind", kind: TargetKind.make("client-react") }], dependencies: [ { _tag: "required-module", diff --git a/packages/catalog/src/registry/modules/config.ts b/packages/catalog/src/registry/modules/config.ts index 035f9f8..1567d9f 100644 --- a/packages/catalog/src/registry/modules/config.ts +++ b/packages/catalog/src/registry/modules/config.ts @@ -10,11 +10,11 @@ import { configTypescriptViteContents } from "../content/client"; */ export const configModules: ReadonlyArray = [ { - id: ModuleId.make("config-typescript-vite"), + id: ModuleId.make("config-typescript-react-vite"), title: "Config TypeScript Vite", description: "Vite TypeScript preset for client applications", visibility: "internal", - supportedOn: [{ _tag: "kind", kind: TargetKind.make("client") }], + supportedOn: [{ _tag: "kind", kind: TargetKind.make("client-react") }], dependencies: [], contributions: [ { diff --git a/packages/catalog/src/registry/targetRegistry.ts b/packages/catalog/src/registry/targetRegistry.ts index 5efdb8f..0a010d9 100644 --- a/packages/catalog/src/registry/targetRegistry.ts +++ b/packages/catalog/src/registry/targetRegistry.ts @@ -78,10 +78,10 @@ export const targetRegistry: ReadonlyArray = [ }, { - kind: TargetKind.make("client"), - title: "Client Application", - description: "A frontend application, such as one built with React or Vue", - requiredModules: [ModuleId.make("config-typescript-vite")], + kind: TargetKind.make("client-react"), + title: "Client React Application", + description: "A frontend application built with React", + requiredModules: [ModuleId.make("config-typescript-react-vite")], contributions: [ // Files { diff --git a/packages/domain/src/Blueprint.test.ts b/packages/domain/src/Blueprint.test.ts index e08a3a7..d5c8618 100644 --- a/packages/domain/src/Blueprint.test.ts +++ b/packages/domain/src/Blueprint.test.ts @@ -112,7 +112,7 @@ describe("@repo/domain Blueprint", () => { identity.matches({ _tag: "identity", identity: new TargetIdentity({ - kind: TargetKind.make("client"), + kind: TargetKind.make("client-react"), name: "api", }), }), diff --git a/packages/domain/src/Scaffold.test.ts b/packages/domain/src/Scaffold.test.ts index e627d0d..a3bddce 100644 --- a/packages/domain/src/Scaffold.test.ts +++ b/packages/domain/src/Scaffold.test.ts @@ -13,14 +13,14 @@ describe("@repo/domain Scaffold", () => { name: "api", }); const clientIdentity = Schema.decodeUnknownSync(TargetIdentity)({ - kind: "client", + kind: "client-react", name: "admin-ui", }); expect(packageIdentity.toKey()).toBe("packages/domain"); expect(packageIdentity.toPath()).toBe("packages/domain"); expect(serverIdentity.toKey()).toBe("apps/server-api"); - expect(clientIdentity.toPath()).toBe("apps/client-admin-ui"); + expect(clientIdentity.toPath()).toBe("apps/client-react-admin-ui"); }); it("accepts empty target names for apps (uses kind only)", () => { @@ -66,12 +66,12 @@ describe("@repo/domain Scaffold", () => { it("slugifies names with underscores into canonical keys and paths", () => { const identity = Schema.decodeUnknownSync(TargetIdentity)({ - kind: "client", + kind: "client-react", name: "admin_ui", }); - expect(identity.toKey()).toBe("apps/client-admin-ui"); - expect(identity.toPath()).toBe("apps/client-admin-ui"); + expect(identity.toKey()).toBe("apps/client-react-admin-ui"); + expect(identity.toPath()).toBe("apps/client-react-admin-ui"); }); it("normalizes surrounding whitespace before deriving canonical keys and paths", () => { @@ -99,12 +99,12 @@ describe("@repo/domain Scaffold", () => { name: "api", }); const clientIdentity = Schema.decodeUnknownSync(TargetIdentity)({ - kind: "client", + kind: "client-react", name: "web", }); expect(serverIdentity.toPackageName()).toBe("server-api"); - expect(clientIdentity.toPackageName()).toBe("client-web"); + expect(clientIdentity.toPackageName()).toBe("client-react-web"); }); it("returns just kind for apps without names", () => { @@ -113,12 +113,12 @@ describe("@repo/domain Scaffold", () => { name: "", }); const clientIdentity = Schema.decodeUnknownSync(TargetIdentity)({ - kind: "client", + kind: "client-react", name: "", }); expect(serverIdentity.toPackageName()).toBe("server"); - expect(clientIdentity.toPackageName()).toBe("client"); + expect(clientIdentity.toPackageName()).toBe("client-react"); }); it("slugifies package names", () => { diff --git a/packages/scaffold/src/service/blueprint/BlueprintService.test.ts b/packages/scaffold/src/service/blueprint/BlueprintService.test.ts index 834d200..f7d50e7 100644 --- a/packages/scaffold/src/service/blueprint/BlueprintService.test.ts +++ b/packages/scaffold/src/service/blueprint/BlueprintService.test.ts @@ -244,7 +244,7 @@ describe("BlueprintService", () => { }, { identity: new TargetIdentity({ - kind: TargetKind.make("client"), + kind: TargetKind.make("client-react"), name: "api", }), modules: [], @@ -258,7 +258,7 @@ describe("BlueprintService", () => { .filter((node) => node._tag === "target") .map((node) => node.id), ).toEqual([ - "apps/client-api", + "apps/client-react-api", "apps/server-api", "packages/domain", ]); @@ -274,10 +274,12 @@ describe("BlueprintService", () => { targets: [ { identity: new TargetIdentity({ - kind: TargetKind.make("client"), + kind: TargetKind.make("client-react"), name: "app", }), - modules: [{ id: ModuleId.make("config-typescript-vite") }], + modules: [ + { id: ModuleId.make("config-typescript-react-vite") }, + ], }, ], }); @@ -287,16 +289,16 @@ describe("BlueprintService", () => { blueprint, toAttachedModuleNodeId( new TargetIdentity({ - kind: TargetKind.make("client"), + kind: TargetKind.make("client-react"), name: "app", }).toKey(), - ModuleId.make("config-typescript-vite"), + ModuleId.make("config-typescript-react-vite"), ), ), ).toMatchObject({ _tag: "attached-module", - targetId: "apps/client-app", - moduleId: "config-typescript-vite", + targetId: "apps/client-react-app", + moduleId: "config-typescript-react-vite", }); }), ); @@ -307,7 +309,7 @@ describe("BlueprintService", () => { Effect.gen(function* () { const blueprintService = yield* BlueprintService; const identity = new TargetIdentity({ - kind: TargetKind.make("client"), + kind: TargetKind.make("client-react"), name: "required", }); const blueprint = yield* blueprintService.resolve({ @@ -319,13 +321,13 @@ describe("BlueprintService", () => { blueprint, toAttachedModuleNodeId( identity.toKey(), - ModuleId.make("config-typescript-vite"), + ModuleId.make("config-typescript-react-vite"), ), ), ).toMatchObject({ _tag: "attached-module", - targetId: "apps/client-required", - moduleId: "config-typescript-vite", + targetId: "apps/client-react-required", + moduleId: "config-typescript-react-vite", }); }), ); diff --git a/packages/scaffold/src/service/finalize/FinalizeService.test.ts b/packages/scaffold/src/service/finalize/FinalizeService.test.ts index 0635af6..5dd03c9 100644 --- a/packages/scaffold/src/service/finalize/FinalizeService.test.ts +++ b/packages/scaffold/src/service/finalize/FinalizeService.test.ts @@ -24,7 +24,7 @@ const serverIdentity = new TargetIdentity({ }); const clientIdentity = new TargetIdentity({ - kind: TargetKind.make("client"), + kind: TargetKind.make("client-react"), name: "web", });