Skip to content

Instantly share code, notes, and snippets.

@ksaldana1
Last active October 4, 2024 16:27
Show Gist options
  • Save ksaldana1/41179d791651f808e048ceab89dafe66 to your computer and use it in GitHub Desktop.
Save ksaldana1/41179d791651f808e048ceab89dafe66 to your computer and use it in GitHub Desktop.
Layer Composition - Effect.ts
import { Context, Effect, Layer, pipe } from "effect";
class Config extends Context.Tag("Config")<
Config,
{
readonly getConfig: Effect.Effect<{
readonly logLevel: string;
readonly connection: string;
}>;
}
>() {}
class Logger extends Context.Tag("Logger")<
Logger,
{ readonly log: (message: string) => Effect.Effect<void> }
>() {}
class Database extends Context.Tag("Database")<
Database,
{ readonly query: (sql: string) => Effect.Effect<{ result: string }> }
>() {}
const ConfigLive = Layer.succeed(
Config,
Config.of({
getConfig: Effect.succeed({
logLevel: "INFO",
connection: "mysql://username:password@hostname:port/database_name",
}),
})
);
const ConfigTest = Layer.succeed(
Config,
Config.of({
getConfig: Effect.succeed({
logLevel: "DEBUG",
connection: ":memory",
}),
})
);
const LoggerImpl = Layer.effect(
Logger,
Effect.gen(function* () {
const config = yield* Config;
return {
log: (message) =>
Effect.gen(function* () {
const { logLevel } = yield* config.getConfig;
console.log(`[${logLevel}] ${message}`);
}),
};
})
);
const LoggerLive = Layer.provide(LoggerImpl, ConfigLive);
const LoggerTest = Layer.provide(LoggerImpl, ConfigTest);
const DatabaseConfigLive = Layer.provideMerge(LoggerLive, ConfigLive);
const DatabaseConfigTest = Layer.provideMerge(LoggerTest, ConfigTest);
const DBImpl = Layer.effect(
Database,
Effect.gen(function* () {
const config = yield* Config;
const logger = yield* Logger;
return {
query: (sql: string) =>
Effect.gen(function* () {
yield* logger.log(`Executing query: ${sql}`);
const { connection } = yield* config.getConfig;
return { result: `Results from ${connection}` };
}),
};
})
);
const DatabaseLive = Layer.provide(DBImpl, DatabaseConfigLive);
const DatabaseTest = Layer.provide(DBImpl, DatabaseConfigTest);
const program = Effect.gen(function* () {
const logger = yield* Logger;
const config = yield* Config;
const { connection } = yield* config.getConfig;
yield* logger.log(`Querying db at connection: ${connection}`);
const db = yield* Database;
const result = yield* db.query("test query");
return result;
});
const ProgramLive = Layer.mergeAll(ConfigLive, LoggerLive, DatabaseLive);
const { result } = await Effect.runPromise(
program.pipe(Effect.provide(ProgramLive))
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment