
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
@clayroach/effect-unplugin
Advanced tools
Build-time AST transformer for Effect source location tracing
Build-time AST transformer for Effect source location tracing and automatic span instrumentation.
yield* expressions inside Effect.gen() to inject stack frame informationEffect.withSpan() for distributed tracingcode.filepath, code.lineno, code.column, code.function attributespnpm add -D @clayroach/effect-unplugin
// vite.config.ts
import { defineConfig } from 'vite'
import effectPlugin from '@clayroach/effect-unplugin/vite'
export default defineConfig({
plugins: [
effectPlugin({
sourceTrace: true,
spans: { enabled: true }
})
]
})
import effectPlugin from '@clayroach/effect-unplugin/esbuild'
import { build } from 'esbuild'
build({
plugins: [effectPlugin({ sourceTrace: true, spans: { enabled: true } })],
// ... other options
})
import effectPlugin from '@clayroach/effect-unplugin/webpack'
// or
import effectPlugin from '@clayroach/effect-unplugin/rollup'
effectPlugin({
// Enable source tracing for yield* expressions (default: true)
sourceTrace: true,
// Extract function names from yield* arguments (default: true)
extractFunctionName: true,
// File patterns to include (default: .js, .ts, .jsx, .tsx)
include: /\.[jt]sx?$/,
// File patterns to exclude (default: node_modules)
exclude: /node_modules/,
// Span instrumentation options
spans: {
enabled: true,
include: ["gen", "fork", "all", "forEach"],
nameFormat: "function" // "function" | "location" | "full"
}
})
Control how span names appear in traces:
"function" (default): Use function/variable names
effect.gen (fetchUser)
effect.all
effect.forEach (processItems)
**"location": Use file locations
effect.gen (index.ts:23)
effect.all (index.ts:49)
effect.forEach (index.ts:59)
**"full": Include both
effect.gen (fetchUser @ index.ts:23)
effect.all (index.ts:49)
effect.forEach (processItems @ index.ts:59)
All formats include full source location in span attributes (code.filepath, code.lineno, etc.)
Reduce overhead with fine-grained control over which Effect calls get instrumented.
Limit instrumentation by nesting depth:
spans: {
enabled: true,
strategy: {
type: "depth",
maxDepth: 2 // 0 = top-level only, 1 = one level deep, etc.
}
}
Per-combinator depth limits:
spans: {
enabled: true,
strategy: {
type: "depth",
perCombinator: {
fork: 0, // Only top-level forks
gen: 1, // Gen + one level deep
all: Infinity // No limit on Effect.all
}
}
}
Filter by file patterns and function names:
spans: {
enabled: true,
strategy: {
type: "overrides",
rules: {
// Only instrument forks in worker files
fork: {
files: "src/workers/**"
},
// Skip gen in tests and private functions
gen: {
excludeFiles: "**/*.test.ts",
excludeFunctions: "^_.*"
},
// Only instrument forEach in API handlers
forEach: {
files: ["src/api/**", "src/handlers/**"],
functions: "^handle.*"
}
}
}
}
Filter Options:
files: Glob patterns to include (single string or array)excludeFiles: Glob patterns to excludefunctions: Regex patterns for function names to includeexcludeFunctions: Regex patterns for function names to excludeOnly instrument top-level forks to avoid noisy background task traces:
spans: {
enabled: true,
strategy: {
type: "depth",
perCombinator: {
fork: 0,
forkDaemon: 0,
forkScoped: 0
}
}
}
Skip instrumentation in tests and development utilities:
spans: {
enabled: true,
strategy: {
type: "overrides",
rules: {
gen: {
excludeFiles: [
"**/*.test.ts",
"**/__tests__/**",
"src/dev/**"
]
}
}
}
}
Only instrument critical paths:
spans: {
enabled: true,
strategy: {
type: "overrides",
rules: {
gen: {
files: [
"src/api/**",
"src/workers/**",
"src/processors/**"
]
},
fork: {
files: "src/workers/**",
functions: "^(background|worker).*"
}
}
}
}
Transforms:
const fetchUser = (id: string) =>
Effect.gen(function* () {
yield* Console.log(`Fetching ${id}`)
return { id, name: `User ${id}` }
})
Into:
const _sf0 = { name: "log", stack: () => "index.ts:3:4", parent: undefined }
const fetchUser = (id: string) =>
Effect.gen(function* () {
yield* Effect.updateService(
Console.log(`Fetching ${id}`),
References.CurrentStackFrame,
(parent) => ({ ..._sf0, parent })
)
return { id, name: `User ${id}` }
})
Transforms:
const program = Effect.gen(function* () {
const users = yield* Effect.all([
fetchUser('alice'),
fetchUser('bob')
])
})
Into:
const program = Effect.withSpan(
Effect.gen(function* () {
const users = yield* Effect.withSpan(
Effect.all([fetchUser('alice'), fetchUser('bob')]),
"effect.all",
{
attributes: {
"code.filepath": "src/index.ts",
"code.lineno": 5,
"code.column": 23,
"code.function": "effect.all"
}
}
)
}),
"effect.gen (program)",
{
attributes: {
"code.filepath": "src/index.ts",
"code.lineno": 3,
"code.column": 16,
"code.function": "program"
}
}
)
gen - Effect.gen()fork - Effect.fork()forkDaemon - Effect.forkDaemon()forkScoped - Effect.forkScoped()all - Effect.all()forEach - Effect.forEach()filter - Effect.filter()reduce - Effect.reduce()iterate - Effect.iterate()loop - Effect.loop()interface SourceTraceOptions {
include?: string | RegExp | Array<string | RegExp>
exclude?: string | RegExp | Array<string | RegExp>
sourceTrace?: boolean
extractFunctionName?: boolean
spans?: SpanInstrumentationOptions
}
interface SpanInstrumentationOptions {
enabled?: boolean
include?: Array<InstrumentableEffect>
exclude?: Array<InstrumentableEffect>
nameFormat?: "function" | "location" | "full"
strategy?: DepthInstrumentationStrategy | OverrideInstrumentationStrategy
}
interface DepthInstrumentationStrategy {
type: "depth"
maxDepth?: number
perCombinator?: Partial<Record<InstrumentableEffect, number>>
}
interface OverrideInstrumentationStrategy {
type: "overrides"
rules: Partial<Record<InstrumentableEffect, CombinatorFilter>>
}
interface CombinatorFilter {
files?: string | Array<string>
excludeFiles?: string | Array<string>
functions?: string | Array<string> // Regex patterns
excludeFunctions?: string | Array<string> // Regex patterns
}
MIT
FAQs
Build-time AST transformer for Effect source location tracing
The npm package @clayroach/effect-unplugin receives a total of 26 weekly downloads. As such, @clayroach/effect-unplugin popularity was classified as not popular.
We found that @clayroach/effect-unplugin demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.