Add Effect v4 support, Fast Refresh tooling, and revamped docs #56

Merged
Thilawyn merged 133 commits from next into master 2026-07-26 02:32:59 +02:00
26 changed files with 78 additions and 48 deletions
Showing only changes of commit 65e90325d0 - Show all commits
+2 -2
View File
@@ -90,9 +90,9 @@
"lint:tsc": "tsc --noEmit", "lint:tsc": "tsc --noEmit",
"lint:biome": "biome lint", "lint:biome": "biome lint",
"test": "vitest run", "test": "vitest run",
"build": "tsc", "build": "tsc -b tsconfig.build.json",
"pack": "npm pack", "pack": "npm pack",
"clean:cache": "rm -rf .turbo tsconfig.tsbuildinfo", "clean:cache": "rm -rf .turbo *.tsbuildinfo",
"clean:dist": "rm -rf dist", "clean:dist": "rm -rf dist",
"clean:modules": "rm -rf node_modules" "clean:modules": "rm -rf node_modules"
}, },
@@ -2,10 +2,10 @@ import { act, fireEvent, render, screen } from "@testing-library/react"
import { Effect, Layer } from "effect" import { Effect, Layer } from "effect"
import * as React from "react" import * as React from "react"
import { describe, expect, it, vi } from "vitest" import { describe, expect, it, vi } from "vitest"
import * as Async from "../src/Async.js" import * as Async from "./Async.js"
import * as Component from "../src/Component.js" import * as Component from "./Component.js"
import * as Memoized from "../src/Memoized.js" import * as Memoized from "./Memoized.js"
import * as ReactRuntime from "../src/ReactRuntime.js" import * as ReactRuntime from "./ReactRuntime.js"
describe("Async", () => { describe("Async", () => {
it("does not rerun for an unrelated parent state update", async () => { it("does not rerun for an unrelated parent state update", async () => {
@@ -2,10 +2,10 @@ import { act, fireEvent, render, screen, waitFor } from "@testing-library/react"
import { Context, Effect, HashMap, Layer, SubscriptionRef } from "effect" import { Context, Effect, HashMap, Layer, SubscriptionRef } from "effect"
import * as React from "react" import * as React from "react"
import { afterEach, describe, expect, it, vi } from "vitest" import { afterEach, describe, expect, it, vi } from "vitest"
import * as Component from "../src/Component.js" import * as Component from "./Component.js"
import * as ReactRuntime from "../src/ReactRuntime.js" import * as ReactRuntime from "./ReactRuntime.js"
import * as Refreshable from "../src/Refreshable.js" import * as Refreshable from "./Refreshable.js"
import * as ScopeRegistry from "../src/ScopeRegistry.js" import * as ScopeRegistry from "./ScopeRegistry.js"
class ValueService extends Context.Service<ValueService, { readonly value: string }>()("ValueService") {} class ValueService extends Context.Service<ValueService, { readonly value: string }>()("ValueService") {}
@@ -2,9 +2,9 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react"
import { Effect, Layer, SubscriptionRef } from "effect" import { Effect, Layer, SubscriptionRef } from "effect"
import * as React from "react" import * as React from "react"
import { describe, expect, it } from "vitest" import { describe, expect, it } from "vitest"
import * as Component from "../src/Component.js" import * as Component from "./Component.js"
import * as Lens from "../src/Lens.js" import * as Lens from "./Lens.js"
import * as ReactRuntime from "../src/ReactRuntime.js" import * as ReactRuntime from "./ReactRuntime.js"
const makeRuntime = async () => { const makeRuntime = async () => {
@@ -1,9 +1,9 @@
import { Effect, type Scope, Stream } from "effect" import { Effect, type Scope, Stream } from "effect"
import { AsyncResult } from "effect/unstable/reactivity" import { AsyncResult } from "effect/unstable/reactivity"
import { describe, expect, it } from "vitest" import { describe, expect, it } from "vitest"
import * as Query from "../src/Query.js" import * as Query from "./Query.js"
import * as QueryClient from "../src/QueryClient.js" import * as QueryClient from "./QueryClient.js"
import * as View from "../src/View.js" import * as View from "./View.js"
const runQueryTest = <A, E>(effect: Effect.Effect<A, E, QueryClient.QueryClient | Scope.Scope>) => const runQueryTest = <A, E>(effect: Effect.Effect<A, E, QueryClient.QueryClient | Scope.Scope>) =>
@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from "vitest" import { describe, expect, it, vi } from "vitest"
import type * as Component from "../src/Component.js" import type * as Component from "./Component.js"
import * as Refreshable from "../src/Refreshable.js" import * as Refreshable from "./Refreshable.js"
describe("Refreshable", () => { describe("Refreshable", () => {
@@ -2,9 +2,9 @@ import { render, screen, waitFor } from "@testing-library/react"
import { Effect, Layer, SubscriptionRef } from "effect" import { Effect, Layer, SubscriptionRef } from "effect"
import { Lens } from "effect-lens" import { Lens } from "effect-lens"
import { describe, expect, it } from "vitest" import { describe, expect, it } from "vitest"
import * as Component from "../src/Component.js" import * as Component from "./Component.js"
import * as ReactRuntime from "../src/ReactRuntime.js" import * as ReactRuntime from "./ReactRuntime.js"
import * as View from "../src/View.js" import * as View from "./View.js"
const makeRuntime = async () => { const makeRuntime = async () => {
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["**/setup-tests.ts", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"]
}
-1
View File
@@ -36,5 +36,4 @@
}, },
"include": ["./src"], "include": ["./src"],
"exclude": ["**/*.test.ts", "**/*.spec.ts"]
} }
+2 -2
View File
@@ -4,7 +4,7 @@ import { defineConfig } from "vitest/config"
export default defineConfig({ export default defineConfig({
test: { test: {
environment: "jsdom", environment: "jsdom",
include: ["test/**/*.test.ts?(x)"], include: ["./src/**/*.test.ts?(x)"],
setupFiles: ["test/setup.ts"], setupFiles: ["./src/setup-tests.ts"],
}, },
}) })
+2 -2
View File
@@ -29,12 +29,12 @@
] ]
}, },
"scripts": { "scripts": {
"build": "tsc",
"lint:tsc": "tsc --noEmit", "lint:tsc": "tsc --noEmit",
"lint:biome": "biome lint", "lint:biome": "biome lint",
"test": "vitest run", "test": "vitest run",
"build": "tsc -b tsconfig.build.json",
"pack": "npm pack", "pack": "npm pack",
"clean:cache": "rm -rf .turbo tsconfig.tsbuildinfo", "clean:cache": "rm -rf .turbo *.tsbuildinfo",
"clean:dist": "rm -rf dist", "clean:dist": "rm -rf dist",
"clean:modules": "rm -rf node_modules" "clean:modules": "rm -rf node_modules"
}, },
@@ -2,8 +2,8 @@ import { render, screen, waitFor } from "@testing-library/react"
import { Context, Effect, Layer } from "effect" import { Context, Effect, Layer } from "effect"
import * as React from "react" import * as React from "react"
import { afterEach, describe, expect, it, vi } from "vitest" import { afterEach, describe, expect, it, vi } from "vitest"
import * as Component from "../src/Component.js" import * as Component from "./Component.js"
import * as ReactRuntime from "../src/ReactRuntime.js" import * as ReactRuntime from "./ReactRuntime.js"
class ValueService extends Context.Tag("ValueService")<ValueService, { readonly value: string }>() {} class ValueService extends Context.Tag("ValueService")<ValueService, { readonly value: string }>() {}
@@ -2,9 +2,9 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react"
import { Effect, Layer, SubscriptionRef } from "effect" import { Effect, Layer, SubscriptionRef } from "effect"
import * as React from "react" import * as React from "react"
import { describe, expect, it } from "vitest" import { describe, expect, it } from "vitest"
import * as Component from "../src/Component.js" import * as Component from "./Component.js"
import * as Lens from "../src/Lens.js" import * as Lens from "./Lens.js"
import * as ReactRuntime from "../src/ReactRuntime.js" import * as ReactRuntime from "./ReactRuntime.js"
const makeRuntime = async () => { const makeRuntime = async () => {
@@ -1,8 +1,8 @@
import { Effect, Option, type Scope, Stream } from "effect" import { Effect, Option, type Scope, Stream } from "effect"
import { describe, expect, it } from "vitest" import { describe, expect, it } from "vitest"
import * as Query from "../src/Query.js" import * as Query from "./Query.js"
import * as QueryClient from "../src/QueryClient.js" import * as QueryClient from "./QueryClient.js"
import * as Result from "../src/Result.js" import * as Result from "./Result.js"
const runQueryTest = <A, E>(effect: Effect.Effect<A, E, QueryClient.QueryClient | Scope.Scope>) => const runQueryTest = <A, E>(effect: Effect.Effect<A, E, QueryClient.QueryClient | Scope.Scope>) =>
@@ -2,9 +2,9 @@ import { render, screen, waitFor } from "@testing-library/react"
import { Effect, Fiber, Layer, Stream, SubscriptionRef } from "effect" import { Effect, Fiber, Layer, Stream, SubscriptionRef } from "effect"
import { Lens } from "effect-lens" import { Lens } from "effect-lens"
import { describe, expect, it } from "vitest" import { describe, expect, it } from "vitest"
import * as Component from "../src/Component.js" import * as Component from "./Component.js"
import * as ReactRuntime from "../src/ReactRuntime.js" import * as ReactRuntime from "./ReactRuntime.js"
import * as Subscribable from "../src/Subscribable.js" import * as Subscribable from "./Subscribable.js"
const makeRuntime = async () => { const makeRuntime = async () => {
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["**/setup-tests.ts", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"]
}
-1
View File
@@ -36,5 +36,4 @@
}, },
"include": ["./src"], "include": ["./src"],
"exclude": ["**/*.test.ts", "**/*.spec.ts"]
} }
+1 -1
View File
@@ -4,6 +4,6 @@ import { defineConfig } from "vitest/config"
export default defineConfig({ export default defineConfig({
test: { test: {
environment: "jsdom", environment: "jsdom",
include: ["test/**/*.test.ts?(x)"], include: ["./src/**/*.test.ts?(x)"],
}, },
}) })
+1 -1
View File
@@ -3,6 +3,6 @@
"root": false, "root": false,
"extends": "//", "extends": "//",
"files": { "files": {
"includes": ["./src/**", "./test/**"] "includes": ["./src/**"]
} }
} }
+2 -2
View File
@@ -26,9 +26,9 @@
"lint:tsc": "tsc --noEmit", "lint:tsc": "tsc --noEmit",
"lint:biome": "biome lint", "lint:biome": "biome lint",
"test": "vitest run", "test": "vitest run",
"build": "tsc", "build": "tsc -b tsconfig.build.json",
"pack": "npm pack", "pack": "npm pack",
"clean:cache": "rm -rf .turbo tsconfig.tsbuildinfo", "clean:cache": "rm -rf .turbo *.tsbuildinfo",
"clean:dist": "rm -rf dist", "clean:dist": "rm -rf dist",
"clean:modules": "rm -rf node_modules" "clean:modules": "rm -rf node_modules"
}, },
@@ -1,7 +1,7 @@
import path from "node:path" import path from "node:path"
import type { Plugin, TransformPluginContext } from "vite" import type { Plugin, TransformPluginContext } from "vite"
import { describe, expect, it } from "vitest" import { describe, expect, it } from "vitest"
import { effectViewPlugin } from "../src/index.js" import { effectViewPlugin } from "./index.js"
const runTransform = async ( const runTransform = async (
@@ -1,7 +1,7 @@
import type * as Component from "effect-fc-next/Component" import type * as Component from "effect-fc-next/Component"
import * as Refreshable from "effect-fc-next/Refreshable" import * as Refreshable from "effect-fc-next/Refreshable"
import { describe, expect, it, vi } from "vitest" import { describe, expect, it, vi } from "vitest"
import { accept, register } from "../src/runtime.js" import { accept, register } from "./runtime.js"
describe("refresh runtime", () => { describe("refresh runtime", () => {
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["**/setup-tests.ts", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"]
}
+23 -3
View File
@@ -1,19 +1,39 @@
{ {
"compilerOptions": { "compilerOptions": {
"lib": ["ESNext"], // Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext", "target": "ESNext",
"module": "NodeNext", "module": "NodeNext",
"moduleDetection": "force", "moduleDetection": "force",
"jsx": "react-jsx",
// "allowJs": true,
// Bundler mode
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
// "allowImportingTsExtensions": true,
"verbatimModuleSyntax": true, "verbatimModuleSyntax": true,
// "noEmit": true,
// Best practices
"strict": true, "strict": true,
"skipLibCheck": true, "skipLibCheck": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false,
// Build
"rootDir": "./src", "rootDir": "./src",
"outDir": "./dist", "outDir": "./dist",
"declaration": true, "declaration": true,
"sourceMap": true "sourceMap": true,
"plugins": [
{ "name": "@effect/language-service" }
]
}, },
"include": ["./src"], "include": ["./src"],
"exclude": ["**/*.test.ts", "**/*.spec.ts"]
} }
+1 -1
View File
@@ -3,6 +3,6 @@ import { defineConfig } from "vitest/config"
export default defineConfig({ export default defineConfig({
test: { test: {
include: ["test/**/*.test.ts"], include: ["./src/**/*.test.ts?(x)"],
}, },
}) })