0.1.0 #1
@@ -1,8 +0,0 @@
|
|||||||
import { Schema } from "effect"
|
|
||||||
|
|
||||||
|
|
||||||
export class Post extends Schema.Class<Post>("Post")({
|
|
||||||
id: Schema.String,
|
|
||||||
title: Schema.String,
|
|
||||||
content: Schema.String,
|
|
||||||
}) {}
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
export * as Post from "./Post"
|
|
||||||
export * as Todo from "./Todo"
|
export * as Todo from "./Todo"
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { ReffuseContext } from "@thilawyn/reffuse"
|
import { Reffuse, ReffuseContext } from "@thilawyn/reffuse"
|
||||||
import { make } from "@thilawyn/reffuse/Reffuse"
|
|
||||||
import { FetchData } from "./services"
|
|
||||||
|
|
||||||
|
|
||||||
export const GlobalContext = ReffuseContext.make<FetchData.FetchData>()
|
export const GlobalContext = ReffuseContext.make()
|
||||||
export const Reffuse = make(GlobalContext)
|
export const R = Reffuse.make(GlobalContext)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Reffuse } from "@/reffuse"
|
import { R } from "@/reffuse"
|
||||||
import { createFileRoute } from "@tanstack/react-router"
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
import { Ref } from "effect"
|
import { Ref } from "effect"
|
||||||
|
|
||||||
@@ -9,10 +9,10 @@ export const Route = createFileRoute("/count")({
|
|||||||
|
|
||||||
function Count() {
|
function Count() {
|
||||||
|
|
||||||
const runSync = Reffuse.useRunSync()
|
const runSync = R.useRunSync()
|
||||||
|
|
||||||
const countRef = Reffuse.useRef(0)
|
const countRef = R.useRef(0)
|
||||||
const [count] = Reffuse.useRefState(countRef)
|
const [count] = R.useRefState(countRef)
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Reffuse } from "@/reffuse"
|
import { R } from "@/reffuse"
|
||||||
import { TodosContext } from "@/todos/reffuse"
|
import { TodosContext } from "@/todos/reffuse"
|
||||||
import { TodosState } from "@/todos/services"
|
import { TodosState } from "@/todos/services"
|
||||||
import { VTodos } from "@/todos/views/VTodos"
|
import { VTodos } from "@/todos/views/VTodos"
|
||||||
@@ -18,7 +18,7 @@ function Index() {
|
|||||||
Layer.provideMerge(TodosState.make("todos"))
|
Layer.provideMerge(TodosState.make("todos"))
|
||||||
), [])
|
), [])
|
||||||
|
|
||||||
Reffuse.useEffect(Effect.addFinalizer(() => Console.log("Effect cleanup")).pipe(
|
R.useEffect(Effect.addFinalizer(() => Console.log("Effect cleanup")).pipe(
|
||||||
Effect.flatMap(() => Console.log("Effect recalculated"))
|
Effect.flatMap(() => Console.log("Effect recalculated"))
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Reffuse } from "@/reffuse"
|
import { R } from "@/reffuse"
|
||||||
import { createFileRoute } from "@tanstack/react-router"
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
import { Console, DateTime, Effect, Ref, Schedule, Stream } from "effect"
|
import { Console, DateTime, Effect, Ref, Schedule, Stream } from "effect"
|
||||||
|
|
||||||
@@ -15,9 +15,9 @@ export const Route = createFileRoute("/time")({
|
|||||||
|
|
||||||
function Time() {
|
function Time() {
|
||||||
|
|
||||||
const timeRef = Reffuse.useRefFromEffect(DateTime.now)
|
const timeRef = R.useRefFromEffect(DateTime.now)
|
||||||
|
|
||||||
Reffuse.useFork(Effect.addFinalizer(() => Console.log("Cleanup")).pipe(
|
R.useFork(Effect.addFinalizer(() => Console.log("Cleanup")).pipe(
|
||||||
Effect.flatMap(() =>
|
Effect.flatMap(() =>
|
||||||
Stream.runForEach(timeEverySecond, v => Ref.set(timeRef, v))
|
Stream.runForEach(timeEverySecond, v => Ref.set(timeRef, v))
|
||||||
)
|
)
|
||||||
@@ -31,7 +31,7 @@ function Time() {
|
|||||||
// )),
|
// )),
|
||||||
// ), [timeRef])
|
// ), [timeRef])
|
||||||
|
|
||||||
const [time] = Reffuse.useRefState(timeRef)
|
const [time] = R.useRefState(timeRef)
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
import { Post } from "@/domain"
|
|
||||||
import { Chunk, Context, Effect, Layer } from "effect"
|
|
||||||
|
|
||||||
|
|
||||||
export class FetchData extends Context.Tag("FetchData")<FetchData, {
|
|
||||||
readonly fetchPosts: Effect.Effect<Chunk.Chunk<Post.Post>>
|
|
||||||
}>() {}
|
|
||||||
|
|
||||||
|
|
||||||
export const mockLayer = Layer.succeed(FetchData, {
|
|
||||||
fetchPosts: Effect.succeed(Chunk.make(
|
|
||||||
Post.Post.make({
|
|
||||||
id: "1",
|
|
||||||
title: "Lorem ipsum dolor sit amet",
|
|
||||||
content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eget lacus sit amet diam suscipit porttitor non at felis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla risus ligula, elementum nec scelerisque eget, volutpat vel sapien. Phasellus aliquam ac neque vitae sodales. Nunc sodales congue odio. Nulla eget nisl cursus, convallis lorem at, varius lectus. Aliquam vitae mauris vel mi dignissim condimentum. Proin sed dignissim sapien, ut cursus ex. Donec eget sapien sagittis, auctor metus vitae, fringilla lacus. Donec ut elit a quam aliquet consectetur interdum eu nisl. Etiam nec convallis purus, eu venenatis nulla. Phasellus non metus id mauris tincidunt cursus. Cras varius aliquet diam eu blandit. In hac habitasse platea dictumst.",
|
|
||||||
}),
|
|
||||||
|
|
||||||
Post.Post.make({
|
|
||||||
id: "2",
|
|
||||||
title: "Vestibulum non bibendum ligula",
|
|
||||||
content: "Vestibulum non bibendum ligula. Integer pellentesque, diam ac faucibus volutpat, nulla libero porttitor nunc, ac pulvinar tortor diam id ipsum. Sed id enim at odio euismod imperdiet et ac purus. Etiam tempus ipsum semper scelerisque mollis. Integer auctor, magna et tristique tempus, nisi mi euismod est, nec finibus quam nunc nec libero. Maecenas aliquet viverra magna, vitae blandit ligula pharetra id. Vestibulum vel lacus at nibh placerat tincidunt. Sed suscipit tellus vel felis euismod, et sollicitudin neque cursus. Curabitur dapibus eros vitae ligula suscipit, at facilisis risus venenatis. Sed pharetra blandit pulvinar. Vivamus vestibulum at ligula pulvinar fringilla. Suspendisse vel mattis libero, eget vulputate massa. Vivamus vehicula, lectus id tempor maximus, erat tortor blandit purus, at scelerisque nunc urna faucibus sapien.",
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
@@ -1 +1 @@
|
|||||||
export * as FetchData from "./FetchData"
|
export {}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { GlobalContext } from "@/reffuse"
|
import { GlobalContext } from "@/reffuse"
|
||||||
import { ReffuseContext } from "@thilawyn/reffuse"
|
import { Reffuse, ReffuseContext } from "@thilawyn/reffuse"
|
||||||
import { make } from "@thilawyn/reffuse/Reffuse"
|
|
||||||
import { TodosState } from "./services"
|
import { TodosState } from "./services"
|
||||||
|
|
||||||
|
|
||||||
export const TodosContext = ReffuseContext.make<TodosState.TodosState>()
|
export const TodosContext = ReffuseContext.make<TodosState.TodosState>()
|
||||||
export const Reffuse = make(GlobalContext, TodosContext)
|
export const R = Reffuse.make(GlobalContext, TodosContext)
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Todo } from "@/domain"
|
import { Todo } from "@/domain"
|
||||||
import { Box, Button, Card, Flex, TextArea } from "@radix-ui/themes"
|
import { Box, Button, Card, Flex, TextArea } from "@radix-ui/themes"
|
||||||
import { Effect, Option } from "effect"
|
import { Effect, Option } from "effect"
|
||||||
import { Reffuse } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
import { TodosState } from "../services"
|
import { TodosState } from "../services"
|
||||||
|
|
||||||
|
|
||||||
export function VNewTodo() {
|
export function VNewTodo() {
|
||||||
|
|
||||||
const runSync = Reffuse.useRunSync()
|
const runSync = R.useRunSync()
|
||||||
|
|
||||||
const createEmptyTodo = Todo.generateUniqueID.pipe(
|
const createEmptyTodo = Todo.generateUniqueID.pipe(
|
||||||
Effect.map(id => Todo.Todo.make({
|
Effect.map(id => Todo.Todo.make({
|
||||||
@@ -17,8 +17,8 @@ export function VNewTodo() {
|
|||||||
}, true))
|
}, true))
|
||||||
)
|
)
|
||||||
|
|
||||||
const todoRef = Reffuse.useRefFromEffect(createEmptyTodo)
|
const todoRef = R.useRefFromEffect(createEmptyTodo)
|
||||||
const [todo, setTodo] = Reffuse.useRefState(todoRef)
|
const [todo, setTodo] = R.useRefState(todoRef)
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Box, Card, Flex, IconButton, TextArea } from "@radix-ui/themes"
|
|||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
import { Delete } from "lucide-react"
|
import { Delete } from "lucide-react"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { Reffuse } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
import { TodosState } from "../services"
|
import { TodosState } from "../services"
|
||||||
|
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ export interface VTodoProps {
|
|||||||
|
|
||||||
export function VTodo({ index, todo }: VTodoProps) {
|
export function VTodo({ index, todo }: VTodoProps) {
|
||||||
|
|
||||||
const runSync = Reffuse.useRunSync()
|
const runSync = R.useRunSync()
|
||||||
const editorMode = useState(false)
|
const editorMode = useState(false)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Box, Flex } from "@radix-ui/themes"
|
import { Box, Flex } from "@radix-ui/themes"
|
||||||
import { Chunk, Effect, Stream } from "effect"
|
import { Chunk, Effect, Stream } from "effect"
|
||||||
import { Reffuse } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
import { TodosState } from "../services"
|
import { TodosState } from "../services"
|
||||||
import { VNewTodo } from "./VNewTodo"
|
import { VNewTodo } from "./VNewTodo"
|
||||||
import { VTodo } from "./VTodo"
|
import { VTodo } from "./VTodo"
|
||||||
@@ -9,14 +9,14 @@ import { VTodo } from "./VTodo"
|
|||||||
export function VTodos() {
|
export function VTodos() {
|
||||||
|
|
||||||
// Sync changes to the todos with the local storage
|
// Sync changes to the todos with the local storage
|
||||||
Reffuse.useFork(TodosState.TodosState.pipe(
|
R.useFork(TodosState.TodosState.pipe(
|
||||||
Effect.flatMap(state =>
|
Effect.flatMap(state =>
|
||||||
Stream.runForEach(state.todos.changes, () => state.saveToLocalStorage)
|
Stream.runForEach(state.todos.changes, () => state.saveToLocalStorage)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
const todosRef = Reffuse.useMemo(TodosState.TodosState.pipe(Effect.map(state => state.todos)))
|
const todosRef = R.useMemo(TodosState.TodosState.pipe(Effect.map(state => state.todos)))
|
||||||
const [todos] = Reffuse.useRefState(todosRef)
|
const [todos] = R.useRefState(todosRef)
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import { Post } from "@/domain"
|
|
||||||
import { Effect } from "effect"
|
|
||||||
import { PostsState } from "../posts/services"
|
|
||||||
import { Reffuse } from "./reffuse"
|
|
||||||
|
|
||||||
|
|
||||||
export interface VPostProps {
|
|
||||||
readonly index: number
|
|
||||||
readonly post: Post.Post
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function VPost({ post, index }: VPostProps) {
|
|
||||||
|
|
||||||
const runSync = Reffuse.useRunSync()
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex-col gap-1 items-stretch">
|
|
||||||
<p>{post.title}</p>
|
|
||||||
<p>{post.content}</p>
|
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={() => PostsState.PostsState.pipe(
|
|
||||||
Effect.flatMap(state => state.remove(index)),
|
|
||||||
runSync,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
X
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { Reffuse } from "../posts/reffuse"
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { Chunk } from "effect"
|
|
||||||
import { VPost } from "../post/VPost"
|
|
||||||
import { Reffuse } from "./reffuse"
|
|
||||||
import { PostsState } from "./services"
|
|
||||||
|
|
||||||
|
|
||||||
export function VPosts() {
|
|
||||||
|
|
||||||
const state = Reffuse.useMemo(PostsState.PostsState)
|
|
||||||
const [posts] = Reffuse.useRefState(state.posts)
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex-col gap-2 items-stretch">
|
|
||||||
{Chunk.map(posts, (post, index) => (
|
|
||||||
<VPost
|
|
||||||
key={`${ index }-${ post.id }`}
|
|
||||||
index={index}
|
|
||||||
post={post}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { GlobalContext } from "@/reffuse"
|
|
||||||
import { ReffuseContext } from "@thilawyn/reffuse"
|
|
||||||
import { make } from "@thilawyn/reffuse/Reffuse"
|
|
||||||
import { PostsState } from "./services"
|
|
||||||
|
|
||||||
|
|
||||||
export const PostsContext = ReffuseContext.make<PostsState.PostsState>()
|
|
||||||
export const Reffuse = make(GlobalContext, PostsContext)
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { Post } from "@/domain"
|
|
||||||
import { Chunk, Context, Effect, Layer, Ref, SubscriptionRef } from "effect"
|
|
||||||
|
|
||||||
|
|
||||||
export class PostsState extends Context.Tag("PostsState")<PostsState, {
|
|
||||||
readonly posts: SubscriptionRef.SubscriptionRef<Chunk.Chunk<Post.Post>>
|
|
||||||
readonly remove: (index: number) => Effect.Effect<void>
|
|
||||||
}>() {}
|
|
||||||
|
|
||||||
export const make = (posts: Chunk.Chunk<Post.Post>) => Layer.effect(PostsState, SubscriptionRef.make(posts).pipe(
|
|
||||||
Effect.map(posts => ({
|
|
||||||
posts,
|
|
||||||
remove: (index: number) => Ref.update(posts, Chunk.remove(index)),
|
|
||||||
}))
|
|
||||||
))
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * as PostsState from "./PostsState"
|
|
||||||
@@ -198,7 +198,7 @@ export interface ScopeOptions {
|
|||||||
|
|
||||||
|
|
||||||
export const make = <
|
export const make = <
|
||||||
const Contexts extends readonly ReffuseContext.ReffuseContext<any>[]
|
const Contexts extends readonly (ReffuseContext.ReffuseContext<any> | ReffuseContext.ReffuseContext<never>)[]
|
||||||
>(
|
>(
|
||||||
...contexts: Contexts
|
...contexts: Contexts
|
||||||
): Reffuse<{ [K in keyof Contexts]: ReffuseContext.R<Contexts[K]> }[number]> =>
|
): Reffuse<{ [K in keyof Contexts]: ReffuseContext.R<Contexts[K]> }[number]> =>
|
||||||
|
|||||||
Reference in New Issue
Block a user