|
| 1 | +// deno-lint-ignore-file no-explicit-any |
| 2 | +import type { Operation } from "effection"; |
| 3 | +import type { Handle, Inspector, Methods, Protocol } from "./types.ts"; |
| 4 | + |
| 5 | +export interface Combine { |
| 6 | + protocols<A extends Methods>(protocols: [Protocol<A>]): Protocol<A>; |
| 7 | + protocols<A extends Methods, B extends Methods>( |
| 8 | + protocols: [Protocol<A>, Protocol<B>], |
| 9 | + ): Protocol<A & B>; |
| 10 | + protocols<A extends Methods, B extends Methods, C extends Methods>( |
| 11 | + protocols: [Protocol<A>, Protocol<B>, Protocol<C>], |
| 12 | + ): Protocol<A & B & C>; |
| 13 | + protocols< |
| 14 | + A extends Methods, |
| 15 | + B extends Methods, |
| 16 | + C extends Methods, |
| 17 | + D extends Methods, |
| 18 | + >( |
| 19 | + protocols: [Protocol<A>, Protocol<B>, Protocol<C>, Protocol<D>], |
| 20 | + ): Protocol<A & B & C & D>; |
| 21 | + |
| 22 | + inspectors<A extends Methods>(inspectors: [Inspector<A>]): Inspector<A>; |
| 23 | + inspectors<A extends Methods, B extends Methods>( |
| 24 | + inspectors: [Inspector<A>, Inspector<B>], |
| 25 | + ): Inspector<A & B>; |
| 26 | + inspectors<A extends Methods, B extends Methods, C extends Methods>( |
| 27 | + inspectors: [Inspector<A>, Inspector<B>, Inspector<C>], |
| 28 | + ): Inspector<A & B & C>; |
| 29 | + inspectors< |
| 30 | + A extends Methods, |
| 31 | + B extends Methods, |
| 32 | + C extends Methods, |
| 33 | + D extends Methods, |
| 34 | + >( |
| 35 | + inspectors: [Inspector<A>, Inspector<B>, Inspector<C>, Inspector<D>], |
| 36 | + ): Inspector<A & B & C & D>; |
| 37 | +} |
| 38 | + |
| 39 | +export const combine: Combine = { |
| 40 | + protocols: (...protocols: any[]) => { |
| 41 | + return protocols.reduce((acc, protocol) => { |
| 42 | + Object.assign(acc.methods, protocol.methods); |
| 43 | + return acc; |
| 44 | + }, { methods: {} }) as Protocol<Methods>; |
| 45 | + }, |
| 46 | + inspectors: (...inspectors: any[]) => { |
| 47 | + return inspectors.reduce( |
| 48 | + (acc: Inspector<Methods>, inspector: Inspector<Methods>) => { |
| 49 | + let protocol = combine.protocols([acc.protocol, inspector.protocol]); |
| 50 | + let attach = function* (): Operation<Handle<Methods>> { |
| 51 | + let a = yield* acc.attach(); |
| 52 | + let b = yield* inspector.attach(); |
| 53 | + let methods = Object.assign(a.methods, b.methods); |
| 54 | + return { |
| 55 | + protocol, |
| 56 | + methods, |
| 57 | + invoke: ({ name, args }) => methods[name](...args), |
| 58 | + }; |
| 59 | + }; |
| 60 | + return { protocol, attach }; |
| 61 | + }, |
| 62 | + ); |
| 63 | + }, |
| 64 | +}; |
0 commit comments