Skip to content

Commit

Permalink
update types for flavors
Browse files Browse the repository at this point in the history
  • Loading branch information
Ayc0 committed Oct 14, 2021
1 parent f5d453c commit 079cdb1
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 29 deletions.
11 changes: 11 additions & 0 deletions packages/manatea/__tests__/manatea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,15 @@ describe('Manatea', () => {
await cup(NaN);
expect(fn).not.toHaveBeenCalled();
});

it('should have flavors', async () => {
const cup = orderCup('0' as string, unflavored => parseInt(unflavored, 10));
const fn = jest.fn();
cup.on(tea => fn(tea));
expect(cup()).toBe(0);

await cup('1');
expect(cup()).toBe(1);
expect(fn).toHaveBeenCalledWith(1);
});
});
51 changes: 34 additions & 17 deletions packages/manatea/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,44 @@ export type Tea =
| Map<any, any>
| Set<any>;

type Handler<T extends Tea> = (tea: T, context: Context) => void;
type Handler<UnflavoredTea extends Tea> = (
tea: UnflavoredTea,
context: Context,
) => void;
export interface Server {
(): boolean;
listening: boolean;
}

type Order<T extends Tea> = ((tea: T) => T | Promise<T>) | T;
type Order<FlavoredTea extends Tea, UnflavoredTea extends Tea> =
| ((tea: FlavoredTea) => UnflavoredTea | Promise<UnflavoredTea>)
| UnflavoredTea;

export interface Cup<T extends Tea> {
(): T;
(order: Order<T>, context?: Context): Promise<T>;
on: (fn: Handler<T>) => Server;
export interface Cup<FlavoredTea extends Tea, UnflavoredTea extends Tea> {
(): FlavoredTea;
(
order: Order<FlavoredTea, UnflavoredTea>,
context?: Context,
): Promise<FlavoredTea>;
on: (fn: Handler<FlavoredTea>) => Server;
clear: () => void;
}

export type Context = WeakSet<Cup<any>>;
export type Context = WeakSet<Cup<any, any>>;

export function orderCup<T extends Tea>(
firstTea: T,
flavoring: (tea: T) => T = t => t,
): Cup<T> {
let handlers = new Set<Handler<T>>();
export function orderCup<
FlavoredTea extends Tea,
UnflavoredTea extends Tea = FlavoredTea
>(
firstTea: UnflavoredTea,
flavoring: (tea: UnflavoredTea) => FlavoredTea = t => t as any,
): Cup<FlavoredTea, UnflavoredTea> {
let handlers = new Set<Handler<FlavoredTea>>();
let flavoredTea = flavoring(firstTea);

let isPreviousCancelled = { cancelled: false };

const setTea = (teaRefill: T, context: Context) => {
const setTea = (teaRefill: UnflavoredTea, context: Context) => {
const flavoredTeaRefill = flavoring(teaRefill);
if (
flavoredTea === flavoredTeaRefill ||
Expand All @@ -58,9 +69,15 @@ export function orderCup<T extends Tea>(
});
};

function cup(): T;
function cup(order: Order<T>, context?: Context): Promise<T>;
function cup(order?: Order<T>, context: Context = new WeakSet()) {
function cup(): FlavoredTea;
function cup(
order: Order<FlavoredTea, UnflavoredTea>,
context?: Context,
): Promise<FlavoredTea>;
function cup(
order?: Order<FlavoredTea, UnflavoredTea>,
context: Context = new WeakSet(),
) {
if (arguments.length === 0) {
return flavoredTea;
}
Expand All @@ -76,7 +93,7 @@ export function orderCup<T extends Tea>(
});
}

cup.on = (fn: Handler<T>) => {
cup.on = (fn: Handler<FlavoredTea>) => {
handlers.add(fn);
const server = () => handlers.delete(fn);
Object.defineProperty(server, 'listening', {
Expand Down
19 changes: 19 additions & 0 deletions packages/react-manatea/__tests__/useInfuser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe('useInfuser', () => {

expect(result.current[0]).toBe(1);
});

it('should trigger updates', async () => {
const cup = orderCup<number>(0);

Expand All @@ -30,6 +31,7 @@ describe('useInfuser', () => {

expect(cup()).toBe(-1);
});

it('should avoid infinite loops', async () => {
const cup = orderCup<number>(0);

Expand All @@ -44,4 +46,21 @@ describe('useInfuser', () => {

expect(cup()).toBe(2);
});

it('should have flavors', async () => {
const cup = orderCup('0' as string, unflavored => parseInt(unflavored, 10));

const { result, waitForNextUpdate } = renderHook(() => useInfuser(cup));
expect(result.current[0]).toBe(0);

const fn = jest.fn();
cup.on(tea => fn(tea));

await act(async () => {
await result.current[1]('1');
});

expect(cup()).toBe(1);
expect(fn).toHaveBeenCalledWith(1);
});
});
16 changes: 11 additions & 5 deletions packages/react-manatea/src/Infuser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ import { Cup, Tea } from 'manatea';

import { useInfuser } from './useInfuser';

interface InfuserProps<T extends Tea> {
cup: Cup<T>;
children: (tea: T) => ReactNode;
interface InfuserProps<FlavoredTea extends Tea, UnflavoredTea extends Tea> {
cup: Cup<FlavoredTea, UnflavoredTea>;
children: (tea: FlavoredTea) => ReactNode;
}

export const Infuser = <T extends Tea>({ cup, children }: InfuserProps<T>) => {
const [tea] = useInfuser<T>(cup);
export const Infuser = <
FlavoredTea extends Tea,
UnflavoredTea extends Tea = FlavoredTea
>({
cup,
children,
}: InfuserProps<FlavoredTea, UnflavoredTea>) => {
const [tea] = useInfuser<FlavoredTea, UnflavoredTea>(cup);
return children(tea);
};
11 changes: 7 additions & 4 deletions packages/react-manatea/src/infuse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import { Cup, Tea } from 'manatea';

import { useInfuser } from './useInfuser';

export const infuse = <T extends Tea>(cup: Cup<T>) => (
component: React.ComponentType<any>,
) => {
export const infuse = <
FlavoredTea extends Tea,
UnflavoredTea extends Tea = FlavoredTea
>(
cup: Cup<FlavoredTea, UnflavoredTea>,
) => (component: React.ComponentType<any>) => {
const Consumer = (props: any) => {
const [tea] = useInfuser<T>(cup);
const [tea] = useInfuser<FlavoredTea, UnflavoredTea>(cup);

return React.createElement(component, {
...props,
Expand Down
14 changes: 11 additions & 3 deletions packages/react-manatea/src/useInfuser.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import * as React from 'react';
import { Cup, Tea, Server, Context } from 'manatea';

export const useInfuser = <T extends Tea>(cup: Cup<T>) => {
export const useInfuser = <
FlavoredTea extends Tea,
UnflavoredTea extends Tea = FlavoredTea
>(
cup: Cup<FlavoredTea, UnflavoredTea>,
) => {
const [tea, setTea] = React.useState(() => cup());

React.useEffect(() => {
const server: Server = cup.on((tea: T) => setTea(tea));
const server: Server = cup.on((tea: FlavoredTea) => setTea(tea));
setTea(cup());
return () => {
if (server.listening) {
Expand All @@ -14,5 +19,8 @@ export const useInfuser = <T extends Tea>(cup: Cup<T>) => {
};
}, [cup]);

return [tea, (tea: T, context?: Context) => cup(tea, context)] as const;
return [
tea,
(tea: UnflavoredTea, context?: Context) => cup(tea, context),
] as const;
};

0 comments on commit 079cdb1

Please sign in to comment.