From 1956eae57cdeb2088558c1597f312f4207002588 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 6 Aug 2026 14:48:26 +0000
Subject: [PATCH 01/23] chore: update generated/latest
---
.changeset/readme-absolute-links.md | 5 +
README.md | 192 ++++++++++++++--------------
internal/rules/rules_json_test.go | 23 +++-
3 files changed, 123 insertions(+), 97 deletions(-)
create mode 100644 .changeset/readme-absolute-links.md
diff --git a/.changeset/readme-absolute-links.md b/.changeset/readme-absolute-links.md
new file mode 100644
index 00000000..a1a35d7b
--- /dev/null
+++ b/.changeset/readme-absolute-links.md
@@ -0,0 +1,5 @@
+---
+"@effect/tsgo": patch
+---
+
+Use absolute GitHub URLs for links in the published README so documentation links remain clickable on npm.
diff --git a/README.md b/README.md
index 467db20c..c3922582 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ The Effect LSP doubles as a tool to perform type-aware linting of Effect code, a
Linting can occur either during the `tsc` typecheck phase (with the benefit of running typechecking only once and caching the output), or via a dedicated `npx @effect/tsgo diagnostics --project tsconfig.json` command (with typechecking occurring again), or via the Oxlint Patch.
-See the Oxlint Setup guide for instructions on how to install and configure Oxlint with the Effect LSP.
+See the Oxlint Setup guide for instructions on how to install and configure Oxlint with the Effect LSP.
When running in `tsc` mode, the Effect diagnostics are emitted as standard TypeScript diagnostics, and can be configured to affect the `tsc` exit code through the options `ignoreEffectSuggestionsInTscExitCode`, `ignoreEffectWarningsInTscExitCode`, and `ignoreEffectErrorsInTscExitCode`.
@@ -46,104 +46,104 @@ Some diagnostics are off by default or have a default severity of suggestion, bu
| Correctness Wrong, unsafe, or structurally invalid code patterns. |
- anyUnknownInErrorContext | Detects 'any' or 'unknown' types in Effect error or requirements channels |
- classSelfMismatch | Ensures Self type parameter matches the class name in Context/Service/Tag/Schema classes |
- duplicatePackage | Warns when multiple versions of an Effect-related package are detected in the program |
- effectFnImplicitAny | Mirrors noImplicitAny for unannotated Effect.fn, Effect.fnUntraced, and Effect.fnUntracedEager callback parameters when no outer contextual function type exists. Requires TS's noImplicitAny: true |
- floatingEffect | Detects Effect values that are neither yielded nor assigned |
- floatingEffectInVitest | Detects Effects returned from non-Effect-aware Vitest callbacks |
- genericEffectServices | Prevents services with type parameters that cannot be discriminated at runtime |
- missingEffectContext | Detects Effect values with unhandled context requirements |
- missingEffectError | Detects Effect values with unhandled error types |
- missingLayerContext | Detects Layer values with unhandled context requirements |
- missingReturnYieldStar | Suggests using return yield* for Effects that never succeed |
- missingStarInYieldEffectGen | Detects bare yield (without *) inside Effect generator scopes |
- nonObjectEffectServiceType | Ensures Effect.Service types are objects, not primitives |
- outdatedApi | Detects usage of APIs that have been removed or renamed in Effect v4 |
- overriddenSchemaConstructor | Prevents overriding constructors in Schema classes which breaks decoding behavior |
- promiseInEffectSuccess | Detects Promise types in Effect success channels where they are not awaited |
- schemaLiteralNonFinite | Reports statically known non-finite numbers passed to Schema literal constructors |
- schemaOpaqueInstanceMember | Disallows instance members in classes extending Schema.Opaque |
+ anyUnknownInErrorContext | Detects 'any' or 'unknown' types in Effect error or requirements channels |
+ classSelfMismatch | Ensures Self type parameter matches the class name in Context/Service/Tag/Schema classes |
+ duplicatePackage | Warns when multiple versions of an Effect-related package are detected in the program |
+ effectFnImplicitAny | Mirrors noImplicitAny for unannotated Effect.fn, Effect.fnUntraced, and Effect.fnUntracedEager callback parameters when no outer contextual function type exists. Requires TS's noImplicitAny: true |
+ floatingEffect | Detects Effect values that are neither yielded nor assigned |
+ floatingEffectInVitest | Detects Effects returned from non-Effect-aware Vitest callbacks |
+ genericEffectServices | Prevents services with type parameters that cannot be discriminated at runtime |
+ missingEffectContext | Detects Effect values with unhandled context requirements |
+ missingEffectError | Detects Effect values with unhandled error types |
+ missingLayerContext | Detects Layer values with unhandled context requirements |
+ missingReturnYieldStar | Suggests using return yield* for Effects that never succeed |
+ missingStarInYieldEffectGen | Detects bare yield (without *) inside Effect generator scopes |
+ nonObjectEffectServiceType | Ensures Effect.Service types are objects, not primitives |
+ outdatedApi | Detects usage of APIs that have been removed or renamed in Effect v4 |
+ overriddenSchemaConstructor | Prevents overriding constructors in Schema classes which breaks decoding behavior |
+ promiseInEffectSuccess | Detects Promise types in Effect success channels where they are not awaited |
+ schemaLiteralNonFinite | Reports statically known non-finite numbers passed to Schema literal constructors |
+ schemaOpaqueInstanceMember | Disallows instance members in classes extending Schema.Opaque |
| Anti-pattern Discouraged patterns that often lead to bugs or confusing behavior. |
- catchUnfailableEffect | Warns when using error handling on Effects that never fail |
- effectFnIife | Effect.fn or Effect.fnUntraced is called as an IIFE; use Effect.gen instead |
- effectGenUsesAdapter | Warns when using the deprecated adapter parameter in Effect.gen |
- effectInFailure | Warns when an Effect is used inside an Effect failure channel |
- effectInVoidSuccess | Detects nested Effects in void success channels that may cause unexecuted effects |
- globalErrorInEffectCatch | Warns when catch callbacks return global Error type instead of typed errors |
- globalErrorInEffectFailure | Warns when the global Error type is used in an Effect failure channel |
- layerMergeAllWithDependencies | Detects interdependencies in Layer.mergeAll calls where one layer provides a service that another layer requires |
- lazyEffect | Suggests avoiding exported zero-argument functions and service members that lazily return Effect or Stream values |
- lazyPromiseInEffectSync | Warns when Effect.sync lazily returns a Promise instead of using an async Effect constructor |
- leakingRequirements | Detects implementation services leaked in service methods |
- multipleEffectProvide | Warns against chaining Effect.provide calls which can cause service lifecycle issues |
- preferUnsafeConstructor | Suggests replacing Effect.runSync of a pure effect constructor with the synchronous *Unsafe variant exported by the same module |
- returnEffectInGen | Warns when returning an Effect in a generator causes nested Effect<Effect<...>> |
- runEffectInsideEffect | Suggests using Runtime or Effect.run*With methods instead of Effect.run* inside Effect contexts |
- schemaSyncInEffect | Suggests using Effect-based Schema methods instead of sync methods inside Effect generators |
- scopeInLayerEffect | Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements |
- strictEffectProvide | Warns when using Effect.provide with layers outside of application entry points |
- tryCatchInEffectGen | Discourages try/catch in Effect generators in favor of Effect error handling |
- unknownInEffectCatch | Warns when catch callbacks return unknown instead of typed errors |
+ catchUnfailableEffect | Warns when using error handling on Effects that never fail |
+ effectFnIife | Effect.fn or Effect.fnUntraced is called as an IIFE; use Effect.gen instead |
+ effectGenUsesAdapter | Warns when using the deprecated adapter parameter in Effect.gen |
+ effectInFailure | Warns when an Effect is used inside an Effect failure channel |
+ effectInVoidSuccess | Detects nested Effects in void success channels that may cause unexecuted effects |
+ globalErrorInEffectCatch | Warns when catch callbacks return global Error type instead of typed errors |
+ globalErrorInEffectFailure | Warns when the global Error type is used in an Effect failure channel |
+ layerMergeAllWithDependencies | Detects interdependencies in Layer.mergeAll calls where one layer provides a service that another layer requires |
+ lazyEffect | Suggests avoiding exported zero-argument functions and service members that lazily return Effect or Stream values |
+ lazyPromiseInEffectSync | Warns when Effect.sync lazily returns a Promise instead of using an async Effect constructor |
+ leakingRequirements | Detects implementation services leaked in service methods |
+ multipleEffectProvide | Warns against chaining Effect.provide calls which can cause service lifecycle issues |
+ preferUnsafeConstructor | Suggests replacing Effect.runSync of a pure effect constructor with the synchronous *Unsafe variant exported by the same module |
+ returnEffectInGen | Warns when returning an Effect in a generator causes nested Effect<Effect<...>> |
+ runEffectInsideEffect | Suggests using Runtime or Effect.run*With methods instead of Effect.run* inside Effect contexts |
+ schemaSyncInEffect | Suggests using Effect-based Schema methods instead of sync methods inside Effect generators |
+ scopeInLayerEffect | Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements |
+ strictEffectProvide | Warns when using Effect.provide with layers outside of application entry points |
+ tryCatchInEffectGen | Discourages try/catch in Effect generators in favor of Effect error handling |
+ unknownInEffectCatch | Warns when catch callbacks return unknown instead of typed errors |
| Effect-native Prefer Effect-native APIs and abstractions when available. |
- abortControllerInEffect | Warns when manually constructing AbortController inside Effect generators instead of using Effect.abortSignal |
- asyncFunction | Warns when declaring async functions and suggests using Effect values and Effect.gen for async control flow |
- cryptoRandomUUID | Warns when using crypto.randomUUID() outside Effect generators instead of the Effect Random module, which uses Effect-injected randomness rather than the crypto module behind the scenes |
- cryptoRandomUUIDInEffect | Warns when using crypto.randomUUID() inside Effect generators instead of the Effect Random module, which uses Effect-injected randomness rather than the crypto module behind the scenes |
- extendsNativeError | Warns when a class directly extends the native Error class |
- globalConsole | Warns when using console methods outside Effect generators instead of Effect.log/Logger |
- globalConsoleInEffect | Warns when using console methods inside Effect generators instead of Effect.log/Logger |
- globalDate | Warns when using Date.now() or new Date() outside Effect generators instead of Clock/DateTime |
- globalDateInEffect | Warns when using Date.now() or new Date() inside Effect generators instead of Clock/DateTime |
- globalFetch | Warns when using the global fetch function outside Effect generators instead of the Effect HTTP client |
- globalFetchInEffect | Warns when using the global fetch function inside Effect generators instead of the Effect HTTP client |
- globalRandom | Warns when using Math.random() outside Effect generators instead of the Random service |
- globalRandomInEffect | Warns when using Math.random() inside Effect generators instead of the Random service |
- globalTimers | Warns when using setTimeout/setInterval outside Effect generators instead of Effect.sleep/Schedule |
- globalTimersInEffect | Warns when using setTimeout/setInterval inside Effect generators instead of Effect.sleep/Schedule |
- instanceOfSchema | Suggests using Schema.is instead of instanceof for Effect Schema types |
- newPromise | Warns when constructing promises with new Promise instead of using Effect APIs |
- nodeBuiltinImport | Warns when importing Node.js built-in modules that have Effect-native counterparts |
- preferSchemaOverJson | Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify |
- processEnv | Warns when reading process.env outside Effect generators instead of using Effect Config |
- processEnvInEffect | Warns when reading process.env inside Effect generators instead of using Effect Config |
- unsafeEffectTypeAssertion | Detects unsafe type assertions that narrow Effect, Stream, or Layer error or requirements channels |
+ abortControllerInEffect | Warns when manually constructing AbortController inside Effect generators instead of using Effect.abortSignal |
+ asyncFunction | Warns when declaring async functions and suggests using Effect values and Effect.gen for async control flow |
+ cryptoRandomUUID | Warns when using crypto.randomUUID() outside Effect generators instead of the Effect Random module, which uses Effect-injected randomness rather than the crypto module behind the scenes |
+ cryptoRandomUUIDInEffect | Warns when using crypto.randomUUID() inside Effect generators instead of the Effect Random module, which uses Effect-injected randomness rather than the crypto module behind the scenes |
+ extendsNativeError | Warns when a class directly extends the native Error class |
+ globalConsole | Warns when using console methods outside Effect generators instead of Effect.log/Logger |
+ globalConsoleInEffect | Warns when using console methods inside Effect generators instead of Effect.log/Logger |
+ globalDate | Warns when using Date.now() or new Date() outside Effect generators instead of Clock/DateTime |
+ globalDateInEffect | Warns when using Date.now() or new Date() inside Effect generators instead of Clock/DateTime |
+ globalFetch | Warns when using the global fetch function outside Effect generators instead of the Effect HTTP client |
+ globalFetchInEffect | Warns when using the global fetch function inside Effect generators instead of the Effect HTTP client |
+ globalRandom | Warns when using Math.random() outside Effect generators instead of the Random service |
+ globalRandomInEffect | Warns when using Math.random() inside Effect generators instead of the Random service |
+ globalTimers | Warns when using setTimeout/setInterval outside Effect generators instead of Effect.sleep/Schedule |
+ globalTimersInEffect | Warns when using setTimeout/setInterval inside Effect generators instead of Effect.sleep/Schedule |
+ instanceOfSchema | Suggests using Schema.is instead of instanceof for Effect Schema types |
+ newPromise | Warns when constructing promises with new Promise instead of using Effect APIs |
+ nodeBuiltinImport | Warns when importing Node.js built-in modules that have Effect-native counterparts |
+ preferSchemaOverJson | Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify |
+ processEnv | Warns when reading process.env outside Effect generators instead of using Effect Config |
+ processEnvInEffect | Warns when reading process.env inside Effect generators instead of using Effect Config |
+ unsafeEffectTypeAssertion | Detects unsafe type assertions that narrow Effect, Stream, or Layer error or requirements channels |
| Style Cleanup, consistency, and idiomatic Effect code. |
- catchAllToMapError | Suggests using Effect.mapError instead of Effect.catch + Effect.fail |
- catchChainToFirstSuccessOf | Suggests Effect.firstSuccessOf for consecutive error-independent Effect.catch fallbacks when the error type is preserved |
- catchTagToCatchReason | Suggests Effect.catchReason or Effect.catchReasons for handlers that re-fail unmatched reason._tag branches |
- catchToIgnore | Suggests using Effect.ignore or Effect.ignoreCause instead of Effect.catch/catchCause returning Effect.void |
- catchToOrElseSucceed | Suggests using Effect.orElseSucceed instead of Effect.catch + Effect.succeed |
- deterministicKeys | Enforces deterministic naming for service/tag/error identifiers based on class names |
- effectDoNotation | Suggests using Effect.gen or Effect.fn instead of the Effect.Do notation helpers |
- effectFnOpportunity | Suggests using Effect.fn for functions that return an Effect |
- effectMapFlatten | Suggests using Effect.flatMap instead of Effect.map followed by Effect.flatten in piping flows |
- effectMapVoid | Suggests using Effect.asVoid instead of Effect.map(() => void 0), Effect.map(() => undefined), or Effect.map(() => {}) |
- effectSucceedWithVoid | Suggests using Effect.void instead of Effect.succeed(undefined) or Effect.succeed(void 0) |
- flatMapToMap | Suggests using Effect.map instead of Effect.flatMap when the callback only wraps its result with Effect.succeed |
- missedPipeableOpportunity | Suggests using .pipe() for nested function calls |
- missingEffectServiceDependency | Checks that Effect.Service dependencies satisfy all required layer inputs |
- missingPipeableSignature | Reports exported fixed-arity functions whose call signatures have no corresponding pipeable overload |
- multipleCatchTag | Suggests collapsing consecutive Effect.catchTag transformations into a single Effect.catchTags call when semantics stay equivalent |
- nestedEffectGenYield | Warns when yielding a nested bare Effect.gen inside an existing Effect generator context |
- newSchemaClass | Suggests using Schema make instead of new for Schema classes |
- preferSchemaTypeProperty | Disallows Schema.Schema.Type<typeof X> in favor of typeof X.Type |
- preferTypedSchemaDecoder | Suggests typed Schema decoders when the input is assignable to the schema's Encoded type |
- redundantMapError | Suggests hoisting a repeated trailing Effect.mapError from every yield in an Effect generator |
- redundantOrDie | Suggests hoisting a repeated trailing Effect.orDie from every yield in an Effect generator |
- redundantSchemaTagIdentifier | Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest |
- schemaNumber | Suggests Schema.Finite and Schema.FiniteFromString instead of Schema.Number APIs when describing domain numbers |
- schemaStructWithTag | Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field |
- schemaUnionOfLiterals | Suggests combining multiple Schema.Literal calls in Schema.Union into a single Schema.Literal |
- serviceNotAsClass | Warns when Context.Service is used as a variable instead of a class declaration |
- strictBooleanExpressions | Enforces boolean types in conditional expressions for type safety |
- syncToSucceed | Suggests using Effect.succeed instead of Effect.sync when the thunk returns a constant value |
- unnecessaryArrowBlock | Suggests using a concise arrow body when the block only returns an expression |
- unnecessaryEffectGen | Suggests removing Effect.gen when it contains only a single return statement |
- unnecessaryFailYieldableError | Suggests yielding yieldable errors directly instead of wrapping with Effect.fail |
- unnecessaryPipe | Removes pipe calls with no arguments |
- unnecessaryPipeChain | Simplifies chained pipe calls into a single pipe call |
- unnecessaryTypeofType | Suggests replacing typeof Schema.Type style annotations with the matching named type when available |
+ catchAllToMapError | Suggests using Effect.mapError instead of Effect.catch + Effect.fail |
+ catchChainToFirstSuccessOf | Suggests Effect.firstSuccessOf for consecutive error-independent Effect.catch fallbacks when the error type is preserved |
+ catchTagToCatchReason | Suggests Effect.catchReason or Effect.catchReasons for handlers that re-fail unmatched reason._tag branches |
+ catchToIgnore | Suggests using Effect.ignore or Effect.ignoreCause instead of Effect.catch/catchCause returning Effect.void |
+ catchToOrElseSucceed | Suggests using Effect.orElseSucceed instead of Effect.catch + Effect.succeed |
+ deterministicKeys | Enforces deterministic naming for service/tag/error identifiers based on class names |
+ effectDoNotation | Suggests using Effect.gen or Effect.fn instead of the Effect.Do notation helpers |
+ effectFnOpportunity | Suggests using Effect.fn for functions that return an Effect |
+ effectMapFlatten | Suggests using Effect.flatMap instead of Effect.map followed by Effect.flatten in piping flows |
+ effectMapVoid | Suggests using Effect.asVoid instead of Effect.map(() => void 0), Effect.map(() => undefined), or Effect.map(() => {}) |
+ effectSucceedWithVoid | Suggests using Effect.void instead of Effect.succeed(undefined) or Effect.succeed(void 0) |
+ flatMapToMap | Suggests using Effect.map instead of Effect.flatMap when the callback only wraps its result with Effect.succeed |
+ missedPipeableOpportunity | Suggests using .pipe() for nested function calls |
+ missingEffectServiceDependency | Checks that Effect.Service dependencies satisfy all required layer inputs |
+ missingPipeableSignature | Reports exported fixed-arity functions whose call signatures have no corresponding pipeable overload |
+ multipleCatchTag | Suggests collapsing consecutive Effect.catchTag transformations into a single Effect.catchTags call when semantics stay equivalent |
+ nestedEffectGenYield | Warns when yielding a nested bare Effect.gen inside an existing Effect generator context |
+ newSchemaClass | Suggests using Schema make instead of new for Schema classes |
+ preferSchemaTypeProperty | Disallows Schema.Schema.Type<typeof X> in favor of typeof X.Type |
+ preferTypedSchemaDecoder | Suggests typed Schema decoders when the input is assignable to the schema's Encoded type |
+ redundantMapError | Suggests hoisting a repeated trailing Effect.mapError from every yield in an Effect generator |
+ redundantOrDie | Suggests hoisting a repeated trailing Effect.orDie from every yield in an Effect generator |
+ redundantSchemaTagIdentifier | Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest |
+ schemaNumber | Suggests Schema.Finite and Schema.FiniteFromString instead of Schema.Number APIs when describing domain numbers |
+ schemaStructWithTag | Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field |
+ schemaUnionOfLiterals | Suggests combining multiple Schema.Literal calls in Schema.Union into a single Schema.Literal |
+ serviceNotAsClass | Warns when Context.Service is used as a variable instead of a class declaration |
+ strictBooleanExpressions | Enforces boolean types in conditional expressions for type safety |
+ syncToSucceed | Suggests using Effect.succeed instead of Effect.sync when the thunk returns a constant value |
+ unnecessaryArrowBlock | Suggests using a concise arrow body when the block only returns an expression |
+ unnecessaryEffectGen | Suggests removing Effect.gen when it contains only a single return statement |
+ unnecessaryFailYieldableError | Suggests yielding yieldable errors directly instead of wrapping with Effect.fail |
+ unnecessaryPipe | Removes pipe calls with no arguments |
+ unnecessaryPipeChain | Simplifies chained pipe calls into a single pipe call |
+ unnecessaryTypeofType | Suggests replacing typeof Schema.Type style annotations with the matching named type when available |
diff --git a/internal/rules/rules_json_test.go b/internal/rules/rules_json_test.go
index 53d8fe60..43a02524 100644
--- a/internal/rules/rules_json_test.go
+++ b/internal/rules/rules_json_test.go
@@ -89,6 +89,27 @@ func TestReadmeTable(t *testing.T) {
}
}
+func TestReadmeLinksAreAbsolute(t *testing.T) {
+ t.Parallel()
+ readmePath := filepath.Join(repoRoot(t), "README.md")
+ content, err := os.ReadFile(readmePath)
+ if err != nil {
+ t.Fatalf("read README.md: %v", err)
+ }
+
+ patterns := []*regexp.Regexp{
+ regexp.MustCompile(`href="([^"]+)"`),
+ regexp.MustCompile(`\[[^\]]+\]\(([^)]+)\)`),
+ }
+ for _, pattern := range patterns {
+ for _, match := range pattern.FindAllStringSubmatch(string(content), -1) {
+ if !strings.HasPrefix(match[1], "https://") && !strings.HasPrefix(match[1], "http://") {
+ t.Errorf("README.md contains non-absolute link %q", match[1])
+ }
+ }
+ }
+}
+
func TestMetadataJSON(t *testing.T) {
t.Parallel()
root := repoRoot(t)
@@ -737,7 +758,7 @@ func generateReadmeTable() string {
lines = append(lines, fmt.Sprintf("