Setup Effect
Use this skill when a project should switch from a basic TypeScript scaffold to an Effect-first scaffold.
When To Use
- •The user asks to enable Effect in a non-Effect template.
- •
effectand@effect/language-serviceare not installed. - •
package.jsonandtsconfig.jsonare missing Effect language-service setup. - •
src/env.tsandsrc/index.tsneed Effect bootstrap scaffolding.
Prerequisites
- •Package manager is Bun.
- •
src/env.ts,src/index.ts,package.json, andtsconfig.jsonexist. - •The user approved dependency and config changes.
Setup Steps
- •Install dependencies.
bash
bun add effect @rayhanadev/env bun add -d @effect/language-service
- •Add prepare script to
package.json.
json
{
"scripts": {
"prepare": "effect-language-service patch"
}
}
- •Add language service plugin to
tsconfig.json.
json
{
"compilerOptions": {
"plugins": [{ "name": "@effect/language-service" }]
}
}
- •Replace
src/env.tswith the Effect env scaffold.
typescript
/* oxlint-disable */
import { Env, makeEnv } from "@rayhanadev/env";
export const AppEnv = makeEnv("AppEnv", {
nodeEnv: Env.stringOr("NODE_ENV", "development"),
appName: Env.stringOr("APP_NAME", "__PROJECT_NAME__"),
});
- •Replace
src/index.tswith the baseline Effect program scaffold.
typescript
import { Effect, Layer, Logger, Match } from "effect";
import { AppEnv } from "./env";
const program = Effect.gen(function* () {
/* user code */
});
const LoggerLayer = Effect.gen(function* () {
const env = yield* AppEnv;
return env.nodeEnv;
}).pipe(
Effect.andThen((nodeEnv) =>
Match.value(nodeEnv).pipe(
Match.when("development", () => Logger.pretty),
Match.when("production", () => Logger.json),
Match.when("test", () => Logger.pretty),
Match.orElseAbsurd,
),
),
Layer.unwrapEffect,
);
const AppLayer = Layer.mergeAll(AppEnv.Default, Layer.provide(LoggerLayer, AppEnv.Default));
const main = program.pipe(Effect.provide(AppLayer));
Effect.runSync(main);
Verification
bash
bun run typecheck bun run lint
If test harness is configured:
bash
bun run test bun run test:coverage