| author | |
| committer | |
| log | ff397a29523d3c63e5844b11608c0189640c7561 |
| tree | bd5179ac2bcd68f267b03c130c2adc7a8b6336d8 |
| parent | fad673225650193fad2a85487ecffc903f8ff30a |
| signature | Signed by PGP key B5690EEEBB952194 |
21 files changed, 220 insertions(+), 85 deletions(-)
apps/desktop/src/backend/DesktopBackendManager.ts+1-1| ... | ... | @@ -423,7 +423,7 @@ function drainBackendOutput( |
| 423 | 423 | cause, |
| 424 | 424 | }), |
| 425 | 425 | ), |
| 426 | Effect.catchTag("BackendProcessOutputHandlingError", onOutputFailure), | |
| 426 | Effect.catchTags({ BackendProcessOutputHandlingError: onOutputFailure }), | |
| 427 | 427 | ), |
| 428 | 428 | ), |
| 429 | 429 | Effect.catchTags({ |
apps/server/src/auth/http.ts+5-4| ... | ... | @@ -223,7 +223,7 @@ export const layerAuthenticatedAuth = Layer.effect( |
| 223 | 223 | }), |
| 224 | 224 | session.subject === "cloud-connect" ? traceAuthenticatedRelayRequest : identity, |
| 225 | 225 | ); |
| 226 | }).pipe(Effect.catchTag("EnvironmentAuthInvalidError", appendDpopChallengeOnUnauthorized)); | |
| 226 | }).pipe(Effect.catchTags({ EnvironmentAuthInvalidError: appendDpopChallengeOnUnauthorized })); | |
| 227 | 227 | }), |
| 228 | 228 | ); |
| 229 | 229 | |
| ... | ... | @@ -474,9 +474,10 @@ export const layer = HttpApiBuilder.group( |
| 474 | 474 | ); |
| 475 | 475 | return { revoked }; |
| 476 | 476 | }, |
| 477 | Effect.catchTag("ServerAuthForbiddenOperationError", () => | |
| 478 | failEnvironmentOperationForbidden("current_session_revoke_not_allowed"), | |
| 479 | ), | |
| 477 | Effect.catchTags({ | |
| 478 | ServerAuthForbiddenOperationError: () => | |
| 479 | failEnvironmentOperationForbidden("current_session_revoke_not_allowed"), | |
| 480 | }), | |
| 480 | 481 | Effect.catchIf(EnvironmentAuth.isServerAuthInternalError, (error) => |
| 481 | 482 | failEnvironmentInternal("client_session_revoke_failed", error), |
| 482 | 483 | ), |
apps/server/src/cli/connect.ts+6-5| ... | ... | @@ -105,11 +105,12 @@ const authorizeCli = Effect.fn("cloud.cli.authorize")(function* (options: { |
| 105 | 105 | // A stored credential whose refresh fails (revoked, expired grant) must |
| 106 | 106 | // fall through to a fresh device authorization, not dead-end the command. |
| 107 | 107 | const existing = yield* tokens.getExisting.pipe( |
| 108 | Effect.catchTag("CloudCliCredentialRefreshError", () => | |
| 109 | Console.log( | |
| 110 | "The stored T3 Connect credential could not be refreshed; signing in again.", | |
| 111 | ).pipe(Effect.as(Option.none())), | |
| 112 | ), | |
| 108 | Effect.catchTags({ | |
| 109 | CloudCliCredentialRefreshError: () => | |
| 110 | Console.log( | |
| 111 | "The stored T3 Connect credential could not be refreshed; signing in again.", | |
| 112 | ).pipe(Effect.as(Option.none())), | |
| 113 | }), | |
| 113 | 114 | ); |
| 114 | 115 | if (Option.isSome(existing)) { |
| 115 | 116 | return existing.value.identity ?? null; |
apps/server/src/cli/uninstall.ts+1-1| ... | ... | @@ -162,7 +162,7 @@ const runUninstall = Effect.fn("cli.uninstall.run")(function* (input: { |
| 162 | 162 | } |
| 163 | 163 | const confirmed = yield* Prompt.run( |
| 164 | 164 | Prompt.Confirm({ message: "Remove t3 from this machine?", initial: false }), |
| 165 | ).pipe(Effect.catchTag("QuitError", () => Effect.succeed(false))); | |
| 165 | ).pipe(Effect.catchTags({ QuitError: () => Effect.succeed(false) })); | |
| 166 | 166 | if (!confirmed) { |
| 167 | 167 | yield* Console.log("Left as is."); |
| 168 | 168 | return; |
apps/server/src/cli/update.ts+2-2| ... | ... | @@ -384,7 +384,7 @@ const runUpdate = Effect.fn("cli.update.run")(function* (input: { |
| 384 | 384 | } |
| 385 | 385 | const confirmed = yield* Prompt.run( |
| 386 | 386 | Prompt.Confirm({ message: "Install the preview build anyway?", initial: false }), |
| 387 | ).pipe(Effect.catchTag("QuitError", () => Effect.succeed(false))); | |
| 387 | ).pipe(Effect.catchTags({ QuitError: () => Effect.succeed(false) })); | |
| 388 | 388 | if (!confirmed) { |
| 389 | 389 | yield* Console.log("Left as is."); |
| 390 | 390 | return; |
| ... | ... | @@ -473,7 +473,7 @@ const runUpdate = Effect.fn("cli.update.run")(function* (input: { |
| 473 | 473 | message: "Restart the background service once the download is verified?", |
| 474 | 474 | initial: true, |
| 475 | 475 | }), |
| 476 | ).pipe(Effect.catchTag("QuitError", () => Effect.succeed(false))); | |
| 476 | ).pipe(Effect.catchTags({ QuitError: () => Effect.succeed(false) })); | |
| 477 | 477 | } else { |
| 478 | 478 | yield* Console.log( |
| 479 | 479 | " Not a terminal, so the service keeps running its current version. Rerun with --yes to restart it now, or run `t3 service restart` later.", |
apps/server/src/cloud/CliTokenManager.ts+6-6| ... | ... | @@ -408,9 +408,9 @@ export const deviceAuthorizationLogin = Effect.fn("cloud.cli_token.device_author |
| 408 | 408 | }); |
| 409 | 409 | return yield* pollDeviceToken(metadata, authorization.device_code, interval).pipe( |
| 410 | 410 | Effect.timeout(expiresIn), |
| 411 | Effect.catchTag("TimeoutError", (cause) => | |
| 412 | Effect.fail(new CloudCliAuthorizationTimeoutError({ cause })), | |
| 413 | ), | |
| 411 | Effect.catchTags({ | |
| 412 | TimeoutError: (cause) => Effect.fail(new CloudCliAuthorizationTimeoutError({ cause })), | |
| 413 | }), | |
| 414 | 414 | ); |
| 415 | 415 | }, |
| 416 | 416 | ); |
| ... | ... | @@ -505,9 +505,9 @@ export const make = Effect.gen(function* () { |
| 505 | 505 | authorizationUrl, |
| 506 | 506 | callback: Deferred.await(callback).pipe( |
| 507 | 507 | Effect.timeout(CLOUD_CLI_OAUTH_CALLBACK_TIMEOUT), |
| 508 | Effect.catchTag("TimeoutError", (cause) => | |
| 509 | Effect.fail(new CloudCliAuthorizationTimeoutError({ cause })), | |
| 510 | ), | |
| 508 | Effect.catchTags({ | |
| 509 | TimeoutError: (cause) => Effect.fail(new CloudCliAuthorizationTimeoutError({ cause })), | |
| 510 | }), | |
| 511 | 511 | ), |
| 512 | 512 | terminal, |
| 513 | 513 | launchBrowser: externalLauncher.launchBrowser, |
apps/server/src/cloud/CloudLink.ts+3-3| ... | ... | @@ -681,7 +681,7 @@ const make = Effect.gen(function* () { |
| 681 | 681 | return proof satisfies RelayEnvironmentLinkProof; |
| 682 | 682 | }, |
| 683 | 683 | Effect.catchIf(ServerSecretStore.isSecretStoreError, internalError("generate-link-proof")), |
| 684 | Effect.catchTag("PlatformError", internalError("generate-link-proof")), | |
| 684 | Effect.catchTags({ PlatformError: internalError("generate-link-proof") }), | |
| 685 | 685 | ); |
| 686 | 686 | |
| 687 | 687 | const activateManagedTunnel = Effect.fn("environment.cloud.activateManagedTunnel")( |
| ... | ... | @@ -1546,7 +1546,7 @@ const make = Effect.gen(function* () { |
| 1546 | 1546 | } satisfies RelayEnvironmentHealthResponse; |
| 1547 | 1547 | }, |
| 1548 | 1548 | Effect.catchIf(ServerSecretStore.isSecretStoreError, internalError("answer-health")), |
| 1549 | Effect.catchTag("PlatformError", internalError("answer-health")), | |
| 1549 | Effect.catchTags({ PlatformError: internalError("answer-health") }), | |
| 1550 | 1550 | ); |
| 1551 | 1551 | |
| 1552 | 1552 | const mintCredential = Effect.fn("environment.cloud.mintCredential")( |
| ... | ... | @@ -1653,7 +1653,7 @@ const make = Effect.gen(function* () { |
| 1653 | 1653 | } satisfies RelayEnvironmentMintResponse; |
| 1654 | 1654 | }, |
| 1655 | 1655 | Effect.catchIf(ServerSecretStore.isSecretStoreError, internalError("issue-credential")), |
| 1656 | Effect.catchTag("PlatformError", internalError("issue-credential")), | |
| 1656 | Effect.catchTags({ PlatformError: internalError("issue-credential") }), | |
| 1657 | 1657 | ); |
| 1658 | 1658 | |
| 1659 | 1659 | return CloudLink.of({ |
apps/server/src/htmlRender/HtmlRender.ts+20-18| ... | ... | @@ -351,26 +351,28 @@ const make = Effect.gen(function* () { |
| 351 | 351 | browsers.withPermits(1)( |
| 352 | 352 | // Read once a permit is held, so a queued call sees a fallback learned meanwhile. |
| 353 | 353 | Effect.suspend(() => run(noSandbox)).pipe( |
| 354 | Effect.catchTag("HtmlRenderSandboxUnavailableError", () => | |
| 355 | Effect.logInfo( | |
| 356 | "Chrome's sandbox is unavailable on this host; launching it without one.", | |
| 357 | ).pipe( | |
| 358 | Effect.andThen( | |
| 359 | Effect.sync(() => { | |
| 360 | noSandbox = true; | |
| 354 | Effect.catchTags({ | |
| 355 | HtmlRenderSandboxUnavailableError: () => | |
| 356 | Effect.logInfo( | |
| 357 | "Chrome's sandbox is unavailable on this host; launching it without one.", | |
| 358 | ).pipe( | |
| 359 | Effect.andThen( | |
| 360 | Effect.sync(() => { | |
| 361 | noSandbox = true; | |
| 362 | }), | |
| 363 | ), | |
| 364 | Effect.andThen(run(true)), | |
| 365 | ), | |
| 366 | }), | |
| 367 | Effect.catchTags({ | |
| 368 | HtmlRenderSandboxUnavailableError: (cause) => | |
| 369 | Effect.fail( | |
| 370 | new HeadlessChrome.HtmlRenderBrowserError({ | |
| 371 | reason: "the browser has no sandbox", | |
| 372 | cause, | |
| 361 | 373 | }), |
| 362 | 374 | ), |
| 363 | Effect.andThen(run(true)), | |
| 364 | ), | |
| 365 | ), | |
| 366 | Effect.catchTag("HtmlRenderSandboxUnavailableError", (cause) => | |
| 367 | Effect.fail( | |
| 368 | new HeadlessChrome.HtmlRenderBrowserError({ | |
| 369 | reason: "the browser has no sandbox", | |
| 370 | cause, | |
| 371 | }), | |
| 372 | ), | |
| 373 | ), | |
| 375 | }), | |
| 374 | 376 | ), |
| 375 | 377 | ); |
| 376 | 378 |
apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts+12-10| ... | ... | @@ -3011,16 +3011,18 @@ export function makeOpenCodeAdapterV2( |
| 3011 | 3011 | ); |
| 3012 | 3012 | yield* Effect.raceFirst(Fiber.join(request), Deferred.await(receipt)).pipe( |
| 3013 | 3013 | Effect.timeout("10 seconds"), |
| 3014 | Effect.catchTag("TimeoutError", (cause) => { | |
| 3015 | const error = new OpenCodeRuntime.OpenCodeRuntimeError({ | |
| 3016 | operation: "session.command", | |
| 3017 | detail: "OpenCode command admission did not complete within 10 seconds.", | |
| 3018 | cause, | |
| 3019 | }); | |
| 3020 | abortController.abort(); | |
| 3021 | return finalizeTurn(state, turn, "failed", { | |
| 3022 | failure: makeProviderFailure({ cause: error, class: "provider_error" }), | |
| 3023 | }).pipe(Effect.andThen(Effect.fail(error))); | |
| 3014 | Effect.catchTags({ | |
| 3015 | TimeoutError: (cause) => { | |
| 3016 | const error = new OpenCodeRuntime.OpenCodeRuntimeError({ | |
| 3017 | operation: "session.command", | |
| 3018 | detail: "OpenCode command admission did not complete within 10 seconds.", | |
| 3019 | cause, | |
| 3020 | }); | |
| 3021 | abortController.abort(); | |
| 3022 | return finalizeTurn(state, turn, "failed", { | |
| 3023 | failure: makeProviderFailure({ cause: error, class: "provider_error" }), | |
| 3024 | }).pipe(Effect.andThen(Effect.fail(error))); | |
| 3025 | }, | |
| 3024 | 3026 | }), |
| 3025 | 3027 | ); |
| 3026 | 3028 | }); |
apps/server/src/provider/acp/AcpRegistrySupport.ts+3-4| ... | ... | @@ -1916,16 +1916,15 @@ export const makeAcpRegistryCatalog = Effect.fn("AcpRegistryCatalog.make")(funct |
| 1916 | 1916 | ), |
| 1917 | 1917 | ) |
| 1918 | 1918 | .pipe( |
| 1919 | Effect.catchTag( | |
| 1920 | "ServerSettingsError", | |
| 1921 | (cause) => | |
| 1919 | Effect.catchTags({ | |
| 1920 | ServerSettingsError: (cause) => | |
| 1922 | 1921 | new AcpRegistryError({ |
| 1923 | 1922 | reason: "install_failed", |
| 1924 | 1923 | detail: |
| 1925 | 1924 | "Could not read provider settings while checking managed ACP binary references.", |
| 1926 | 1925 | cause, |
| 1927 | 1926 | }), |
| 1928 | ), | |
| 1927 | }), | |
| 1929 | 1928 | ); |
| 1930 | 1929 | |
| 1931 | 1930 | return AcpRegistryCatalog.of({ |
apps/server/src/pullRequest/PullRequestService.ts+1-1| ... | ... | @@ -1578,7 +1578,7 @@ export const make = Effect.gen(function* () { |
| 1578 | 1578 | ? operation.pipe(Effect.provideService(routingCredential, identity), Effect.result) |
| 1579 | 1579 | : Effect.fail(rejected()), |
| 1580 | 1580 | ) |
| 1581 | .pipe(Effect.catchTag("PullRequestProviderError", () => Effect.fail(rejected()))); | |
| 1581 | .pipe(Effect.catchTags({ PullRequestProviderError: () => Effect.fail(rejected()) })); | |
| 1582 | 1582 | return yield* Effect.fromResult(result); |
| 1583 | 1583 | }); |
| 1584 | 1584 |
apps/server/src/workspace/WorkspaceSearchIndex.ts+8-7| ... | ... | @@ -376,13 +376,14 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( |
| 376 | 376 | cause, |
| 377 | 377 | }), |
| 378 | 378 | ).pipe( |
| 379 | Effect.catchTag("WorkspaceSearchIndexScanTimedOut", (error) => | |
| 380 | variant === "paths" | |
| 381 | ? Effect.sync(() => { | |
| 382 | initialScanTimedOut = true; | |
| 383 | }) | |
| 384 | : Effect.fail(error), | |
| 385 | ), | |
| 379 | Effect.catchTags({ | |
| 380 | WorkspaceSearchIndexScanTimedOut: (error) => | |
| 381 | variant === "paths" | |
| 382 | ? Effect.sync(() => { | |
| 383 | initialScanTimedOut = true; | |
| 384 | }) | |
| 385 | : Effect.fail(error), | |
| 386 | }), | |
| 386 | 387 | ); |
| 387 | 388 | |
| 388 | 389 | const hasIncompleteInitialScan = () => initialScanTimedOut && finder.isScanning(); |
apps/server/src/ws.ts+10-9| ... | ... | @@ -2697,15 +2697,16 @@ const layerWsRpc = ( |
| 2697 | 2697 | status, |
| 2698 | 2698 | }), |
| 2699 | 2699 | ), |
| 2700 | Effect.catchTag("RelayClientInstallError", (error) => | |
| 2701 | Queue.fail( | |
| 2702 | queue, | |
| 2703 | new RelayClientInstallFailedError({ | |
| 2704 | reason: error.reason, | |
| 2705 | message: error.message, | |
| 2706 | }), | |
| 2707 | ), | |
| 2708 | ), | |
| 2700 | Effect.catchTags({ | |
| 2701 | RelayClientInstallError: (error) => | |
| 2702 | Queue.fail( | |
| 2703 | queue, | |
| 2704 | new RelayClientInstallFailedError({ | |
| 2705 | reason: error.reason, | |
| 2706 | message: error.message, | |
| 2707 | }), | |
| 2708 | ), | |
| 2709 | }), | |
| 2709 | 2710 | Effect.andThen(Queue.end(queue)), |
| 2710 | 2711 | Effect.forkScoped, |
| 2711 | 2712 | ), |
oxlint-plugin-t3code/index.ts+2| ... | ... | @@ -9,6 +9,7 @@ import noMobileUniwindThemeEscapeHatches from "./rules/no-mobile-uniwind-theme-e |
| 9 | 9 | import noNativeTitleTooltip from "./rules/no-native-title-tooltip.ts"; |
| 10 | 10 | import noTestInLoop from "./rules/no-test-in-loop.ts"; |
| 11 | 11 | import noUnscopedHas from "./rules/no-unscoped-has.ts"; |
| 12 | import preferCatchTags from "./rules/prefer-catch-tags.ts"; | |
| 12 | 13 | import requireSuppressionReason from "./rules/require-suppression-reason.ts"; |
| 13 | 14 | |
| 14 | 15 | export default definePlugin({ |
| ... | ... | @@ -25,6 +26,7 @@ export default definePlugin({ |
| 25 | 26 | "no-native-title-tooltip": noNativeTitleTooltip, |
| 26 | 27 | "no-test-in-loop": noTestInLoop, |
| 27 | 28 | "no-unscoped-has": noUnscopedHas, |
| 29 | "prefer-catch-tags": preferCatchTags, | |
| 28 | 30 | "require-suppression-reason": requireSuppressionReason, |
| 29 | 31 | }, |
| 30 | 32 | }); |
oxlint-plugin-t3code/rules/prefer-catch-tags.test.ts created+64| ... | ... | @@ -0,0 +1,64 @@ |
| 1 | import { assert, describe } from "@effect/vitest"; | |
| 2 | ||
| 3 | import { createOxlintRuleHarness } from "../test/utils.ts"; | |
| 4 | ||
| 5 | const rule = createOxlintRuleHarness("t3code/prefer-catch-tags"); | |
| 6 | ||
| 7 | describe("t3code/prefer-catch-tags", () => { | |
| 8 | rule.valid( | |
| 9 | "allows Effect.catchTags", | |
| 10 | ` | |
| 11 | import * as Effect from "effect/Effect"; | |
| 12 | ||
| 13 | export const program = Effect.fail({ _tag: "A" } as const).pipe( | |
| 14 | Effect.catchTags({ A: () => Effect.void }), | |
| 15 | ); | |
| 16 | `, | |
| 17 | ); | |
| 18 | ||
| 19 | rule.valid( | |
| 20 | "ignores catchTag on other modules", | |
| 21 | ` | |
| 22 | import * as Stream from "effect/Stream"; | |
| 23 | ||
| 24 | export const recover = Stream.catchTag("A", () => Stream.empty); | |
| 25 | `, | |
| 26 | ); | |
| 27 | ||
| 28 | rule.valid( | |
| 29 | "ignores a local that shadows the namespace", | |
| 30 | ` | |
| 31 | import * as Effect from "effect/Effect"; | |
| 32 | ||
| 33 | export const program = Effect.void; | |
| 34 | export function recover(Effect: { catchTag: (tag: string) => void }) { | |
| 35 | Effect.catchTag("A"); | |
| 36 | } | |
| 37 | `, | |
| 38 | ); | |
| 39 | ||
| 40 | rule.invalid( | |
| 41 | "reports Effect.catchTag", | |
| 42 | ` | |
| 43 | import * as Effect from "effect/Effect"; | |
| 44 | ||
| 45 | export const program = Effect.fail({ _tag: "A" } as const).pipe( | |
| 46 | Effect.catchTag("A", () => Effect.void), | |
| 47 | ); | |
| 48 | `, | |
| 49 | (output) => { | |
| 50 | assert.match(output, /Effect\.catchTags\(\{ Tag: handler \}\)/); | |
| 51 | }, | |
| 52 | ); | |
| 53 | ||
| 54 | rule.invalid( | |
| 55 | "reports catchTag through an aliased namespace", | |
| 56 | ` | |
| 57 | import * as Eff from "effect/Effect"; | |
| 58 | ||
| 59 | export const recover = Eff.catchTag("A", () => Eff.void); | |
| 60 | `, | |
| 61 | ); | |
| 62 | ||
| 63 | rule.invalid("reports a named catchTag import", `import { catchTag } from "effect/Effect";`); | |
| 64 | }); |
oxlint-plugin-t3code/rules/prefer-catch-tags.ts created+60| ... | ... | @@ -0,0 +1,60 @@ |
| 1 | import { defineRule, type ESTree } from "@oxlint/plugins"; | |
| 2 | ||
| 3 | const MESSAGE = "Catch known tags with `Effect.catchTags({ Tag: handler })`, even for one tag."; | |
| 4 | ||
| 5 | /** Reports `Effect.catchTag`, through any namespace import of `effect/Effect` or a named import. */ | |
| 6 | export default defineRule({ | |
| 7 | meta: { | |
| 8 | type: "suggestion", | |
| 9 | docs: { | |
| 10 | description: "Require `Effect.catchTags` over `Effect.catchTag`.", | |
| 11 | }, | |
| 12 | }, | |
| 13 | create(context) { | |
| 14 | // Whether `identifier` is bound by `import * as X from "effect/Effect"`, not a shadowing local. | |
| 15 | const isEffectNamespace = (identifier: ESTree.IdentifierReference) => { | |
| 16 | let scope = context.sourceCode.getScope(identifier); | |
| 17 | while (true) { | |
| 18 | const variable = scope.set.get(identifier.name); | |
| 19 | if (variable !== undefined) { | |
| 20 | return variable.defs.some( | |
| 21 | (def) => | |
| 22 | def.type === "ImportBinding" && | |
| 23 | def.node.type === "ImportNamespaceSpecifier" && | |
| 24 | def.parent?.type === "ImportDeclaration" && | |
| 25 | def.parent.source.value === "effect/Effect", | |
| 26 | ); | |
| 27 | } | |
| 28 | if (scope.upper === null) return false; | |
| 29 | scope = scope.upper; | |
| 30 | } | |
| 31 | }; | |
| 32 | ||
| 33 | return { | |
| 34 | ImportDeclaration(node) { | |
| 35 | if (node.source.value !== "effect/Effect") return; | |
| 36 | for (const specifier of node.specifiers) { | |
| 37 | if ( | |
| 38 | specifier.type === "ImportSpecifier" && | |
| 39 | (specifier.imported.type === "Identifier" | |
| 40 | ? specifier.imported.name | |
| 41 | : specifier.imported.value) === "catchTag" | |
| 42 | ) { | |
| 43 | context.report({ node: specifier, message: MESSAGE }); | |
| 44 | } | |
| 45 | } | |
| 46 | }, | |
| 47 | MemberExpression(node) { | |
| 48 | if ( | |
| 49 | !node.computed && | |
| 50 | node.object.type === "Identifier" && | |
| 51 | node.property.type === "Identifier" && | |
| 52 | node.property.name === "catchTag" && | |
| 53 | isEffectNamespace(node.object) | |
| 54 | ) { | |
| 55 | context.report({ node, message: MESSAGE }); | |
| 56 | } | |
| 57 | }, | |
| 58 | }; | |
| 59 | }, | |
| 60 | }); |
packages/client-runtime/src/connection/registry.ts+3-3| ... | ... | @@ -482,7 +482,7 @@ export const make = Effect.gen(function* () { |
| 482 | 482 | persistedRoutesByEnvironment.keys(), |
| 483 | 483 | (environmentId) => |
| 484 | 484 | acquireSupervisor(environmentId).pipe( |
| 485 | Effect.catchTag("EnvironmentNotRegisteredError", () => Effect.void), | |
| 485 | Effect.catchTags({ EnvironmentNotRegisteredError: () => Effect.void }), | |
| 486 | 486 | ), |
| 487 | 487 | { |
| 488 | 488 | concurrency: "unbounded", |
| ... | ... | @@ -999,7 +999,7 @@ export const make = Effect.gen(function* () { |
| 999 | 999 | relayEnvironmentIds, |
| 1000 | 1000 | (environmentId) => |
| 1001 | 1001 | removeRoute(environmentId, RELAY_ROUTE_ID).pipe( |
| 1002 | Effect.catchTag("EnvironmentNotRegisteredError", () => Effect.void), | |
| 1002 | Effect.catchTags({ EnvironmentNotRegisteredError: () => Effect.void }), | |
| 1003 | 1003 | ), |
| 1004 | 1004 | { |
| 1005 | 1005 | concurrency: "unbounded", |
| ... | ... | @@ -1012,7 +1012,7 @@ export const make = Effect.gen(function* () { |
| 1012 | 1012 | const retryNow = (environmentId: EnvironmentId) => |
| 1013 | 1013 | acquireSupervisor(environmentId).pipe( |
| 1014 | 1014 | Effect.flatMap((supervisor) => supervisor.retryNow), |
| 1015 | Effect.catchTag("EnvironmentNotRegisteredError", () => Effect.void), | |
| 1015 | Effect.catchTags({ EnvironmentNotRegisteredError: () => Effect.void }), | |
| 1016 | 1016 | Effect.withSpan("EnvironmentRegistry.retryNow"), |
| 1017 | 1017 | ); |
| 1018 | 1018 | const setEnabled = Effect.fn("EnvironmentRegistry.setEnabled")(function* ( |
packages/shared/src/relayClient.ts+10-9| ... | ... | @@ -379,15 +379,16 @@ export const makeCloudflaredRelayClient = Effect.fn("cloudflared.make")(function |
| 379 | 379 | ); |
| 380 | 380 | yield* report("waiting_for_lock"); |
| 381 | 381 | yield* acquireInstallLock(lockPath).pipe( |
| 382 | Effect.catchTag("PlatformError", (cause) => | |
| 383 | Effect.fail( | |
| 384 | new RelayClientInstallError({ | |
| 385 | reason: "write_failed", | |
| 386 | message: "Could not acquire the relay client installation lock.", | |
| 387 | cause, | |
| 388 | }), | |
| 389 | ), | |
| 390 | ), | |
| 382 | Effect.catchTags({ | |
| 383 | PlatformError: (cause) => | |
| 384 | Effect.fail( | |
| 385 | new RelayClientInstallError({ | |
| 386 | reason: "write_failed", | |
| 387 | message: "Could not acquire the relay client installation lock.", | |
| 388 | cause, | |
| 389 | }), | |
| 390 | ), | |
| 391 | }), | |
| 391 | 392 | ); |
| 392 | 393 | return yield* Effect.gen(function* () { |
| 393 | 394 | const afterLock = yield* resolve; |
packages/shared/src/shell.ts+1-1| ... | ... | @@ -756,7 +756,7 @@ export const isCommandAvailable = Effect.fn("shell.isCommandAvailable")(function |
| 756 | 756 | ) { |
| 757 | 757 | return yield* resolveCommandPath(command, options).pipe( |
| 758 | 758 | Effect.as(true), |
| 759 | Effect.catchTag("CommandResolutionError", () => Effect.succeed(false)), | |
| 759 | Effect.catchTags({ CommandResolutionError: () => Effect.succeed(false) }), | |
| 760 | 760 | ); |
| 761 | 761 | }); |
| 762 | 762 |
scripts/mobile-native-client.ts+1-1| ... | ... | @@ -316,7 +316,7 @@ const main = Command.make( |
| 316 | 316 | installedBinary: installedBinary(platform, device), |
| 317 | 317 | readRecord: fs.readFileString(recordPath).pipe( |
| 318 | 318 | Effect.flatMap(decodeRecord), |
| 319 | Effect.catchTag("SchemaError", () => Effect.succeed(null)), | |
| 319 | Effect.catchTags({ SchemaError: () => Effect.succeed(null) }), | |
| 320 | 320 | Effect.catchIf( |
| 321 | 321 | (error) => error.reason._tag === "NotFound", |
| 322 | 322 | () => Effect.succeed(null), |
vite.config.ts+1| ... | ... | @@ -170,6 +170,7 @@ export default defineConfig({ |
| 170 | 170 | "t3code/no-test-in-loop": "error", |
| 171 | 171 | "t3code/no-unscoped-has": "error", |
| 172 | 172 | "t3code/namespace-node-imports": "error", |
| 173 | "t3code/prefer-catch-tags": "error", | |
| 173 | 174 | "t3code/require-suppression-reason": "error", |
| 174 | 175 | }, |
| 175 | 176 | overrides: [ |