Skip to content

Commit

Permalink
fix: Fix Ether's bug on removing self symbol (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikuroXina authored May 26, 2024
1 parent 5ef32da commit 5ff7fb6
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 41 deletions.
35 changes: 25 additions & 10 deletions src/ether.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,39 @@ Deno.test("deps on Promise", async () => {
}),
);

type PrivateRepository = {
fetch: () => Promise<unknown>;
};
const privateRepositorySymbol = newEtherSymbol<PrivateRepository>();
const privateRepository = newEther(privateRepositorySymbol, () => ({
fetch: () => Promise.resolve({ flag: "YOU_ARE_AN_IDIOT" }),
}));

type PrivateFetcher = {
fetch: (token: string) => Promise<unknown>;
};
const privateFetcherSymbol = newEtherSymbol<PrivateFetcher>();
const privateFetcher = newEther(privateFetcherSymbol, ({ verifier }) => ({
fetch: async (token) => {
if (!(await verifier.verify(token))) {
throw new Error("token verification failure");
}
return { flag: "YOU_ARE_AN_IDIOT" };
const privateFetcher = newEther(
privateFetcherSymbol,
({ verifier, repo }) => ({
fetch: async (token) => {
if (!(await verifier.verify(token))) {
throw new Error("token verification failure");
}
return repo.fetch();
},
}),
{
verifier: tokenVerifierSymbol,
repo: privateRepositorySymbol,
},
}), {
verifier: tokenVerifierSymbol,
});
);

const composePromise = composeT(monad);
const composed = await cat(liftEther(monad)(privateFetcher))
const liftPromise = liftEther(monad);
const composed = await cat(liftPromise(privateFetcher))
.feed(composePromise(tokenVerifier))
.feed(composePromise(liftPromise(privateRepository)))
.feed(runEtherT).value;

assertEquals(await composed.fetch("foo"), { flag: "YOU_ARE_AN_IDIOT" });
Expand Down
66 changes: 35 additions & 31 deletions src/ether.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,27 @@ export const composeT =
const targetKeys = Object.entries(upper.depSymbols).filter(([, sym]) =>
sym === lower.selfSymbol
).map(([key]) => key);
const composedHandler = (deps: EtherDeps<OmitType<E, T> & D>) =>
doT(monad).addM("resolved", lower.handler(deps))
.addMWith("ret", ({ resolved }) => {
const depsForUpper: Record<string, unknown> = {
...deps,
};
for (const targetKey of targetKeys) {
depsForUpper[targetKey] = resolved;
}
return upper.handler(depsForUpper as EtherDeps<E>);
}).finish(({ ret }) => ret);
const symbolsDeletedSelf = Object.fromEntries(
Object.entries({ ...upper.depSymbols, ...lower.depSymbols })
.filter(
([, depSym]) => depSym !== lower.selfSymbol,
),
);
return {
selfSymbol: upper.selfSymbol,
handler: (deps) =>
doT(monad).addM("resolved", lower.handler(deps))
.addMWith("ret", ({ resolved }) => {
const depsForUpper: Record<string, unknown> = {
...deps,
};
for (const targetKey of targetKeys) {
depsForUpper[targetKey] = resolved;
}
return upper.handler(depsForUpper as EtherDeps<E>);
}).finish(({ ret }) => ret),
depSymbols: Object.fromEntries(
Object.entries({ ...upper.depSymbols, ...lower.depSymbols })
.filter(
([, depSym]) => depSym === lower.selfSymbol,
),
) as OmitType<E, T> & D,
handler: composedHandler,
depSymbols: symbolsDeletedSelf as OmitType<E, T> & D,
};
};

Expand Down Expand Up @@ -185,22 +187,24 @@ export const compose =
const targetKeys = Object.entries(upper.depSymbols).filter(([, sym]) =>
sym === lower.selfSymbol
).map(([key]) => key);
const composedHandler = (deps: EtherDeps<OmitType<E, T> & D>) => {
const resolved = lower.handler(deps);
const depsForUpper: Record<string, unknown> = { ...deps };
for (const targetKey of targetKeys) {
depsForUpper[targetKey] = resolved;
}
return upper.handler(depsForUpper as EtherDeps<E>);
};
const symbolsDeletedSelf = Object.fromEntries(
Object.entries({ ...upper.depSymbols, ...lower.depSymbols })
.filter(
([, depSym]) => depSym !== lower.selfSymbol,
),
);
return {
selfSymbol: upper.selfSymbol,
handler: (deps) => {
const resolved = lower.handler(deps);
const depsForUpper: Record<string, unknown> = { ...deps };
for (const targetKey of targetKeys) {
depsForUpper[targetKey] = resolved;
}
return upper.handler(depsForUpper as EtherDeps<E>);
},
depSymbols: Object.fromEntries(
Object.entries({ ...upper.depSymbols, ...lower.depSymbols })
.filter(
([, depSym]) => depSym === lower.selfSymbol,
),
) as OmitType<E, T> & D,
handler: composedHandler,
depSymbols: symbolsDeletedSelf as OmitType<E, T> & D,
};
};

Expand Down

0 comments on commit 5ff7fb6

Please sign in to comment.