| 57 | * @since 4.0.0 |
| 58 | */ |
| 59 | export const dehydrate = ( |
| 60 | registry: AtomRegistry.AtomRegistry, |
| 61 | options?: { |
| 62 | /** |
| 63 | * How to encode `AsyncResult.Initial` values. Default is "ignore". |
| 64 | */ |
| 65 | readonly encodeInitialAs?: "ignore" | "promise" | "value-only" | undefined |
| 66 | } |
| 67 | ): Array<DehydratedAtom> => { |
| 68 | const encodeInitialResultMode = options?.encodeInitialAs ?? "ignore" |
| 69 | const arr: Array<DehydratedAtomValue> = [] |
| 70 | const now = Date.now() |
| 71 | registry.getNodes().forEach((node, key) => { |
| 72 | if (!Atom.isSerializable(node.atom)) return |
| 73 | const atom = node.atom |
| 74 | const value = node.value() |
| 75 | const isInitial = AsyncResult.isAsyncResult(value) && AsyncResult.isInitial(value) |
| 76 | if (encodeInitialResultMode === "ignore" && isInitial) return |
| 77 | const encodedValue = atom[Atom.SerializableTypeId].encode(value) |
| 78 | |
| 79 | // Create a promise that resolves when the atom moves out of Initial state |
| 80 | let resultPromise: Promise<unknown> | undefined |
| 81 | if (encodeInitialResultMode === "promise" && isInitial) { |
| 82 | resultPromise = new Promise((resolve) => { |
| 83 | const unsubscribe = registry.subscribe(atom, (newValue) => { |
| 84 | if (AsyncResult.isAsyncResult(newValue) && !AsyncResult.isInitial(newValue)) { |
| 85 | resolve(atom[Atom.SerializableTypeId].encode(newValue)) |
| 86 | unsubscribe() |
| 87 | } |
| 88 | }) |
| 89 | }) |
| 90 | } |
| 91 | |
| 92 | arr.push({ |
| 93 | "~effect/reactivity/DehydratedAtom": true, |
| 94 | key: key as string, |
| 95 | value: encodedValue, |
| 96 | dehydratedAt: now, |
| 97 | resultPromise |
| 98 | }) |
| 99 | }) |
| 100 | return arr as any |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * Returns dehydrated state entries as `DehydratedAtomValue` records. |