Last active
October 4, 2024 16:27
-
-
Save ksaldana1/41179d791651f808e048ceab89dafe66 to your computer and use it in GitHub Desktop.
Layer Composition - Effect.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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