@rikalabs/effect-react 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +179 -0
- package/dist/actions/http.d.ts +18 -0
- package/dist/actions/index.d.ts +4 -0
- package/dist/actions/react.d.ts +7 -0
- package/dist/actions/service.d.ts +18 -0
- package/dist/actions/types.d.ts +33 -0
- package/dist/boundary/codecs.d.ts +40 -0
- package/dist/boundary/errors.d.ts +22 -0
- package/dist/boundary/index.d.ts +2 -0
- package/dist/chunk-2GIUCKL2.js +16 -0
- package/dist/chunk-2GIUCKL2.js.map +1 -0
- package/dist/chunk-2TG7YEVD.js +11 -0
- package/dist/chunk-2TG7YEVD.js.map +1 -0
- package/dist/chunk-6FI4ROTW.js +152 -0
- package/dist/chunk-6FI4ROTW.js.map +1 -0
- package/dist/chunk-C5JI7D7W.js +213 -0
- package/dist/chunk-C5JI7D7W.js.map +1 -0
- package/dist/chunk-EEYASTXR.js +99 -0
- package/dist/chunk-EEYASTXR.js.map +1 -0
- package/dist/chunk-H7MOLKTU.js +301 -0
- package/dist/chunk-H7MOLKTU.js.map +1 -0
- package/dist/chunk-IVIYY6S5.js +77 -0
- package/dist/chunk-IVIYY6S5.js.map +1 -0
- package/dist/chunk-JKN75OYC.js +87 -0
- package/dist/chunk-JKN75OYC.js.map +1 -0
- package/dist/chunk-M2CJG6T7.js +24 -0
- package/dist/chunk-M2CJG6T7.js.map +1 -0
- package/dist/chunk-MDGEGQZB.js +206 -0
- package/dist/chunk-MDGEGQZB.js.map +1 -0
- package/dist/chunk-NI2GNZ7S.js +78 -0
- package/dist/chunk-NI2GNZ7S.js.map +1 -0
- package/dist/chunk-O7XTA7H3.js +423 -0
- package/dist/chunk-O7XTA7H3.js.map +1 -0
- package/dist/chunk-S67FHWAR.js +88 -0
- package/dist/chunk-S67FHWAR.js.map +1 -0
- package/dist/chunk-SKC3HMF3.js +17 -0
- package/dist/chunk-SKC3HMF3.js.map +1 -0
- package/dist/chunk-TUJZ6XJY.js +127 -0
- package/dist/chunk-TUJZ6XJY.js.map +1 -0
- package/dist/chunk-WPV3WFMS.js +38 -0
- package/dist/chunk-WPV3WFMS.js.map +1 -0
- package/dist/chunk-XIBEKS5A.js +301 -0
- package/dist/chunk-XIBEKS5A.js.map +1 -0
- package/dist/chunk-YG22YP5K.js +68 -0
- package/dist/chunk-YG22YP5K.js.map +1 -0
- package/dist/chunk-ZMZQBREU.js +262 -0
- package/dist/chunk-ZMZQBREU.js.map +1 -0
- package/dist/client/index.cjs +191 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.js +14 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config/index.cjs +63 -0
- package/dist/config/index.cjs.map +1 -0
- package/dist/config/index.d.ts +32 -0
- package/dist/config/index.js +9 -0
- package/dist/config/index.js.map +1 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/data/react.d.ts +10 -0
- package/dist/data/service.d.ts +20 -0
- package/dist/data/types.d.ts +31 -0
- package/dist/devtools/events.d.ts +37 -0
- package/dist/devtools/index.cjs +149 -0
- package/dist/devtools/index.cjs.map +1 -0
- package/dist/devtools/index.d.ts +2 -0
- package/dist/devtools/index.js +18 -0
- package/dist/devtools/index.js.map +1 -0
- package/dist/devtools/react.d.ts +8 -0
- package/dist/form/index.cjs +301 -0
- package/dist/form/index.cjs.map +1 -0
- package/dist/form/index.d.ts +3 -0
- package/dist/form/index.js +14 -0
- package/dist/form/index.js.map +1 -0
- package/dist/form/react.d.ts +9 -0
- package/dist/form/service.d.ts +3 -0
- package/dist/form/types.d.ts +41 -0
- package/dist/framework/app.d.ts +21 -0
- package/dist/framework/cache.d.ts +10 -0
- package/dist/framework/contracts.d.ts +32 -0
- package/dist/framework/index.cjs +1006 -0
- package/dist/framework/index.cjs.map +1 -0
- package/dist/framework/index.d.ts +4 -0
- package/dist/framework/index.js +35 -0
- package/dist/framework/index.js.map +1 -0
- package/dist/framework/manifest.d.ts +12 -0
- package/dist/framework/vite.d.ts +13 -0
- package/dist/framework-vite/index.cjs +163 -0
- package/dist/framework-vite/index.cjs.map +1 -0
- package/dist/framework-vite/index.d.ts +1 -0
- package/dist/framework-vite/index.js +125 -0
- package/dist/framework-vite/index.js.map +1 -0
- package/dist/grid/grid.d.ts +8 -0
- package/dist/grid/index.cjs +238 -0
- package/dist/grid/index.cjs.map +1 -0
- package/dist/grid/index.d.ts +2 -0
- package/dist/grid/index.js +19 -0
- package/dist/grid/index.js.map +1 -0
- package/dist/grid/types.d.ts +35 -0
- package/dist/index.cjs +2512 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +207 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/app.d.ts +26 -0
- package/dist/kernel/index.d.ts +3 -0
- package/dist/kernel/runtime.d.ts +5 -0
- package/dist/kernel/telemetry.d.ts +37 -0
- package/dist/navigation/index.d.ts +4 -0
- package/dist/navigation/matcher.d.ts +13 -0
- package/dist/navigation/react.d.ts +12 -0
- package/dist/navigation/service.d.ts +23 -0
- package/dist/navigation/types.d.ts +65 -0
- package/dist/query/index.cjs +361 -0
- package/dist/query/index.cjs.map +1 -0
- package/dist/query/index.d.ts +3 -0
- package/dist/query/index.js +30 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/react.d.ts +27 -0
- package/dist/query/service.d.ts +10 -0
- package/dist/query/types.d.ts +5 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/provider.d.ts +10 -0
- package/dist/realtime/channel.d.ts +15 -0
- package/dist/realtime/index.cjs +117 -0
- package/dist/realtime/index.cjs.map +1 -0
- package/dist/realtime/index.d.ts +2 -0
- package/dist/realtime/index.js +15 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/presence.d.ts +22 -0
- package/dist/render/hydration.d.ts +24 -0
- package/dist/render/index.d.ts +2 -0
- package/dist/render/ssr.d.ts +13 -0
- package/dist/router/helpers.d.ts +26 -0
- package/dist/router/index.cjs +236 -0
- package/dist/router/index.cjs.map +1 -0
- package/dist/router/index.d.ts +4 -0
- package/dist/router/index.js +40 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/react.d.ts +5 -0
- package/dist/router/service.d.ts +5 -0
- package/dist/router/types.d.ts +1 -0
- package/dist/server/index.cjs +174 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.ts +16 -0
- package/dist/server/index.js +12 -0
- package/dist/server/index.js.map +1 -0
- package/dist/state/index.cjs +128 -0
- package/dist/state/index.cjs.map +1 -0
- package/dist/state/index.d.ts +2 -0
- package/dist/state/index.js +36 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/react.d.ts +3 -0
- package/dist/state/service.d.ts +28 -0
- package/dist/testing/index.cjs +970 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +13 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/virtual/index.cjs +160 -0
- package/dist/virtual/index.cjs.map +1 -0
- package/dist/virtual/index.d.ts +2 -0
- package/dist/virtual/index.js +21 -0
- package/dist/virtual/index.js.map +1 -0
- package/dist/virtual/types.d.ts +25 -0
- package/dist/virtual/virtual.d.ts +9 -0
- package/package.json +156 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/query/service.ts","../src/data/react.tsx","../src/query/react.tsx"],"sourcesContent":["import { Effect } from \"effect\";\nimport { Data, fetchQuery as fetchDataQuery } from \"../data\";\nimport type { BoundaryDecodeError } from \"../boundary\";\nimport type { BoundaryProtocolError } from \"../boundary/errors\";\nimport type { QueryDefinition, QueryRuntimeError } from \"./types\";\n\nexport const fetchQuery = fetchDataQuery;\n\nexport const prefetchQuery = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n): Effect.Effect<void, E | BoundaryDecodeError | BoundaryProtocolError | QueryRuntimeError, Data> =>\n Effect.flatMap(Data, (service) => service.prefetch(definition, input));\n\nexport const invalidateQuery = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n): Effect.Effect<void, QueryRuntimeError, Data> =>\n Effect.flatMap(Data, (service) => service.invalidate(definition, input));\n\nexport const prefetch = prefetchQuery;\nexport const invalidate = invalidateQuery;\n","import { Effect, Fiber, Stream } from \"effect\";\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from \"react\";\nimport { useEffectRuntime } from \"../react/provider\";\nimport { Data } from \"./service\";\nimport type { QueryDefinition, QueryRunOptions, QuerySnapshot } from \"./types\";\n\nconst useDataService = () => {\n const runtime = useEffectRuntime();\n return useMemo(() => runtime.runSync(Data), [runtime]);\n};\n\nexport interface UseQueryOptions {\n readonly enabled?: boolean;\n readonly run?: QueryRunOptions;\n}\n\nexport const useQuery = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n options: UseQueryOptions = {},\n): QuerySnapshot<Output, E> & {\n readonly refetch: () => Promise<Output>;\n readonly invalidate: () => Promise<void>;\n} => {\n const runtime = useEffectRuntime();\n const data = useDataService();\n\n const subscribe = useCallback(\n (listener: () => void) => {\n const fiber = runtime.runFork(\n Stream.runForEach(data.snapshots, () => Effect.sync(listener)),\n );\n\n return () => {\n runtime.runFork(Fiber.interrupt(fiber));\n };\n },\n [data, runtime],\n );\n\n const getSnapshot = useCallback(\n () => runtime.runSync(data.getSnapshot(definition, input)) as QuerySnapshot<Output, E>,\n [data, definition, input, runtime],\n );\n\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (options.enabled === false) {\n return;\n }\n runtime.runFork(data.prefetch(definition, input));\n }, [data, definition, input, options.enabled, runtime]);\n\n const refetch = useCallback(\n () => runtime.runPromise(data.fetch(definition, input, { ...options.run, forceRefresh: true })),\n [data, definition, input, options.run, runtime],\n );\n\n const invalidate = useCallback(\n () => runtime.runPromise(data.invalidate(definition, input)),\n [data, definition, input, runtime],\n );\n\n return {\n ...snapshot,\n refetch,\n invalidate,\n };\n};\n\nexport const useSuspenseQuery = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n): Output => {\n const result = useQuery(definition, input);\n if (result.phase === \"failure\") {\n throw result.error;\n }\n if (result.phase === \"success\") {\n return result.data as Output;\n }\n throw result.refetch();\n};\n","import { Effect } from \"effect\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n useQuery as useDataQuery,\n useSuspenseQuery as useDataSuspenseQuery,\n type UseQueryOptions,\n} from \"../data\";\nimport { Data } from \"../data\";\nimport { useEffectRuntime } from \"../react/provider\";\nimport type {\n QueryDefinition,\n QueryError,\n QueryPhase,\n QueryRunOptions,\n} from \"./types\";\n\ninterface InfiniteQueryEntry<Output, PageParam> {\n readonly key: string;\n readonly pageParam: PageParam;\n readonly data: Output;\n}\n\nconst upsertInfiniteEntry = <Output, PageParam>(\n entries: readonly InfiniteQueryEntry<Output, PageParam>[],\n nextEntry: InfiniteQueryEntry<Output, PageParam>,\n): readonly InfiniteQueryEntry<Output, PageParam>[] => {\n const index = entries.findIndex((entry) => entry.key === nextEntry.key);\n if (index < 0) {\n return [...entries, nextEntry];\n }\n const next = [...entries];\n next[index] = nextEntry;\n return next;\n};\n\nconst useDataService = () => {\n const runtime = useEffectRuntime();\n return useMemo(() => runtime.runSync(Data), [runtime]);\n};\n\nexport { type UseQueryOptions };\n\nexport const useQuery = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n options: UseQueryOptions = {},\n) => useDataQuery(definition, input, options);\n\nexport const useSuspenseQuery = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n): Output => useDataSuspenseQuery(definition, input);\n\nexport interface UseInfiniteQueryOptions<Input, Output, PageParam> {\n readonly initialPageParam: PageParam;\n readonly getInput: (pageParam: PageParam) => Input;\n readonly getNextPageParam: (\n lastPage: Output,\n allPages: readonly Output[],\n lastPageParam: PageParam,\n allPageParams: readonly PageParam[],\n ) => PageParam | undefined;\n readonly enabled?: boolean;\n readonly run?: QueryRunOptions;\n}\n\nexport interface UseInfiniteQueryResult<Output, E, PageParam> {\n readonly phase: QueryPhase;\n readonly pages: readonly Output[];\n readonly pageParams: readonly PageParam[];\n readonly error: QueryError<E> | undefined;\n readonly hasNextPage: boolean;\n readonly isFetchingNextPage: boolean;\n readonly fetchNextPage: () => Promise<Output | undefined>;\n readonly refetch: () => Promise<readonly Output[]>;\n readonly invalidate: () => Promise<void>;\n}\n\nexport const useInfiniteQuery = <Name extends string, Input, Output, E, PageParam>(\n definition: QueryDefinition<Name, Input, Output, E>,\n options: UseInfiniteQueryOptions<Input, Output, PageParam>,\n): UseInfiniteQueryResult<Output, E, PageParam> => {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const initialPageParam = options.initialPageParam;\n const enabled = options.enabled;\n const run = options.run;\n\n const getInput = useCallback(\n (pageParam: PageParam): Input => optionsRef.current.getInput(pageParam),\n [],\n );\n\n const getNextPageParam = useCallback(\n (\n lastPage: Output,\n allPages: readonly Output[],\n lastPageParam: PageParam,\n allPageParams: readonly PageParam[],\n ): PageParam | undefined =>\n optionsRef.current.getNextPageParam(lastPage, allPages, lastPageParam, allPageParams),\n [],\n );\n\n const runtime = useEffectRuntime();\n const data = useDataService();\n const [initialInput, setInitialInput] = useState<Input>(() =>\n getInput(initialPageParam),\n );\n const [entries, setEntries] = useState<readonly InfiniteQueryEntry<Output, PageParam>[]>([]);\n const [error, setError] = useState<QueryError<E> | undefined>(undefined);\n const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);\n\n const initialQuery = useQuery(\n definition,\n initialInput,\n {\n ...(enabled !== undefined ? { enabled } : {}),\n ...(run !== undefined ? { run } : {}),\n },\n );\n\n useEffect(() => {\n setInitialInput(getInput(initialPageParam));\n setEntries([]);\n setError(undefined);\n setIsFetchingNextPage(false);\n }, [definition, getInput, initialPageParam]);\n\n useEffect(() => {\n if (initialQuery.phase === \"success\") {\n setEntries((current) =>\n upsertInfiniteEntry(current, {\n key: initialQuery.key,\n pageParam: initialPageParam,\n data: initialQuery.data as Output,\n }),\n );\n setError(undefined);\n return;\n }\n if (initialQuery.phase === \"failure\") {\n setError(initialQuery.error as QueryError<E>);\n }\n }, [\n initialQuery.data,\n initialQuery.error,\n initialQuery.key,\n initialQuery.phase,\n initialPageParam,\n ]);\n\n const pages = useMemo(() => entries.map((entry) => entry.data), [entries]);\n const pageParams = useMemo(() => entries.map((entry) => entry.pageParam), [entries]);\n\n const resolveNextPageParam = useCallback((): PageParam | undefined => {\n const lastEntry = entries[entries.length - 1];\n if (lastEntry !== undefined) {\n return getNextPageParam(lastEntry.data, pages, lastEntry.pageParam, pageParams);\n }\n if (initialQuery.phase !== \"success\") {\n return undefined;\n }\n const initialPage = initialQuery.data as Output;\n return getNextPageParam(\n initialPage,\n [initialPage],\n initialPageParam,\n [initialPageParam],\n );\n }, [\n entries,\n getNextPageParam,\n initialPageParam,\n initialQuery.data,\n initialQuery.phase,\n pageParams,\n pages,\n ]);\n\n const fetchNextPage = useCallback((): Promise<Output | undefined> => {\n const nextPageParam = resolveNextPageParam();\n if (nextPageParam === undefined) {\n return runtime.runPromise(Effect.succeed<Output | undefined>(undefined));\n }\n\n setIsFetchingNextPage(true);\n setError(undefined);\n\n const input = getInput(nextPageParam);\n const program = Effect.gen(function* () {\n const value = yield* data.fetch(definition, input, run);\n const snapshot = yield* data.getSnapshot(definition, input);\n return {\n key: snapshot.key,\n pageParam: nextPageParam,\n value,\n };\n });\n\n return runtime.runPromise(program).then(\n ({ key, pageParam, value }) => {\n setEntries((current) =>\n upsertInfiniteEntry(current, {\n key,\n pageParam,\n data: value,\n }),\n );\n setIsFetchingNextPage(false);\n return value;\n },\n (cause: unknown) => {\n setIsFetchingNextPage(false);\n const resolved = cause as QueryError<E>;\n setError(resolved);\n return runtime.runPromise(Effect.fail(resolved));\n },\n );\n }, [data, definition, getInput, resolveNextPageParam, run, runtime]);\n\n const refetch = useCallback((): Promise<readonly Output[]> => {\n const targets = pageParams.length === 0\n ? [initialPageParam]\n : pageParams;\n\n setError(undefined);\n\n const program = Effect.forEach(\n targets,\n (pageParam) => {\n const input = getInput(pageParam);\n return Effect.gen(function* () {\n const value = yield* data.fetch(definition, input, {\n ...run,\n forceRefresh: true,\n });\n const snapshot = yield* data.getSnapshot(definition, input);\n return {\n key: snapshot.key,\n pageParam,\n data: value,\n } satisfies InfiniteQueryEntry<Output, PageParam>;\n });\n },\n {\n concurrency: 1,\n discard: false,\n },\n );\n\n return runtime.runPromise(program).then(\n (fetchedEntries) => {\n setEntries(fetchedEntries);\n return fetchedEntries.map((entry) => entry.data);\n },\n (cause: unknown) => {\n const resolved = cause as QueryError<E>;\n setError(resolved);\n return runtime.runPromise(Effect.fail(resolved));\n },\n );\n }, [data, definition, getInput, initialPageParam, pageParams, run, runtime]);\n\n const invalidate = useCallback((): Promise<void> => {\n const targets = pageParams.length === 0\n ? [initialPageParam]\n : pageParams;\n\n const program = Effect.forEach(\n targets,\n (pageParam) => data.invalidate(definition, getInput(pageParam)),\n {\n concurrency: 1,\n discard: true,\n },\n );\n\n return runtime.runPromise(program).then(\n () => {\n setEntries([]);\n setError(undefined);\n setIsFetchingNextPage(false);\n return undefined;\n },\n (cause: unknown) => {\n const resolved = cause as QueryError<E>;\n setError(resolved);\n return runtime.runPromise(Effect.fail(resolved));\n },\n );\n }, [data, definition, getInput, initialPageParam, pageParams, runtime]);\n\n const resolvedError = error ??\n (initialQuery.phase === \"failure\" ? (initialQuery.error as QueryError<E>) : undefined);\n\n const phase: QueryPhase = resolvedError !== undefined\n ? \"failure\"\n : entries.length > 0\n ? \"success\"\n : initialQuery.phase;\n\n return {\n phase,\n pages,\n pageParams,\n error: resolvedError,\n hasNextPage: resolveNextPageParam() !== undefined,\n isFetchingNextPage,\n fetchNextPage,\n refetch,\n invalidate,\n };\n};\n"],"mappings":"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","names":["Effect","invalidate","fetchQuery","Effect","Effect","useCallback","useEffect","useMemo","useDataService","useMemo","useQuery","useSuspenseQuery","useCallback","useDataService","useEffect","useMemo","Effect","invalidate"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Data
|
|
3
|
+
} from "./chunk-C5JI7D7W.js";
|
|
4
|
+
import {
|
|
5
|
+
Navigation,
|
|
6
|
+
parseHref
|
|
7
|
+
} from "./chunk-O7XTA7H3.js";
|
|
8
|
+
import {
|
|
9
|
+
Boundary
|
|
10
|
+
} from "./chunk-YG22YP5K.js";
|
|
11
|
+
|
|
12
|
+
// src/render/hydration.ts
|
|
13
|
+
import { Effect, Schema } from "effect";
|
|
14
|
+
var QuerySnapshotSchema = Schema.Struct({
|
|
15
|
+
key: Schema.String,
|
|
16
|
+
phase: Schema.Union(
|
|
17
|
+
Schema.Literal("initial"),
|
|
18
|
+
Schema.Literal("loading"),
|
|
19
|
+
Schema.Literal("success"),
|
|
20
|
+
Schema.Literal("failure")
|
|
21
|
+
),
|
|
22
|
+
data: Schema.NullishOr(Schema.Unknown),
|
|
23
|
+
error: Schema.NullishOr(Schema.Unknown),
|
|
24
|
+
updatedAt: Schema.NullishOr(Schema.Number)
|
|
25
|
+
});
|
|
26
|
+
var HydrationStateSchema = Schema.Struct({
|
|
27
|
+
version: Schema.Literal(1),
|
|
28
|
+
data: Schema.Array(Schema.Tuple(Schema.String, QuerySnapshotSchema)),
|
|
29
|
+
navigationHref: Schema.String
|
|
30
|
+
});
|
|
31
|
+
var escapeForScript = (value) => value.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
32
|
+
var dehydrateAppState = () => Effect.gen(function* () {
|
|
33
|
+
const data = yield* Data;
|
|
34
|
+
const navigation = yield* Navigation;
|
|
35
|
+
const snapshots = yield* data.getAllSnapshots;
|
|
36
|
+
const navigationSnapshot = yield* navigation.getSnapshot;
|
|
37
|
+
return {
|
|
38
|
+
version: 1,
|
|
39
|
+
data: Array.from(snapshots.entries()),
|
|
40
|
+
navigationHref: navigationSnapshot.href
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
var createHydrationScript = (state, globalName = "__effectReactHydration") => {
|
|
44
|
+
const serialized = JSON.stringify(state);
|
|
45
|
+
return `window[${JSON.stringify(globalName)}]=JSON.parse(${JSON.stringify(escapeForScript(serialized))});`;
|
|
46
|
+
};
|
|
47
|
+
var hydrateAppState = (payload) => Effect.gen(function* () {
|
|
48
|
+
const boundary = yield* Boundary;
|
|
49
|
+
const data = yield* Data;
|
|
50
|
+
const navigation = yield* Navigation;
|
|
51
|
+
const decoded = yield* boundary.decodeUnknown({
|
|
52
|
+
source: "hydration:payload",
|
|
53
|
+
schema: HydrationStateSchema,
|
|
54
|
+
value: payload
|
|
55
|
+
});
|
|
56
|
+
const mapped = new Map(decoded.data);
|
|
57
|
+
yield* data.hydrateSnapshots(mapped);
|
|
58
|
+
const current = yield* navigation.getSnapshot;
|
|
59
|
+
const parsed = parseHref(decoded.navigationHref);
|
|
60
|
+
yield* navigation.hydrateSnapshot({
|
|
61
|
+
...current,
|
|
62
|
+
pathname: parsed.pathname,
|
|
63
|
+
searchText: parsed.searchText,
|
|
64
|
+
href: decoded.navigationHref,
|
|
65
|
+
status: "success",
|
|
66
|
+
match: null,
|
|
67
|
+
loaders: {},
|
|
68
|
+
error: void 0
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
dehydrateAppState,
|
|
74
|
+
createHydrationScript,
|
|
75
|
+
hydrateAppState
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=chunk-IVIYY6S5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/render/hydration.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport { Boundary } from \"../boundary\";\nimport { Data } from \"../data/service\";\nimport type { QuerySnapshot } from \"../data/types\";\nimport { Navigation } from \"../navigation/service\";\nimport { parseHref } from \"../navigation/matcher\";\n\nexport interface HydrationState {\n readonly version: 1;\n readonly data: readonly (readonly [string, QuerySnapshot<unknown, unknown>])[];\n readonly navigationHref: string;\n}\n\nconst QuerySnapshotSchema = Schema.Struct({\n key: Schema.String,\n phase: Schema.Union(\n Schema.Literal(\"initial\"),\n Schema.Literal(\"loading\"),\n Schema.Literal(\"success\"),\n Schema.Literal(\"failure\"),\n ),\n data: Schema.NullishOr(Schema.Unknown),\n error: Schema.NullishOr(Schema.Unknown),\n updatedAt: Schema.NullishOr(Schema.Number),\n});\n\nexport const HydrationStateSchema = Schema.Struct({\n version: Schema.Literal(1),\n data: Schema.Array(Schema.Tuple(Schema.String, QuerySnapshotSchema)),\n navigationHref: Schema.String,\n});\n\nconst escapeForScript = (value: string): string =>\n value\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n\nexport const dehydrateAppState = (): Effect.Effect<HydrationState, never, Data | Navigation> =>\n Effect.gen(function* () {\n const data = yield* Data;\n const navigation = yield* Navigation;\n\n const snapshots = yield* data.getAllSnapshots;\n const navigationSnapshot = yield* navigation.getSnapshot;\n\n return {\n version: 1,\n data: Array.from(snapshots.entries()),\n navigationHref: navigationSnapshot.href,\n } satisfies HydrationState;\n });\n\nexport const createHydrationScript = (\n state: HydrationState,\n globalName = \"__effectReactHydration\",\n): string => {\n const serialized = JSON.stringify(state);\n return `window[${JSON.stringify(globalName)}]=JSON.parse(${JSON.stringify(escapeForScript(serialized))});`;\n};\n\nexport const hydrateAppState = (\n payload: unknown,\n): Effect.Effect<void, unknown, Boundary | Data | Navigation> =>\n Effect.gen(function* () {\n const boundary = yield* Boundary;\n const data = yield* Data;\n const navigation = yield* Navigation;\n\n const decoded = yield* boundary.decodeUnknown({\n source: \"hydration:payload\",\n schema: HydrationStateSchema,\n value: payload,\n });\n\n const mapped = new Map<string, QuerySnapshot<unknown, unknown>>(decoded.data);\n yield* data.hydrateSnapshots(mapped);\n\n const current = yield* navigation.getSnapshot;\n const parsed = parseHref(decoded.navigationHref);\n\n yield* navigation.hydrateSnapshot({\n ...current,\n pathname: parsed.pathname,\n searchText: parsed.searchText,\n href: decoded.navigationHref,\n status: \"success\",\n match: null,\n loaders: {},\n error: undefined,\n });\n });\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,QAAQ,cAAc;AAa/B,IAAM,sBAAsB,OAAO,OAAO;AAAA,EACxC,KAAK,OAAO;AAAA,EACZ,OAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,SAAS;AAAA,IACxB,OAAO,QAAQ,SAAS;AAAA,IACxB,OAAO,QAAQ,SAAS;AAAA,IACxB,OAAO,QAAQ,SAAS;AAAA,EAC1B;AAAA,EACA,MAAM,OAAO,UAAU,OAAO,OAAO;AAAA,EACrC,OAAO,OAAO,UAAU,OAAO,OAAO;AAAA,EACtC,WAAW,OAAO,UAAU,OAAO,MAAM;AAC3C,CAAC;AAEM,IAAM,uBAAuB,OAAO,OAAO;AAAA,EAChD,SAAS,OAAO,QAAQ,CAAC;AAAA,EACzB,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,QAAQ,mBAAmB,CAAC;AAAA,EACnE,gBAAgB,OAAO;AACzB,CAAC;AAED,IAAM,kBAAkB,CAAC,UACvB,MACG,QAAQ,MAAM,SAAS,EACvB,QAAQ,MAAM,SAAS,EACvB,QAAQ,WAAW,SAAS,EAC5B,QAAQ,WAAW,SAAS;AAE1B,IAAM,oBAAoB,MAC/B,OAAO,IAAI,aAAa;AACtB,QAAM,OAAO,OAAO;AACpB,QAAM,aAAa,OAAO;AAE1B,QAAM,YAAY,OAAO,KAAK;AAC9B,QAAM,qBAAqB,OAAO,WAAW;AAE7C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,MAAM,KAAK,UAAU,QAAQ,CAAC;AAAA,IACpC,gBAAgB,mBAAmB;AAAA,EACrC;AACF,CAAC;AAEI,IAAM,wBAAwB,CACnC,OACA,aAAa,6BACF;AACX,QAAM,aAAa,KAAK,UAAU,KAAK;AACvC,SAAO,UAAU,KAAK,UAAU,UAAU,CAAC,gBAAgB,KAAK,UAAU,gBAAgB,UAAU,CAAC,CAAC;AACxG;AAEO,IAAM,kBAAkB,CAC7B,YAEA,OAAO,IAAI,aAAa;AACtB,QAAM,WAAW,OAAO;AACxB,QAAM,OAAO,OAAO;AACpB,QAAM,aAAa,OAAO;AAE1B,QAAM,UAAU,OAAO,SAAS,cAAc;AAAA,IAC5C,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,EACT,CAAC;AAED,QAAM,SAAS,IAAI,IAA6C,QAAQ,IAAI;AAC5E,SAAO,KAAK,iBAAiB,MAAM;AAEnC,QAAM,UAAU,OAAO,WAAW;AAClC,QAAM,SAAS,UAAU,QAAQ,cAAc;AAE/C,SAAO,WAAW,gBAAgB;AAAA,IAChC,GAAG;AAAA,IACH,UAAU,OAAO;AAAA,IACjB,YAAY,OAAO;AAAA,IACnB,MAAM,QAAQ;AAAA,IACd,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS,CAAC;AAAA,IACV,OAAO;AAAA,EACT,CAAC;AACH,CAAC;","names":[]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// src/realtime/channel.ts
|
|
2
|
+
import { Effect, PubSub, Stream } from "effect";
|
|
3
|
+
var createChannel = (options = {}) => Effect.map(PubSub.unbounded(options), (pubsub) => {
|
|
4
|
+
const subscribe2 = () => Stream.fromPubSub(pubsub);
|
|
5
|
+
return {
|
|
6
|
+
publish: (message) => PubSub.publish(pubsub, message).pipe(Effect.asVoid),
|
|
7
|
+
publishAll: (messages) => PubSub.publishAll(pubsub, messages).pipe(Effect.asVoid),
|
|
8
|
+
subscribe: subscribe2,
|
|
9
|
+
stream: subscribe2(),
|
|
10
|
+
shutdown: PubSub.shutdown(pubsub)
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
var publish = (channel, message) => channel.publish(message);
|
|
14
|
+
var publishAll = (channel, messages) => channel.publishAll(messages);
|
|
15
|
+
var subscribe = (channel) => channel.subscribe();
|
|
16
|
+
|
|
17
|
+
// src/realtime/presence.ts
|
|
18
|
+
import { Effect as Effect2, Ref, Stream as Stream2 } from "effect";
|
|
19
|
+
var cloneMembers = (members) => new Map(members);
|
|
20
|
+
var applyPresenceEvent = (members, event) => {
|
|
21
|
+
const next = new Map(members);
|
|
22
|
+
if (event._tag === "join") {
|
|
23
|
+
next.set(event.memberId, event.member);
|
|
24
|
+
} else {
|
|
25
|
+
next.delete(event.memberId);
|
|
26
|
+
}
|
|
27
|
+
return next;
|
|
28
|
+
};
|
|
29
|
+
var createPresence = (options) => Effect2.gen(function* () {
|
|
30
|
+
const channel = yield* createChannel();
|
|
31
|
+
const membersRef = yield* Ref.make(/* @__PURE__ */ new Map());
|
|
32
|
+
const getMembers = Ref.get(membersRef).pipe(
|
|
33
|
+
Effect2.map((members2) => cloneMembers(members2))
|
|
34
|
+
);
|
|
35
|
+
const events = subscribe(channel);
|
|
36
|
+
const members = Stream2.flatMap(
|
|
37
|
+
Stream2.fromEffect(getMembers),
|
|
38
|
+
(initialMembers) => events.pipe(
|
|
39
|
+
Stream2.scan(
|
|
40
|
+
initialMembers,
|
|
41
|
+
(current, event) => applyPresenceEvent(current, event)
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
const join = (member) => {
|
|
46
|
+
const memberId = options.identify(member);
|
|
47
|
+
const event = {
|
|
48
|
+
_tag: "join",
|
|
49
|
+
memberId,
|
|
50
|
+
member,
|
|
51
|
+
timestamp: Date.now()
|
|
52
|
+
};
|
|
53
|
+
return Ref.update(membersRef, (current) => {
|
|
54
|
+
const next = new Map(current);
|
|
55
|
+
next.set(memberId, member);
|
|
56
|
+
return next;
|
|
57
|
+
}).pipe(Effect2.zipRight(publish(channel, event)));
|
|
58
|
+
};
|
|
59
|
+
const leave = (memberId) => {
|
|
60
|
+
const event = {
|
|
61
|
+
_tag: "leave",
|
|
62
|
+
memberId,
|
|
63
|
+
timestamp: Date.now()
|
|
64
|
+
};
|
|
65
|
+
return Ref.update(membersRef, (current) => {
|
|
66
|
+
const next = new Map(current);
|
|
67
|
+
next.delete(memberId);
|
|
68
|
+
return next;
|
|
69
|
+
}).pipe(Effect2.zipRight(publish(channel, event)));
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
events,
|
|
73
|
+
members,
|
|
74
|
+
getMembers,
|
|
75
|
+
join,
|
|
76
|
+
leave
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
createChannel,
|
|
82
|
+
publish,
|
|
83
|
+
publishAll,
|
|
84
|
+
subscribe,
|
|
85
|
+
createPresence
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=chunk-JKN75OYC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/realtime/channel.ts","../src/realtime/presence.ts"],"sourcesContent":["import { Effect, PubSub, Stream } from \"effect\";\n\nexport interface CreateChannelOptions {\n readonly replay?: number;\n}\n\nexport interface RealtimeChannel<Message> {\n readonly publish: (message: Message) => Effect.Effect<void>;\n readonly publishAll: (messages: Iterable<Message>) => Effect.Effect<void>;\n readonly subscribe: () => Stream.Stream<Message>;\n readonly stream: Stream.Stream<Message>;\n readonly shutdown: Effect.Effect<void>;\n}\n\nexport const createChannel = <Message>(\n options: CreateChannelOptions = {},\n): Effect.Effect<RealtimeChannel<Message>> =>\n Effect.map(PubSub.unbounded<Message>(options), (pubsub) => {\n const subscribe = (): Stream.Stream<Message> => Stream.fromPubSub(pubsub);\n\n return {\n publish: (message) => PubSub.publish(pubsub, message).pipe(Effect.asVoid),\n publishAll: (messages) => PubSub.publishAll(pubsub, messages).pipe(Effect.asVoid),\n subscribe,\n stream: subscribe(),\n shutdown: PubSub.shutdown(pubsub),\n };\n });\n\nexport const publish = <Message>(\n channel: RealtimeChannel<Message>,\n message: Message,\n): Effect.Effect<void> => channel.publish(message);\n\nexport const publishAll = <Message>(\n channel: RealtimeChannel<Message>,\n messages: Iterable<Message>,\n): Effect.Effect<void> => channel.publishAll(messages);\n\nexport const subscribe = <Message>(channel: RealtimeChannel<Message>): Stream.Stream<Message> =>\n channel.subscribe();\n","import { Effect, Ref, Stream } from \"effect\";\nimport { createChannel, publish, subscribe } from \"./channel\";\n\nexport type PresenceEvent<MemberId extends string, Member> =\n | {\n readonly _tag: \"join\";\n readonly memberId: MemberId;\n readonly member: Member;\n readonly timestamp: number;\n }\n | {\n readonly _tag: \"leave\";\n readonly memberId: MemberId;\n readonly timestamp: number;\n };\n\nexport interface CreatePresenceOptions<MemberId extends string, Member> {\n readonly identify: (member: Member) => MemberId;\n}\n\nexport interface Presence<MemberId extends string, Member> {\n readonly events: Stream.Stream<PresenceEvent<MemberId, Member>>;\n readonly members: Stream.Stream<ReadonlyMap<MemberId, Member>>;\n readonly getMembers: Effect.Effect<ReadonlyMap<MemberId, Member>>;\n readonly join: (member: Member) => Effect.Effect<void>;\n readonly leave: (memberId: MemberId) => Effect.Effect<void>;\n}\n\nconst cloneMembers = <MemberId extends string, Member>(\n members: ReadonlyMap<MemberId, Member>,\n): ReadonlyMap<MemberId, Member> => new Map(members);\n\nconst applyPresenceEvent = <MemberId extends string, Member>(\n members: ReadonlyMap<MemberId, Member>,\n event: PresenceEvent<MemberId, Member>,\n): ReadonlyMap<MemberId, Member> => {\n const next = new Map(members);\n if (event._tag === \"join\") {\n next.set(event.memberId, event.member);\n } else {\n next.delete(event.memberId);\n }\n return next;\n};\n\nexport const createPresence = <MemberId extends string, Member>(\n options: CreatePresenceOptions<MemberId, Member>,\n): Effect.Effect<Presence<MemberId, Member>> =>\n Effect.gen(function* () {\n const channel = yield* createChannel<PresenceEvent<MemberId, Member>>();\n const membersRef = yield* Ref.make(new Map<MemberId, Member>());\n\n const getMembers: Effect.Effect<ReadonlyMap<MemberId, Member>> = Ref.get(membersRef).pipe(\n Effect.map((members) => cloneMembers(members)),\n );\n\n const events = subscribe(channel);\n\n const members = Stream.flatMap(\n Stream.fromEffect(getMembers),\n (initialMembers) =>\n events.pipe(\n Stream.scan(initialMembers, (current, event) =>\n applyPresenceEvent(current, event),\n ),\n ),\n );\n\n const join = (member: Member): Effect.Effect<void> => {\n const memberId = options.identify(member);\n const event: PresenceEvent<MemberId, Member> = {\n _tag: \"join\",\n memberId,\n member,\n timestamp: Date.now(),\n };\n\n return Ref.update(membersRef, (current) => {\n const next = new Map(current);\n next.set(memberId, member);\n return next;\n }).pipe(Effect.zipRight(publish(channel, event)));\n };\n\n const leave = (memberId: MemberId): Effect.Effect<void> => {\n const event: PresenceEvent<MemberId, Member> = {\n _tag: \"leave\",\n memberId,\n timestamp: Date.now(),\n };\n\n return Ref.update(membersRef, (current) => {\n const next = new Map(current);\n next.delete(memberId);\n return next;\n }).pipe(Effect.zipRight(publish(channel, event)));\n };\n\n return {\n events,\n members,\n getMembers,\n join,\n leave,\n };\n });\n"],"mappings":";AAAA,SAAS,QAAQ,QAAQ,cAAc;AAchC,IAAM,gBAAgB,CAC3B,UAAgC,CAAC,MAEjC,OAAO,IAAI,OAAO,UAAmB,OAAO,GAAG,CAAC,WAAW;AACzD,QAAMA,aAAY,MAA8B,OAAO,WAAW,MAAM;AAExE,SAAO;AAAA,IACL,SAAS,CAAC,YAAY,OAAO,QAAQ,QAAQ,OAAO,EAAE,KAAK,OAAO,MAAM;AAAA,IACxE,YAAY,CAAC,aAAa,OAAO,WAAW,QAAQ,QAAQ,EAAE,KAAK,OAAO,MAAM;AAAA,IAChF,WAAAA;AAAA,IACA,QAAQA,WAAU;AAAA,IAClB,UAAU,OAAO,SAAS,MAAM;AAAA,EAClC;AACF,CAAC;AAEI,IAAM,UAAU,CACrB,SACA,YACwB,QAAQ,QAAQ,OAAO;AAE1C,IAAM,aAAa,CACxB,SACA,aACwB,QAAQ,WAAW,QAAQ;AAE9C,IAAM,YAAY,CAAU,YACjC,QAAQ,UAAU;;;ACxCpB,SAAS,UAAAC,SAAQ,KAAK,UAAAC,eAAc;AA4BpC,IAAM,eAAe,CACnB,YACkC,IAAI,IAAI,OAAO;AAEnD,IAAM,qBAAqB,CACzB,SACA,UACkC;AAClC,QAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,MAAI,MAAM,SAAS,QAAQ;AACzB,SAAK,IAAI,MAAM,UAAU,MAAM,MAAM;AAAA,EACvC,OAAO;AACL,SAAK,OAAO,MAAM,QAAQ;AAAA,EAC5B;AACA,SAAO;AACT;AAEO,IAAM,iBAAiB,CAC5B,YAEAC,QAAO,IAAI,aAAa;AACtB,QAAM,UAAU,OAAO,cAA+C;AACtE,QAAM,aAAa,OAAO,IAAI,KAAK,oBAAI,IAAsB,CAAC;AAE9D,QAAM,aAA2D,IAAI,IAAI,UAAU,EAAE;AAAA,IACnFA,QAAO,IAAI,CAACC,aAAY,aAAaA,QAAO,CAAC;AAAA,EAC/C;AAEA,QAAM,SAAS,UAAU,OAAO;AAEhC,QAAM,UAAUC,QAAO;AAAA,IACrBA,QAAO,WAAW,UAAU;AAAA,IAC5B,CAAC,mBACC,OAAO;AAAA,MACLA,QAAO;AAAA,QAAK;AAAA,QAAgB,CAAC,SAAS,UACpC,mBAAmB,SAAS,KAAK;AAAA,MACnC;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,OAAO,CAAC,WAAwC;AACpD,UAAM,WAAW,QAAQ,SAAS,MAAM;AACxC,UAAM,QAAyC;AAAA,MAC7C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB;AAEA,WAAO,IAAI,OAAO,YAAY,CAAC,YAAY;AACzC,YAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,WAAK,IAAI,UAAU,MAAM;AACzB,aAAO;AAAA,IACT,CAAC,EAAE,KAAKF,QAAO,SAAS,QAAQ,SAAS,KAAK,CAAC,CAAC;AAAA,EAClD;AAEA,QAAM,QAAQ,CAAC,aAA4C;AACzD,UAAM,QAAyC;AAAA,MAC7C,MAAM;AAAA,MACN;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB;AAEA,WAAO,IAAI,OAAO,YAAY,CAAC,YAAY;AACzC,YAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,WAAK,OAAO,QAAQ;AACpB,aAAO;AAAA,IACT,CAAC,EAAE,KAAKA,QAAO,SAAS,QAAQ,SAAS,KAAK,CAAC,CAAC;AAAA,EAClD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF,CAAC;","names":["subscribe","Effect","Stream","Effect","members","Stream"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hydrateAppState
|
|
3
|
+
} from "./chunk-IVIYY6S5.js";
|
|
4
|
+
|
|
5
|
+
// src/client/index.ts
|
|
6
|
+
import { Effect } from "effect";
|
|
7
|
+
var defaultHydrationGlobalName = "__effectReactHydration";
|
|
8
|
+
var readGlobalHydrationPayload = (globalName) => {
|
|
9
|
+
const globalScope = globalThis;
|
|
10
|
+
return globalScope[globalName];
|
|
11
|
+
};
|
|
12
|
+
var hydrateApp = (options) => {
|
|
13
|
+
const payload = options.payload ?? readGlobalHydrationPayload(options.globalName ?? defaultHydrationGlobalName);
|
|
14
|
+
if (payload === void 0) {
|
|
15
|
+
return options.app.runtime.runPromise(Effect.void);
|
|
16
|
+
}
|
|
17
|
+
return options.app.runtime.runPromise(hydrateAppState(payload));
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
defaultHydrationGlobalName,
|
|
22
|
+
hydrateApp
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=chunk-M2CJG6T7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/index.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport type { EffectReactApp } from \"../framework\";\nimport { hydrateAppState } from \"../render\";\n\nexport interface HydrateAppOptions {\n readonly app: EffectReactApp;\n readonly payload?: unknown;\n readonly globalName?: string;\n}\n\nexport const defaultHydrationGlobalName = \"__effectReactHydration\";\n\nconst readGlobalHydrationPayload = (globalName: string): unknown => {\n const globalScope = globalThis as Record<string, unknown>;\n return globalScope[globalName];\n};\n\nexport const hydrateApp = (options: HydrateAppOptions): Promise<void> => {\n const payload =\n options.payload ??\n readGlobalHydrationPayload(options.globalName ?? defaultHydrationGlobalName);\n\n if (payload === undefined) {\n return options.app.runtime.runPromise(Effect.void);\n }\n\n return options.app.runtime.runPromise(hydrateAppState(payload));\n};\n"],"mappings":";;;;;AAAA,SAAS,cAAc;AAUhB,IAAM,6BAA6B;AAE1C,IAAM,6BAA6B,CAAC,eAAgC;AAClE,QAAM,cAAc;AACpB,SAAO,YAAY,UAAU;AAC/B;AAEO,IAAM,aAAa,CAAC,YAA8C;AACvE,QAAM,UACJ,QAAQ,WACR,2BAA2B,QAAQ,cAAc,0BAA0B;AAE7E,MAAI,YAAY,QAAW;AACzB,WAAO,QAAQ,IAAI,QAAQ,WAAW,OAAO,IAAI;AAAA,EACnD;AAEA,SAAO,QAAQ,IAAI,QAAQ,WAAW,gBAAgB,OAAO,CAAC;AAChE;","names":[]}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// src/grid/grid.ts
|
|
2
|
+
import { Array as EffectArray, Order, pipe } from "effect";
|
|
3
|
+
var normalizeInteger = (value, minimum) => {
|
|
4
|
+
if (!Number.isFinite(value)) {
|
|
5
|
+
return minimum;
|
|
6
|
+
}
|
|
7
|
+
return Math.max(minimum, Math.floor(value));
|
|
8
|
+
};
|
|
9
|
+
var toComparable = (value) => {
|
|
10
|
+
if (value === null || value === void 0 || value instanceof Date) {
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
switch (typeof value) {
|
|
14
|
+
case "string":
|
|
15
|
+
case "number":
|
|
16
|
+
case "bigint":
|
|
17
|
+
case "boolean":
|
|
18
|
+
return value;
|
|
19
|
+
case "symbol":
|
|
20
|
+
return value.description ?? "symbol";
|
|
21
|
+
case "function":
|
|
22
|
+
return value.name.length > 0 ? `[function ${value.name}]` : "[function]";
|
|
23
|
+
default:
|
|
24
|
+
try {
|
|
25
|
+
const encoded = JSON.stringify(value);
|
|
26
|
+
return encoded ?? "";
|
|
27
|
+
} catch {
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var compareComparable = (left, right) => {
|
|
33
|
+
if (left === right) {
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
if (left === null || left === void 0) {
|
|
37
|
+
return right === null || right === void 0 ? 0 : -1;
|
|
38
|
+
}
|
|
39
|
+
if (right === null || right === void 0) {
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
if (left instanceof Date && right instanceof Date) {
|
|
43
|
+
return Order.Date(left, right);
|
|
44
|
+
}
|
|
45
|
+
if (typeof left === "number" && typeof right === "number") {
|
|
46
|
+
return Order.number(left, right);
|
|
47
|
+
}
|
|
48
|
+
if (typeof left === "bigint" && typeof right === "bigint") {
|
|
49
|
+
return Order.bigint(left, right);
|
|
50
|
+
}
|
|
51
|
+
if (typeof left === "boolean" && typeof right === "boolean") {
|
|
52
|
+
return Order.boolean(left, right);
|
|
53
|
+
}
|
|
54
|
+
return Order.string(toSearchText(left), toSearchText(right));
|
|
55
|
+
};
|
|
56
|
+
var comparableOrder = Order.make(compareComparable);
|
|
57
|
+
var toSearchText = (value) => {
|
|
58
|
+
if (value === null || value === void 0) {
|
|
59
|
+
return "";
|
|
60
|
+
}
|
|
61
|
+
if (value instanceof Date) {
|
|
62
|
+
return value.toISOString();
|
|
63
|
+
}
|
|
64
|
+
switch (typeof value) {
|
|
65
|
+
case "string":
|
|
66
|
+
return value;
|
|
67
|
+
case "number":
|
|
68
|
+
case "bigint":
|
|
69
|
+
case "boolean":
|
|
70
|
+
return value.toString();
|
|
71
|
+
case "symbol":
|
|
72
|
+
return value.description ?? "symbol";
|
|
73
|
+
case "function":
|
|
74
|
+
return value.name.length > 0 ? value.name : "function";
|
|
75
|
+
default:
|
|
76
|
+
try {
|
|
77
|
+
const encoded = JSON.stringify(value);
|
|
78
|
+
return encoded ?? "";
|
|
79
|
+
} catch {
|
|
80
|
+
return "";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var defaultFilterMatch = (value, filterValue) => {
|
|
85
|
+
if (filterValue === null || filterValue === void 0) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
if (typeof filterValue === "string") {
|
|
89
|
+
const normalizedFilter = filterValue.trim().toLowerCase();
|
|
90
|
+
if (normalizedFilter.length === 0) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return toSearchText(value).toLowerCase().includes(normalizedFilter);
|
|
94
|
+
}
|
|
95
|
+
if (Array.isArray(filterValue)) {
|
|
96
|
+
return filterValue.some((candidate) => Object.is(candidate, value));
|
|
97
|
+
}
|
|
98
|
+
if (filterValue instanceof Date && value instanceof Date) {
|
|
99
|
+
return filterValue.getTime() === value.getTime();
|
|
100
|
+
}
|
|
101
|
+
return Object.is(value, filterValue);
|
|
102
|
+
};
|
|
103
|
+
var toSortDirection = (direction) => direction === "desc" ? "desc" : "asc";
|
|
104
|
+
var defineColumns = (columns) => columns;
|
|
105
|
+
var projectRow = (row, columns) => {
|
|
106
|
+
const projection = {};
|
|
107
|
+
for (const column of columns) {
|
|
108
|
+
projection[column.id] = column.accessor(row);
|
|
109
|
+
}
|
|
110
|
+
return projection;
|
|
111
|
+
};
|
|
112
|
+
var projectRows = (rows, columns) => pipe(
|
|
113
|
+
rows,
|
|
114
|
+
EffectArray.fromIterable,
|
|
115
|
+
EffectArray.map((row) => projectRow(row, columns))
|
|
116
|
+
);
|
|
117
|
+
var mapRows = projectRows;
|
|
118
|
+
var sortRows = (rows, columns, sorts) => {
|
|
119
|
+
const input = EffectArray.fromIterable(rows);
|
|
120
|
+
if (input.length < 2 || sorts.length === 0) {
|
|
121
|
+
return input;
|
|
122
|
+
}
|
|
123
|
+
const columnLookup = /* @__PURE__ */ new Map();
|
|
124
|
+
for (const column of columns) {
|
|
125
|
+
columnLookup.set(column.id, column);
|
|
126
|
+
}
|
|
127
|
+
const orders = [];
|
|
128
|
+
for (const sort of sorts) {
|
|
129
|
+
const column = columnLookup.get(sort.id);
|
|
130
|
+
if (column === void 0) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const orderForColumn = Order.mapInput(
|
|
134
|
+
comparableOrder,
|
|
135
|
+
(row) => toComparable(column.accessor(row))
|
|
136
|
+
);
|
|
137
|
+
orders.push(toSortDirection(sort.direction) === "desc" ? Order.reverse(orderForColumn) : orderForColumn);
|
|
138
|
+
}
|
|
139
|
+
if (orders.length === 0) {
|
|
140
|
+
return input;
|
|
141
|
+
}
|
|
142
|
+
const combinedOrder = Order.combineAll(orders);
|
|
143
|
+
const indexedOrder = Order.combine(
|
|
144
|
+
Order.mapInput(combinedOrder, (entry) => entry.row),
|
|
145
|
+
Order.mapInput(Order.number, (entry) => entry.index)
|
|
146
|
+
);
|
|
147
|
+
return pipe(
|
|
148
|
+
input,
|
|
149
|
+
EffectArray.map((row, index) => ({ row, index })),
|
|
150
|
+
EffectArray.sort(indexedOrder),
|
|
151
|
+
EffectArray.map((entry) => entry.row)
|
|
152
|
+
);
|
|
153
|
+
};
|
|
154
|
+
var filterRows = (rows, columns, filters) => {
|
|
155
|
+
const input = EffectArray.fromIterable(rows);
|
|
156
|
+
if (filters.length === 0) {
|
|
157
|
+
return input;
|
|
158
|
+
}
|
|
159
|
+
const columnLookup = /* @__PURE__ */ new Map();
|
|
160
|
+
for (const column of columns) {
|
|
161
|
+
columnLookup.set(column.id, column);
|
|
162
|
+
}
|
|
163
|
+
return pipe(
|
|
164
|
+
input,
|
|
165
|
+
EffectArray.filter(
|
|
166
|
+
(row) => filters.every((filter) => {
|
|
167
|
+
const column = columnLookup.get(filter.id);
|
|
168
|
+
if (column === void 0) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return defaultFilterMatch(column.accessor(row), filter.value);
|
|
172
|
+
})
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
var paginateRows = (rows, pagination) => {
|
|
177
|
+
const input = EffectArray.fromIterable(rows);
|
|
178
|
+
const pageSize = normalizeInteger(pagination.pageSize, 1);
|
|
179
|
+
const pageCount = input.length === 0 ? 0 : Math.ceil(input.length / pageSize);
|
|
180
|
+
const requestedPageIndex = normalizeInteger(pagination.pageIndex, 0);
|
|
181
|
+
const pageIndex = pageCount === 0 ? 0 : Math.min(requestedPageIndex, pageCount - 1);
|
|
182
|
+
const pageOffset = pageIndex * pageSize;
|
|
183
|
+
const pageRows = pipe(
|
|
184
|
+
input,
|
|
185
|
+
EffectArray.drop(pageOffset),
|
|
186
|
+
EffectArray.take(pageSize)
|
|
187
|
+
);
|
|
188
|
+
return {
|
|
189
|
+
rows: pageRows,
|
|
190
|
+
pageIndex,
|
|
191
|
+
pageSize,
|
|
192
|
+
pageCount,
|
|
193
|
+
totalRows: input.length
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export {
|
|
198
|
+
defineColumns,
|
|
199
|
+
projectRow,
|
|
200
|
+
projectRows,
|
|
201
|
+
mapRows,
|
|
202
|
+
sortRows,
|
|
203
|
+
filterRows,
|
|
204
|
+
paginateRows
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=chunk-MDGEGQZB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/grid/grid.ts"],"sourcesContent":["import { Array as EffectArray, Order, pipe } from \"effect\";\nimport type {\n GridColumn,\n GridColumnId,\n GridFilter,\n GridPage,\n GridPagination,\n GridRowProjection,\n GridSort,\n GridSortDirection,\n} from \"./types\";\n\ntype GridComparable = string | number | bigint | boolean | Date | null | undefined;\n\nconst normalizeInteger = (value: number, minimum: number): number => {\n if (!Number.isFinite(value)) {\n return minimum;\n }\n return Math.max(minimum, Math.floor(value));\n};\n\nconst toComparable = (value: unknown): GridComparable => {\n if (value === null || value === undefined || value instanceof Date) {\n return value;\n }\n\n switch (typeof value) {\n case \"string\":\n case \"number\":\n case \"bigint\":\n case \"boolean\":\n return value;\n case \"symbol\":\n return value.description ?? \"symbol\";\n case \"function\":\n return value.name.length > 0 ? `[function ${value.name}]` : \"[function]\";\n default:\n try {\n const encoded = JSON.stringify(value);\n return encoded ?? \"\";\n } catch {\n return \"\";\n }\n }\n};\n\nconst compareComparable = (left: GridComparable, right: GridComparable): -1 | 0 | 1 => {\n if (left === right) {\n return 0;\n }\n\n if (left === null || left === undefined) {\n return right === null || right === undefined ? 0 : -1;\n }\n\n if (right === null || right === undefined) {\n return 1;\n }\n\n if (left instanceof Date && right instanceof Date) {\n return Order.Date(left, right);\n }\n\n if (typeof left === \"number\" && typeof right === \"number\") {\n return Order.number(left, right);\n }\n\n if (typeof left === \"bigint\" && typeof right === \"bigint\") {\n return Order.bigint(left, right);\n }\n\n if (typeof left === \"boolean\" && typeof right === \"boolean\") {\n return Order.boolean(left, right);\n }\n\n return Order.string(toSearchText(left), toSearchText(right));\n};\n\nconst comparableOrder: Order.Order<GridComparable> = Order.make(compareComparable);\n\nconst toSearchText = (value: unknown): string => {\n if (value === null || value === undefined) {\n return \"\";\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n switch (typeof value) {\n case \"string\":\n return value;\n case \"number\":\n case \"bigint\":\n case \"boolean\":\n return value.toString();\n case \"symbol\":\n return value.description ?? \"symbol\";\n case \"function\":\n return value.name.length > 0 ? value.name : \"function\";\n default:\n try {\n const encoded = JSON.stringify(value);\n return encoded ?? \"\";\n } catch {\n return \"\";\n }\n }\n};\n\nconst defaultFilterMatch = (value: unknown, filterValue: unknown): boolean => {\n if (filterValue === null || filterValue === undefined) {\n return true;\n }\n\n if (typeof filterValue === \"string\") {\n const normalizedFilter = filterValue.trim().toLowerCase();\n if (normalizedFilter.length === 0) {\n return true;\n }\n return toSearchText(value).toLowerCase().includes(normalizedFilter);\n }\n\n if (Array.isArray(filterValue)) {\n return filterValue.some((candidate) => Object.is(candidate, value));\n }\n\n if (filterValue instanceof Date && value instanceof Date) {\n return filterValue.getTime() === value.getTime();\n }\n\n return Object.is(value, filterValue);\n};\n\nconst toSortDirection = (direction: GridSortDirection | undefined): GridSortDirection =>\n direction === \"desc\" ? \"desc\" : \"asc\";\n\nexport const defineColumns = <\n Row,\n const Columns extends readonly GridColumn<Row, string, unknown>[] = readonly GridColumn<\n Row,\n string,\n unknown\n >[],\n>(\n columns: Columns,\n): Columns => columns;\n\nexport const projectRow = <Row, const Columns extends readonly GridColumn<Row, string, unknown>[]>(\n row: Row,\n columns: Columns,\n): GridRowProjection<Columns> => {\n const projection: Record<string, unknown> = {};\n\n for (const column of columns) {\n projection[column.id] = column.accessor(row);\n }\n\n return projection as GridRowProjection<Columns>;\n};\n\nexport const projectRows = <Row, const Columns extends readonly GridColumn<Row, string, unknown>[]>(\n rows: readonly Row[],\n columns: Columns,\n): readonly GridRowProjection<Columns>[] =>\n pipe(\n rows,\n EffectArray.fromIterable,\n EffectArray.map((row) => projectRow(row, columns)),\n );\n\nexport const mapRows = projectRows;\n\nexport const sortRows = <Row, const Columns extends readonly GridColumn<Row, string, unknown>[]>(\n rows: readonly Row[],\n columns: Columns,\n sorts: readonly GridSort<GridColumnId<Columns>>[],\n): readonly Row[] => {\n const input = EffectArray.fromIterable(rows);\n\n if (input.length < 2 || sorts.length === 0) {\n return input;\n }\n\n const columnLookup = new Map<GridColumnId<Columns>, Columns[number]>();\n for (const column of columns) {\n columnLookup.set(column.id as GridColumnId<Columns>, column);\n }\n\n const orders: Order.Order<Row>[] = [];\n\n for (const sort of sorts) {\n const column = columnLookup.get(sort.id);\n if (column === undefined) {\n continue;\n }\n\n const orderForColumn = Order.mapInput(comparableOrder, (row: Row) =>\n toComparable(column.accessor(row)),\n );\n\n orders.push(toSortDirection(sort.direction) === \"desc\" ? Order.reverse(orderForColumn) : orderForColumn);\n }\n\n if (orders.length === 0) {\n return input;\n }\n\n const combinedOrder = Order.combineAll(orders);\n\n type IndexedRow = {\n readonly row: Row;\n readonly index: number;\n };\n\n const indexedOrder = Order.combine(\n Order.mapInput(combinedOrder, (entry: IndexedRow) => entry.row),\n Order.mapInput(Order.number, (entry: IndexedRow) => entry.index),\n );\n\n return pipe(\n input,\n EffectArray.map((row, index): IndexedRow => ({ row, index })),\n EffectArray.sort(indexedOrder),\n EffectArray.map((entry) => entry.row),\n );\n};\n\nexport const filterRows = <Row, const Columns extends readonly GridColumn<Row, string, unknown>[]>(\n rows: readonly Row[],\n columns: Columns,\n filters: readonly GridFilter<GridColumnId<Columns>>[],\n): readonly Row[] => {\n const input = EffectArray.fromIterable(rows);\n\n if (filters.length === 0) {\n return input;\n }\n\n const columnLookup = new Map<GridColumnId<Columns>, Columns[number]>();\n for (const column of columns) {\n columnLookup.set(column.id as GridColumnId<Columns>, column);\n }\n\n return pipe(\n input,\n EffectArray.filter((row) =>\n filters.every((filter) => {\n const column = columnLookup.get(filter.id);\n if (column === undefined) {\n return true;\n }\n return defaultFilterMatch(column.accessor(row), filter.value);\n }),\n ),\n );\n};\n\nexport const paginateRows = <Row>(\n rows: readonly Row[],\n pagination: GridPagination,\n): GridPage<Row> => {\n const input = EffectArray.fromIterable(rows);\n const pageSize = normalizeInteger(pagination.pageSize, 1);\n const pageCount = input.length === 0 ? 0 : Math.ceil(input.length / pageSize);\n const requestedPageIndex = normalizeInteger(pagination.pageIndex, 0);\n const pageIndex = pageCount === 0 ? 0 : Math.min(requestedPageIndex, pageCount - 1);\n const pageOffset = pageIndex * pageSize;\n\n const pageRows = pipe(\n input,\n EffectArray.drop(pageOffset),\n EffectArray.take(pageSize),\n );\n\n return {\n rows: pageRows,\n pageIndex,\n pageSize,\n pageCount,\n totalRows: input.length,\n };\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useEffectRuntime
|
|
3
|
+
} from "./chunk-2GIUCKL2.js";
|
|
4
|
+
|
|
5
|
+
// src/state/service.ts
|
|
6
|
+
import { Context, Effect, Layer, Stream, SubscriptionRef } from "effect";
|
|
7
|
+
var defaultEquality = (left, right) => Object.is(left, right);
|
|
8
|
+
var createStore = (initial) => Effect.map(SubscriptionRef.make(initial), (ref) => ({ ref }));
|
|
9
|
+
var createStoreFromEffect = (initial) => Effect.flatMap(initial, createStore);
|
|
10
|
+
var createStoreTag = (key) => Context.GenericTag(key);
|
|
11
|
+
var makeStoreLayer = (tag, initial) => Layer.effect(tag, createStore(initial));
|
|
12
|
+
var makeStoreLayerFromEffect = (tag, initial) => Layer.effect(tag, createStoreFromEffect(initial));
|
|
13
|
+
var get = (store) => SubscriptionRef.get(store.ref);
|
|
14
|
+
var set = (store, value) => SubscriptionRef.set(store.ref, value);
|
|
15
|
+
var update = (store, mutate) => SubscriptionRef.update(store.ref, mutate);
|
|
16
|
+
var modify = (store, mutate) => SubscriptionRef.modify(store.ref, mutate);
|
|
17
|
+
var select = (store, selector) => Effect.map(get(store), selector);
|
|
18
|
+
var changes = (store) => store.ref.changes;
|
|
19
|
+
var selectChanges = (store, selector, options = {}) => {
|
|
20
|
+
const selected = changes(store).pipe(Stream.map(selector));
|
|
21
|
+
if (options.distinct === false) {
|
|
22
|
+
return selected;
|
|
23
|
+
}
|
|
24
|
+
return selected.pipe(Stream.changesWith(options.equals ?? defaultEquality));
|
|
25
|
+
};
|
|
26
|
+
var derive = (store, selector, options = {}) => ({
|
|
27
|
+
get: select(store, selector),
|
|
28
|
+
changes: selectChanges(store, selector, options)
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// src/state/react.tsx
|
|
32
|
+
import { Effect as Effect2, Fiber, Stream as Stream2 } from "effect";
|
|
33
|
+
import { useCallback, useSyncExternalStore } from "react";
|
|
34
|
+
var defaultEquality2 = (left, right) => Object.is(left, right);
|
|
35
|
+
var useStore = (store) => useStoreSelector(store, (state) => state);
|
|
36
|
+
var useStoreSelector = (store, selector, equals = defaultEquality2) => {
|
|
37
|
+
const runtime = useEffectRuntime();
|
|
38
|
+
const subscribe = useCallback(
|
|
39
|
+
(listener) => {
|
|
40
|
+
const fiber = runtime.runFork(
|
|
41
|
+
Stream2.runForEach(
|
|
42
|
+
selectChanges(store, selector, {
|
|
43
|
+
equals
|
|
44
|
+
}),
|
|
45
|
+
() => Effect2.sync(listener)
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
return () => {
|
|
49
|
+
runtime.runFork(Fiber.interrupt(fiber));
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
[equals, runtime, selector, store]
|
|
53
|
+
);
|
|
54
|
+
const getSnapshot = useCallback(
|
|
55
|
+
() => runtime.runSync(select(store, selector)),
|
|
56
|
+
[runtime, selector, store]
|
|
57
|
+
);
|
|
58
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
createStore,
|
|
63
|
+
createStoreFromEffect,
|
|
64
|
+
createStoreTag,
|
|
65
|
+
makeStoreLayer,
|
|
66
|
+
makeStoreLayerFromEffect,
|
|
67
|
+
get,
|
|
68
|
+
set,
|
|
69
|
+
update,
|
|
70
|
+
modify,
|
|
71
|
+
select,
|
|
72
|
+
changes,
|
|
73
|
+
selectChanges,
|
|
74
|
+
derive,
|
|
75
|
+
useStore,
|
|
76
|
+
useStoreSelector
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=chunk-NI2GNZ7S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/state/service.ts","../src/state/react.tsx"],"sourcesContent":["import { Context, Effect, Layer, Stream, SubscriptionRef } from \"effect\";\n\nexport type Selector<State, Selected> = (state: State) => Selected;\nexport type Equality<Selected> = (left: Selected, right: Selected) => boolean;\n\nconst defaultEquality = <Value>(left: Value, right: Value): boolean => Object.is(left, right);\n\nexport interface Store<State> {\n readonly ref: SubscriptionRef.SubscriptionRef<State>;\n}\n\nexport interface DerivedStore<Selected> {\n readonly get: Effect.Effect<Selected>;\n readonly changes: Stream.Stream<Selected>;\n}\n\nexport interface SelectChangesOptions<Selected> {\n readonly equals?: Equality<Selected>;\n readonly distinct?: boolean;\n}\n\nexport type StoreTag<State> = Context.Tag<Store<State>, Store<State>>;\n\nexport const createStore = <State>(initial: State): Effect.Effect<Store<State>, never, never> =>\n Effect.map(SubscriptionRef.make(initial), (ref) => ({ ref }));\n\nexport const createStoreFromEffect = <State, E, R>(\n initial: Effect.Effect<State, E, R>,\n): Effect.Effect<Store<State>, E, R> =>\n Effect.flatMap(initial, createStore);\n\nexport const createStoreTag = <State>(key: string): StoreTag<State> =>\n Context.GenericTag<Store<State>>(key);\n\nexport const makeStoreLayer = <State>(\n tag: StoreTag<State>,\n initial: State,\n): Layer.Layer<Store<State>, never, never> =>\n Layer.effect(tag, createStore(initial));\n\nexport const makeStoreLayerFromEffect = <State, E, R>(\n tag: StoreTag<State>,\n initial: Effect.Effect<State, E, R>,\n): Layer.Layer<Store<State>, E, R> =>\n Layer.effect(tag, createStoreFromEffect(initial));\n\nexport const get = <State>(store: Store<State>): Effect.Effect<State, never, never> =>\n SubscriptionRef.get(store.ref);\n\nexport const set = <State>(\n store: Store<State>,\n value: State,\n): Effect.Effect<void, never, never> =>\n SubscriptionRef.set(store.ref, value);\n\nexport const update = <State>(\n store: Store<State>,\n mutate: (state: State) => State,\n): Effect.Effect<void, never, never> =>\n SubscriptionRef.update(store.ref, mutate);\n\nexport const modify = <State, Result>(\n store: Store<State>,\n mutate: (state: State) => readonly [Result, State],\n): Effect.Effect<Result, never, never> =>\n SubscriptionRef.modify(store.ref, mutate);\n\nexport const select = <State, Selected>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n): Effect.Effect<Selected, never, never> =>\n Effect.map(get(store), selector);\n\nexport const changes = <State>(store: Store<State>): Stream.Stream<State, never, never> =>\n store.ref.changes;\n\nexport const selectChanges = <State, Selected>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n options: SelectChangesOptions<Selected> = {},\n): Stream.Stream<Selected, never, never> => {\n const selected = changes(store).pipe(Stream.map(selector));\n if (options.distinct === false) {\n return selected;\n }\n return selected.pipe(Stream.changesWith(options.equals ?? defaultEquality<Selected>));\n};\n\nexport const derive = <State, Selected>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n options: SelectChangesOptions<Selected> = {},\n): DerivedStore<Selected> => ({\n get: select(store, selector),\n changes: selectChanges(store, selector, options),\n});\n\n","import { Effect, Fiber, Stream } from \"effect\";\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport { useEffectRuntime } from \"../react/provider\";\nimport { type Equality, select, selectChanges, type Selector, type Store } from \"./service\";\n\nconst defaultEquality = <Value,>(left: Value, right: Value): boolean => Object.is(left, right);\n\nexport const useStore = <State,>(store: Store<State>): State =>\n useStoreSelector(store, (state) => state);\n\nexport const useStoreSelector = <State, Selected,>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n equals: Equality<Selected> = defaultEquality,\n): Selected => {\n const runtime = useEffectRuntime();\n\n const subscribe = useCallback(\n (listener: () => void) => {\n const fiber = runtime.runFork(\n Stream.runForEach(\n selectChanges(store, selector, {\n equals,\n }),\n () => Effect.sync(listener),\n ),\n );\n\n return () => {\n runtime.runFork(Fiber.interrupt(fiber));\n };\n },\n [equals, runtime, selector, store],\n );\n\n const getSnapshot = useCallback(\n () => runtime.runSync(select(store, selector)),\n [runtime, selector, store],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n};\n"],"mappings":";;;;;AAAA,SAAS,SAAS,QAAQ,OAAO,QAAQ,uBAAuB;AAKhE,IAAM,kBAAkB,CAAQ,MAAa,UAA0B,OAAO,GAAG,MAAM,KAAK;AAkBrF,IAAM,cAAc,CAAQ,YACjC,OAAO,IAAI,gBAAgB,KAAK,OAAO,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE;AAEvD,IAAM,wBAAwB,CACnC,YAEA,OAAO,QAAQ,SAAS,WAAW;AAE9B,IAAM,iBAAiB,CAAQ,QACpC,QAAQ,WAAyB,GAAG;AAE/B,IAAM,iBAAiB,CAC5B,KACA,YAEA,MAAM,OAAO,KAAK,YAAY,OAAO,CAAC;AAEjC,IAAM,2BAA2B,CACtC,KACA,YAEA,MAAM,OAAO,KAAK,sBAAsB,OAAO,CAAC;AAE3C,IAAM,MAAM,CAAQ,UACzB,gBAAgB,IAAI,MAAM,GAAG;AAExB,IAAM,MAAM,CACjB,OACA,UAEA,gBAAgB,IAAI,MAAM,KAAK,KAAK;AAE/B,IAAM,SAAS,CACpB,OACA,WAEA,gBAAgB,OAAO,MAAM,KAAK,MAAM;AAEnC,IAAM,SAAS,CACpB,OACA,WAEA,gBAAgB,OAAO,MAAM,KAAK,MAAM;AAEnC,IAAM,SAAS,CACpB,OACA,aAEA,OAAO,IAAI,IAAI,KAAK,GAAG,QAAQ;AAE1B,IAAM,UAAU,CAAQ,UAC7B,MAAM,IAAI;AAEL,IAAM,gBAAgB,CAC3B,OACA,UACA,UAA0C,CAAC,MACD;AAC1C,QAAM,WAAW,QAAQ,KAAK,EAAE,KAAK,OAAO,IAAI,QAAQ,CAAC;AACzD,MAAI,QAAQ,aAAa,OAAO;AAC9B,WAAO;AAAA,EACT;AACA,SAAO,SAAS,KAAK,OAAO,YAAY,QAAQ,UAAU,eAAyB,CAAC;AACtF;AAEO,IAAM,SAAS,CACpB,OACA,UACA,UAA0C,CAAC,OACf;AAAA,EAC5B,KAAK,OAAO,OAAO,QAAQ;AAAA,EAC3B,SAAS,cAAc,OAAO,UAAU,OAAO;AACjD;;;AC/FA,SAAS,UAAAA,SAAQ,OAAO,UAAAC,eAAc;AACtC,SAAS,aAAa,4BAA4B;AAIlD,IAAMC,mBAAkB,CAAS,MAAa,UAA0B,OAAO,GAAG,MAAM,KAAK;AAEtF,IAAM,WAAW,CAAS,UAC/B,iBAAiB,OAAO,CAAC,UAAU,KAAK;AAEnC,IAAM,mBAAmB,CAC9B,OACA,UACA,SAA6BA,qBAChB;AACb,QAAM,UAAU,iBAAiB;AAEjC,QAAM,YAAY;AAAA,IAChB,CAAC,aAAyB;AACxB,YAAM,QAAQ,QAAQ;AAAA,QACpBC,QAAO;AAAA,UACL,cAAc,OAAO,UAAU;AAAA,YAC7B;AAAA,UACF,CAAC;AAAA,UACD,MAAMC,QAAO,KAAK,QAAQ;AAAA,QAC5B;AAAA,MACF;AAEA,aAAO,MAAM;AACX,gBAAQ,QAAQ,MAAM,UAAU,KAAK,CAAC;AAAA,MACxC;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,SAAS,UAAU,KAAK;AAAA,EACnC;AAEA,QAAM,cAAc;AAAA,IAClB,MAAM,QAAQ,QAAQ,OAAO,OAAO,QAAQ,CAAC;AAAA,IAC7C,CAAC,SAAS,UAAU,KAAK;AAAA,EAC3B;AAEA,SAAO,qBAAqB,WAAW,aAAa,WAAW;AACjE;","names":["Effect","Stream","defaultEquality","Stream","Effect"]}
|