(
fetched: T[],
current: readonly T[],
options: {
touched?: ReadonlySet<string>
retained?: ReadonlySet<string>
preserveUnfetched?: boolean | ((item: T) => boolean)
} = {},
)
| 99 | } |
| 100 | |
| 101 | function reconcileFetched<T extends { id: string }>( |
| 102 | fetched: T[], |
| 103 | current: readonly T[], |
| 104 | options: { |
| 105 | touched?: ReadonlySet<string> |
| 106 | retained?: ReadonlySet<string> |
| 107 | preserveUnfetched?: boolean | ((item: T) => boolean) |
| 108 | } = {}, |
| 109 | ) { |
| 110 | const result = new Map(fetched.map((item) => [item.id, item])) |
| 111 | const live = new Map(current.map((item) => [item.id, item])) |
| 112 | if (options.preserveUnfetched) { |
| 113 | for (const item of current) { |
| 114 | if (!result.has(item.id) && (options.preserveUnfetched === true || options.preserveUnfetched(item))) |
| 115 | result.set(item.id, item) |
| 116 | } |
| 117 | } |
| 118 | for (const id of options.retained ?? emptyIDs) { |
| 119 | if (result.has(id)) continue |
| 120 | const item = live.get(id) |
| 121 | if (item) result.set(id, item) |
| 122 | } |
| 123 | // Events observed while the request is pending are the freshest client state for those identities. |
| 124 | for (const id of options.touched ?? emptyIDs) { |
| 125 | const item = live.get(id) |
| 126 | if (item) result.set(id, item) |
| 127 | if (!item) result.delete(id) |
| 128 | } |
| 129 | return [...result.values()].sort((a, b) => cmp(a.id, b.id)) |
| 130 | } |
| 131 | |
| 132 | export function createServerSession(client: OpencodeClient, options?: { retry?: typeof retry }) { |
| 133 | const [data, setData] = createStore({ |
no test coverage detected