StreamClass.resource<S, U>(start: () => S | PromiseLike<S>,next: (state: S) => Promise<readonly [U, S | null] | null>
| readonly [U, S | null]
| null,after: (state: S) => void | PromiseLike<void>): StreamClass<Exclude<U, AnyFailure>, Extract<U, AnyFailure>>
unfold with lifecycle hooks — Elixir's Stream.resource/3: start runs on first
pull, next is unfold's step, and after ALWAYS runs — normal end, early take, or a
throw. (Plain generators already get this via try/finally; resource is for when
the setup/teardown pair deserves to be explicit.)
const opened: string[] = []; const rows = Stream.resource( () => (opened.push('open'), { cursor: 0 }), (db) => (db.cursor < 2 ? ([`row-${db.cursor}`, { cursor: db.cursor + 1 }] as const) : null), () => void opened.push('close'), ); await rows.collect(); // ['row-0', 'row-1'] — and opened is ['open', 'close']
StreamClass<Exclude<U, AnyFailure>, Extract<U, AnyFailure>>