Simplifying Nested Generators in Effect for API Calls
I'm finding myself doing a lot of nesting of generators when I am trying to do call APIs based on results of other APIs, wondering if there is a more out of the box solution with Effect for this?
const page = yield* Effect.all(
_page.map((r) => {
return Effect.gen(function* () {
if (r.fileIds && r.fileIds.length > 0) {
const files = yield* Effect.all(
r.fileIds!.map((f) => {
return Effect.gen(function* () {
const file = yield* Effect.promise(() => ctx.db.get(f));
if (!file) {
return yield* new ConvexServerError({
message: "idk",
});
}
const { metadata, ...restFile } = file;
const fileURL = yield* Effect.promise(() =>
ctx.storage.getUrl(file.storageId),
);
if (metadata && restFile.type === "image") {
// ...
return {
// ...
};
}
return {
fileURL,
...restFile,
};
});
}),
);
return Effect.succeed({
...r,
files,
});
}
return Effect.succeed(r);
});
}),
);const page = yield* Effect.all(
_page.map((r) => {
return Effect.gen(function* () {
if (r.fileIds && r.fileIds.length > 0) {
const files = yield* Effect.all(
r.fileIds!.map((f) => {
return Effect.gen(function* () {
const file = yield* Effect.promise(() => ctx.db.get(f));
if (!file) {
return yield* new ConvexServerError({
message: "idk",
});
}
const { metadata, ...restFile } = file;
const fileURL = yield* Effect.promise(() =>
ctx.storage.getUrl(file.storageId),
);
if (metadata && restFile.type === "image") {
// ...
return {
// ...
};
}
return {
fileURL,
...restFile,
};
});
}),
);
return Effect.succeed({
...r,
files,
});
}
return Effect.succeed(r);
});
}),
);