diff --git a/packages/store/src/index.ts b/packages/store/src/index.ts index 8a6f2bec..92f68772 100644 --- a/packages/store/src/index.ts +++ b/packages/store/src/index.ts @@ -382,8 +382,7 @@ export function createStoreInstance< const definitions = Array.isArray(rawDefinitions) ? rawDefinitions : [rawDefinitions]; const selected = definitions.find((entry) => entry.runtime === options.runtime) ?? - definitions.find((entry) => entry.runtime === "shared") ?? - definitions.find((entry) => entry.runtime === "legacy"); + definitions.find((entry) => entry.runtime === "shared"); if (!selected) continue; Reflect.set(actions, name, async (...args: unknown[]) => { currentAction = name; diff --git a/packages/store/src/types.ts b/packages/store/src/types.ts index 6116e964..39216e5d 100644 --- a/packages/store/src/types.ts +++ b/packages/store/src/types.ts @@ -1,5 +1,5 @@ export type StoreKind = "global" | "page"; -export type StoreRuntime = "shared" | "client" | "server" | "legacy"; +export type StoreRuntime = "shared" | "client" | "server"; export type PersistenceStorage = "memory" | "session" | "local"; /** Broad callable constraint that preserves each action's concrete parameters and return type. */ export type StoreFunction = (...args: any[]) => unknown; diff --git a/packages/store/test/legacy-runtime-removal.test.ts b/packages/store/test/legacy-runtime-removal.test.ts new file mode 100644 index 00000000..80e9ebde --- /dev/null +++ b/packages/store/test/legacy-runtime-removal.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from "bun:test"; +import { createStoreContainer, defineStore } from "../src/index.ts"; + +// Regression guard for the removed `"legacy"` StoreRuntime fallback. +// +// `createStoreInstance` resolves an action definition by walking: +// exact `options.runtime` match -> "shared" match -> (previously) "legacy" match +// The `"legacy"` step was dead (nothing ever produced a `runtime: "legacy"` +// action once `store-codegen.ts` stopped emitting it) and has been removed. +// This test locks in the remaining `options.runtime` -> `"shared"` chain so a +// future edit can't silently drop the `"shared"` fallback too. +const OnlySharedActionStore = defineStore({ + name: "OnlySharedActionStore", + kind: "global" as const, + createSharedState: () => ({ count: 0 }), + actions: { + // No "client" or "server" definition exists for this action — only + // "shared". A server-runtime container must still resolve it via the + // "shared" fallback. + increment: { + runtime: "shared" as const, + handler: ({ state }: any, amount = 1) => { + state.count += amount; + }, + }, + }, +}); + +test("an action with only a shared definition resolves via the shared fallback on the server runtime", async () => { + const container = createStoreContainer({ runtime: "server", request: {} }); + const store = await container.use(OnlySharedActionStore); + await store.increment(5); + expect(store.count).toBe(5); +}); + +test("an action with only a shared definition resolves via the shared fallback on the client runtime", async () => { + const container = createStoreContainer({ runtime: "client" }); + const store = await container.use(OnlySharedActionStore); + await store.increment(3); + expect(store.count).toBe(3); +});