diff --git a/.changeset/shiny-seals-rush.md b/.changeset/shiny-seals-rush.md new file mode 100644 index 0000000..729b66d --- /dev/null +++ b/.changeset/shiny-seals-rush.md @@ -0,0 +1,7 @@ +--- +"@effect/tsgo": patch +--- + +Fix the toggle-pipe-style refactor to avoid formatter panics on nested callback bodies such as SQL effects using `.pipe(Effect.flatMap(...))`. + +This adds a regression test and updates the affected refactor baselines to match the new text-preserving rewrite output. diff --git a/internal/refactors/toggle_pipe_style.go b/internal/refactors/toggle_pipe_style.go index 9f91caa..be2b84e 100644 --- a/internal/refactors/toggle_pipe_style.go +++ b/internal/refactors/toggle_pipe_style.go @@ -1,12 +1,16 @@ package refactors import ( + "strings" + "github.com/effect-ts/tsgo/internal/refactor" "github.com/effect-ts/tsgo/internal/typeparser" "github.com/microsoft/typescript-go/shim/ast" "github.com/microsoft/typescript-go/shim/astnav" "github.com/microsoft/typescript-go/shim/ls" "github.com/microsoft/typescript-go/shim/ls/change" + "github.com/microsoft/typescript-go/shim/lsp/lsproto" + "github.com/microsoft/typescript-go/shim/scanner" ) var TogglePipeStyle = refactor.Refactor{ @@ -45,17 +49,12 @@ func runTogglePipeStyle(ctx *refactor.Context) []ls.CodeAction { action := ctx.NewRefactorAction(refactor.RefactorAction{ Description: "Rewrite as X.pipe(Y, Z, ...)", Run: func(tracker *change.Tracker) { - clonedSubject := tracker.DeepCloneNode(pipeCall.Subject) - pipeAccess := tracker.NewPropertyAccessExpression(clonedSubject, nil, tracker.NewIdentifier("pipe"), ast.NodeFlagsNone) - - var clonedArgs []*ast.Node - for _, arg := range pipeCall.Args { - clonedArgs = append(clonedArgs, tracker.DeepCloneNode(arg)) - } - - callExpr := tracker.NewCallExpression(pipeAccess, nil, nil, tracker.NewNodeList(clonedArgs), ast.NodeFlagsNone) - ast.SetParentInChildren(callExpr) - tracker.ReplaceNode(ctx.SourceFile, node, callExpr, nil) + start := astnav.GetStartOfNode(node, ctx.SourceFile, false) + rewritten := togglePipeToMethodText(ctx.SourceFile, pipeCall.Subject, pipeCall.Args) + tracker.ReplaceRangeWithText(ctx.SourceFile, lsproto.Range{ + Start: ctx.BytePosToLSPPosition(start), + End: ctx.BytePosToLSPPosition(node.End()), + }, rewritten) }, }) if action == nil { @@ -69,18 +68,12 @@ func runTogglePipeStyle(ctx *refactor.Context) []ls.CodeAction { action := ctx.NewRefactorAction(refactor.RefactorAction{ Description: "Rewrite as pipe(X, Y, Z, ...)", Run: func(tracker *change.Tracker) { - clonedSubject := tracker.DeepCloneNode(pipeCall.Subject) - - allArgs := make([]*ast.Node, 0, 1+len(pipeCall.Args)) - allArgs = append(allArgs, clonedSubject) - for _, arg := range pipeCall.Args { - allArgs = append(allArgs, tracker.DeepCloneNode(arg)) - } - - pipeId := tracker.NewIdentifier("pipe") - callExpr := tracker.NewCallExpression(pipeId, nil, nil, tracker.NewNodeList(allArgs), ast.NodeFlagsNone) - ast.SetParentInChildren(callExpr) - tracker.ReplaceNode(ctx.SourceFile, node, callExpr, nil) + start := astnav.GetStartOfNode(node, ctx.SourceFile, false) + rewritten := togglePipeToFunctionText(ctx.SourceFile, pipeCall.Subject, pipeCall.Args) + tracker.ReplaceRangeWithText(ctx.SourceFile, lsproto.Range{ + Start: ctx.BytePosToLSPPosition(start), + End: ctx.BytePosToLSPPosition(node.End()), + }, rewritten) }, }) if action == nil { @@ -93,3 +86,20 @@ func runTogglePipeStyle(ctx *refactor.Context) []ls.CodeAction { return nil } + +func togglePipeToMethodText(sf *ast.SourceFile, subject *ast.Node, args []*ast.Node) string { + parts := make([]string, 0, len(args)) + for _, arg := range args { + parts = append(parts, scanner.GetSourceTextOfNodeFromSourceFile(sf, arg, false)) + } + return scanner.GetSourceTextOfNodeFromSourceFile(sf, subject, false) + ".pipe(" + strings.Join(parts, ", ") + ")" +} + +func togglePipeToFunctionText(sf *ast.SourceFile, subject *ast.Node, args []*ast.Node) string { + parts := make([]string, 0, len(args)+1) + parts = append(parts, scanner.GetSourceTextOfNodeFromSourceFile(sf, subject, false)) + for _, arg := range args { + parts = append(parts, scanner.GetSourceTextOfNodeFromSourceFile(sf, arg, false)) + } + return "pipe(" + strings.Join(parts, ", ") + ")" +} diff --git a/testdata/baselines/reference/effect-v3/effectGenToFn.refactors.txt b/testdata/baselines/reference/effect-v3/effectGenToFn.refactors.txt index 6e3c0b8..b269603 100644 --- a/testdata/baselines/reference/effect-v3/effectGenToFn.refactors.txt +++ b/testdata/baselines/reference/effect-v3/effectGenToFn.refactors.txt @@ -124,10 +124,10 @@ export const program = () => export const programWithPipes = (fa: number, fb: number) => pipe(Eff.gen(function*() { - const a = yield* Eff.succeed(fa) - const b = yield* Eff.succeed(fb) - return a + b - }), Eff.map(a => a + 1)) + const a = yield* Eff.succeed(fa) + const b = yield* Eff.succeed(fb) + return a + b + }), Eff.map((a) => a + 1)) export function sampleReturns(arg1: A, arg2: B) { return Eff.gen(function*() { diff --git a/testdata/baselines/reference/effect-v3/effectGenToFn_mixedPipes.refactors.txt b/testdata/baselines/reference/effect-v3/effectGenToFn_mixedPipes.refactors.txt index 23eb6f6..83b6518 100644 --- a/testdata/baselines/reference/effect-v3/effectGenToFn_mixedPipes.refactors.txt +++ b/testdata/baselines/reference/effect-v3/effectGenToFn_mixedPipes.refactors.txt @@ -22,9 +22,9 @@ import { pipe } from "effect/Function" const test = () => pipe( pipe(Effect.gen(function*() { - const test = "test" - return yield* Effect.succeed(test) - }), Effect.asVoid), + const test = "test" + return yield* Effect.succeed(test) + }), Effect.asVoid), Effect.tapError(Effect.logError) ) diff --git a/testdata/baselines/reference/effect-v3/effectGenToFn_withPipes.refactors.txt b/testdata/baselines/reference/effect-v3/effectGenToFn_withPipes.refactors.txt index eb3b2ee..bef1640 100644 --- a/testdata/baselines/reference/effect-v3/effectGenToFn_withPipes.refactors.txt +++ b/testdata/baselines/reference/effect-v3/effectGenToFn_withPipes.refactors.txt @@ -21,8 +21,8 @@ import { pipe } from "effect/Function" const test = () => Effect.gen(function*() { - const test = "test" - return yield* Effect.succeed(test) + const test = "test" + return yield* Effect.succeed(test) }).pipe(Effect.tapError(Effect.logError)) diff --git a/testdata/baselines/reference/effect-v3/pipeableToDatafirst.refactors.txt b/testdata/baselines/reference/effect-v3/pipeableToDatafirst.refactors.txt index 705cf3a..6f9ceee 100644 --- a/testdata/baselines/reference/effect-v3/pipeableToDatafirst.refactors.txt +++ b/testdata/baselines/reference/effect-v3/pipeableToDatafirst.refactors.txt @@ -63,7 +63,7 @@ const test3 = pipe( import * as T from "effect/Effect" import { pipe } from "effect/Function" -const test = T.succeed("Hello").pipe(T.flatMap(_ => T.log(_)), T.zipRight(T.succeed(42)), T.map(_ => _ * 2)) +const test = T.succeed("Hello").pipe(T.flatMap((_) => T.log(_)), T.zipRight(T.succeed(42)), T.map((_) => _ * 2)) const noDataFirst = (value: string) => (eff: T.Effect) => pipe(eff, T.zipLeft(T.log(value))) @@ -190,7 +190,7 @@ const test = pipe( const noDataFirst = (value: string) => (eff: T.Effect) => pipe(eff, T.zipLeft(T.log(value))) -const test2 = T.succeed("Hello").pipe(T.flatMap(_ => T.log(_)), noDataFirst("42")) +const test2 = T.succeed("Hello").pipe(T.flatMap((_) => T.log(_)), noDataFirst("42")) const test3 = pipe( T.succeed("Hello"), @@ -316,7 +316,7 @@ const test2 = pipe( noDataFirst("42") ) -const test3 = T.succeed("Hello").pipe(T.flatMap(_ => T.log(_)), noDataFirst("a"), noDataFirst("b"), noDataFirst("c")) +const test3 = T.succeed("Hello").pipe(T.flatMap((_) => T.log(_)), noDataFirst("a"), noDataFirst("b"), noDataFirst("c")) === [R3] Refactor 2: "Rewrite to datafirst" === diff --git a/testdata/baselines/reference/effect-v3/togglePipeStyle.refactors.txt b/testdata/baselines/reference/effect-v3/togglePipeStyle.refactors.txt index 0dfa465..336e46d 100644 --- a/testdata/baselines/reference/effect-v3/togglePipeStyle.refactors.txt +++ b/testdata/baselines/reference/effect-v3/togglePipeStyle.refactors.txt @@ -36,7 +36,7 @@ export const toPipeable = pipe(Effect.succeed(42), Effect.map((x) => x * 2)) import * as Effect from "effect/Effect" import { pipe } from "effect/Function" -export const toRegularPipe = pipe(Effect.succeed(42), Effect.map(x => x * 2)) +export const toRegularPipe = pipe(Effect.succeed(42), Effect.map((x) => x * 2)) export const toPipeable = pipe(Effect.succeed(42), Effect.map((x) => x * 2)) @@ -77,7 +77,7 @@ import { pipe } from "effect/Function" export const toRegularPipe = Effect.succeed(42).pipe(Effect.map((x) => x * 2)) -export const toPipeable = Effect.succeed(42).pipe(Effect.map(x => x * 2)) +export const toPipeable = Effect.succeed(42).pipe(Effect.map((x) => x * 2)) === [R2] Refactor 2: "Wrap with Effect.gen" === diff --git a/testdata/baselines/reference/effect-v3/wrapWithEffectGen.refactors.txt b/testdata/baselines/reference/effect-v3/wrapWithEffectGen.refactors.txt index 7d3a5ce..40ec584 100644 --- a/testdata/baselines/reference/effect-v3/wrapWithEffectGen.refactors.txt +++ b/testdata/baselines/reference/effect-v3/wrapWithEffectGen.refactors.txt @@ -166,7 +166,7 @@ export const test1 = Effect.succeed(42) export const test3 = test1 -export const test2 = pipe(Effect.succeed(42), Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test2 = pipe(Effect.succeed(42), Effect.map((n) => n + 1), Effect.map((n) => n - 1)) export const test4 = pipe( Effect.succeed(42), @@ -235,7 +235,7 @@ export const test1 = Effect.succeed(42) export const test3 = test1 -export const test2 = pipe(Effect.succeed(42), Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test2 = pipe(Effect.succeed(42), Effect.map((n) => n + 1), Effect.map((n) => n - 1)) export const test4 = pipe( Effect.succeed(42), @@ -309,7 +309,7 @@ export const test2 = Effect.succeed(42).pipe( Effect.map((n) => n - 1) ) -export const test4 = Effect.succeed(42).pipe(Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test4 = Effect.succeed(42).pipe(Effect.map((n) => n + 1), Effect.map((n) => n - 1)) === [R5] Refactor 2: "Rewrite to datafirst" === @@ -397,7 +397,7 @@ export const test2 = Effect.succeed(42).pipe( Effect.map((n) => n - 1) ) -export const test4 = Effect.succeed(42).pipe(Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test4 = Effect.succeed(42).pipe(Effect.map((n) => n + 1), Effect.map((n) => n - 1)) === [R6] Refactor 2: "Wrap with Effect.gen" === diff --git a/testdata/baselines/reference/effect-v4/effectGenToFn.refactors.txt b/testdata/baselines/reference/effect-v4/effectGenToFn.refactors.txt index bf40975..01bd080 100644 --- a/testdata/baselines/reference/effect-v4/effectGenToFn.refactors.txt +++ b/testdata/baselines/reference/effect-v4/effectGenToFn.refactors.txt @@ -121,10 +121,10 @@ export const program = () => export const programWithPipes = (fa: number, fb: number) => pipe(Eff.gen(function*() { - const a = yield* Eff.succeed(fa) - const b = yield* Eff.succeed(fb) - return a + b - }), Eff.map(a => a + 1)) + const a = yield* Eff.succeed(fa) + const b = yield* Eff.succeed(fb) + return a + b + }), Eff.map((a) => a + 1)) export function sampleReturns(arg1: A, arg2: B) { return Eff.gen(function*() { diff --git a/testdata/baselines/reference/effect-v4/effectGenToFn_mixedPipes.refactors.txt b/testdata/baselines/reference/effect-v4/effectGenToFn_mixedPipes.refactors.txt index c366b09..ac094fe 100644 --- a/testdata/baselines/reference/effect-v4/effectGenToFn_mixedPipes.refactors.txt +++ b/testdata/baselines/reference/effect-v4/effectGenToFn_mixedPipes.refactors.txt @@ -21,9 +21,9 @@ import { pipe } from "effect/Function" const test = () => pipe( pipe(Effect.gen(function*() { - const test = "test" - return yield* Effect.succeed(test) - }), Effect.asVoid), + const test = "test" + return yield* Effect.succeed(test) + }), Effect.asVoid), Effect.tapError(Effect.logError) ) diff --git a/testdata/baselines/reference/effect-v4/effectGenToFn_withPipes.refactors.txt b/testdata/baselines/reference/effect-v4/effectGenToFn_withPipes.refactors.txt index 3bcc3e1..98b873a 100644 --- a/testdata/baselines/reference/effect-v4/effectGenToFn_withPipes.refactors.txt +++ b/testdata/baselines/reference/effect-v4/effectGenToFn_withPipes.refactors.txt @@ -20,8 +20,8 @@ import { pipe } from "effect/Function" const test = () => Effect.gen(function*() { - const test = "test" - return yield* Effect.succeed(test) + const test = "test" + return yield* Effect.succeed(test) }).pipe(Effect.tapError(Effect.logError)) diff --git a/testdata/baselines/reference/effect-v4/pipeableToDatafirst.refactors.txt b/testdata/baselines/reference/effect-v4/pipeableToDatafirst.refactors.txt index 5398c0a..72171a0 100644 --- a/testdata/baselines/reference/effect-v4/pipeableToDatafirst.refactors.txt +++ b/testdata/baselines/reference/effect-v4/pipeableToDatafirst.refactors.txt @@ -61,7 +61,7 @@ const test3 = pipe( import * as T from "effect/Effect" import { pipe } from "effect/Function" -const test = T.succeed("Hello").pipe(T.flatMap(_ => T.log(_)), T.andThen(T.succeed(42)), T.map(_ => _ * 2)) +const test = T.succeed("Hello").pipe(T.flatMap((_) => T.log(_)), T.andThen(T.succeed(42)), T.map((_) => _ * 2)) const noDataFirst = (value: string) => (eff: T.Effect) => pipe(eff, T.andThen(T.log(value))) @@ -184,7 +184,7 @@ const test = pipe( const noDataFirst = (value: string) => (eff: T.Effect) => pipe(eff, T.andThen(T.log(value))) -const test2 = T.succeed("Hello").pipe(T.flatMap(_ => T.log(_)), noDataFirst("42")) +const test2 = T.succeed("Hello").pipe(T.flatMap((_) => T.log(_)), noDataFirst("42")) const test3 = pipe( T.succeed("Hello"), @@ -306,7 +306,7 @@ const test2 = pipe( noDataFirst("42") ) -const test3 = T.succeed("Hello").pipe(T.flatMap(_ => T.log(_)), noDataFirst("a"), noDataFirst("b"), noDataFirst("c")) +const test3 = T.succeed("Hello").pipe(T.flatMap((_) => T.log(_)), noDataFirst("a"), noDataFirst("b"), noDataFirst("c")) === [R3] Refactor 2: "Rewrite to datafirst" === diff --git a/testdata/baselines/reference/effect-v4/togglePipeStyle.refactors.txt b/testdata/baselines/reference/effect-v4/togglePipeStyle.refactors.txt index 9580629..9410316 100644 --- a/testdata/baselines/reference/effect-v4/togglePipeStyle.refactors.txt +++ b/testdata/baselines/reference/effect-v4/togglePipeStyle.refactors.txt @@ -34,7 +34,7 @@ export const toPipeable = pipe(Effect.succeed(42), Effect.map((x) => x * 2)) import * as Effect from "effect/Effect" import { pipe } from "effect/Function" -export const toRegularPipe = pipe(Effect.succeed(42), Effect.map(x => x * 2)) +export const toRegularPipe = pipe(Effect.succeed(42), Effect.map((x) => x * 2)) export const toPipeable = pipe(Effect.succeed(42), Effect.map((x) => x * 2)) @@ -72,7 +72,7 @@ import { pipe } from "effect/Function" export const toRegularPipe = Effect.succeed(42).pipe(Effect.map((x) => x * 2)) -export const toPipeable = Effect.succeed(42).pipe(Effect.map(x => x * 2)) +export const toPipeable = Effect.succeed(42).pipe(Effect.map((x) => x * 2)) === [R2] Refactor 2: "Wrap with Effect.gen" === diff --git a/testdata/baselines/reference/effect-v4/togglePipeStyle_nestedCallback.refactors.txt b/testdata/baselines/reference/effect-v4/togglePipeStyle_nestedCallback.refactors.txt new file mode 100644 index 0000000..734de2b --- /dev/null +++ b/testdata/baselines/reference/effect-v4/togglePipeStyle_nestedCallback.refactors.txt @@ -0,0 +1,108 @@ +=== Refactor Inventory === + +[R1] selection: "11:9-11:10" + Refactor 0: "Wrap with pipe" (refactor.rewrite.effect.wrapWithPipe) + Refactor 1: "Rewrite as pipe(X, Y, Z, ...)" (refactor.rewrite.effect.togglePipeStyle) + Refactor 2: "Wrap with Effect.gen" (refactor.rewrite.effect.wrapWithEffectGen) + Refactor 3: "Toggle return type annotation" (refactor.rewrite.effect.toggleReturnTypeAnnotation) + +[R2] selection: "empty (0:0-0:0)" + (no refactors) + +=== Refactor Application Results === + +=== [R1] Refactor 0: "Wrap with pipe" === + +--- file:///.src/togglePipeStyle_nestedCallback.ts --- +// refactor: 11:9-11:10 +import * as Effect from "effect/Effect" + +type SqlResult = ReadonlyArray<{ id: number }> + +const sql = (_strings: TemplateStringsArray, ..._args: ReadonlyArray): Effect.Effect => + Effect.succeed([]) + +export const insertEnvelope = { + pg: () => (_row: { id: string }, messageId: string) => + sql`pipe( +) select * from messages where id = ${messageId} + `.pipe(Effect.flatMap((rows) => { + if (rows.length > 0) return Effect.succeed(rows) + return sql` + select * from messages where id = ${messageId} + ` + })) +} + + +=== [R1] Refactor 1: "Rewrite as pipe(X, Y, Z, ...)" === + +--- file:///.src/togglePipeStyle_nestedCallback.ts --- +// refactor: 11:9-11:10 +import * as Effect from "effect/Effect" + +type SqlResult = ReadonlyArray<{ id: number }> + +const sql = (_strings: TemplateStringsArray, ..._args: ReadonlyArray): Effect.Effect => + Effect.succeed([]) + +export const insertEnvelope = { + pg: () => (_row: { id: string }, messageId: string) => + pipe(sql` + select * from messages where id = ${messageId} + `, Effect.flatMap((rows) => { + if (rows.length > 0) return Effect.succeed(rows) + return sql` + select * from messages where id = ${messageId} + ` + })) +} + + +=== [R1] Refactor 2: "Wrap with Effect.gen" === + +--- file:///.src/togglePipeStyle_nestedCallback.ts --- +// refactor: 11:9-11:10 +import * as Effect from "effect/Effect" + +type SqlResult = ReadonlyArray<{ id: number }> + +const sql = (_strings: TemplateStringsArray, ..._args: ReadonlyArray): Effect.Effect => + Effect.succeed([]) + +export const insertEnvelope = { + pg: () => (_row: { id: string }, messageId: string) => + Effect.gen(function*() { return yield* sql` + select * from messages where id = ${messageId} + ` }).pipe(Effect.flatMap((rows) => { + if (rows.length > 0) return Effect.succeed(rows) + return sql` + select * from messages where id = ${messageId} + ` + })) +} + + +=== [R1] Refactor 3: "Toggle return type annotation" === + +--- file:///.src/togglePipeStyle_nestedCallback.ts --- +// refactor: 11:9-11:10 +import * as Effect from "effect/Effect" + +type SqlResult = ReadonlyArray<{ id: number }> + +const sql = (_strings: TemplateStringsArray, ..._args: ReadonlyArray): Effect.Effect => + Effect.succeed([]) + +export const insertEnvelope = { + pg: () => (_row: { id: string }, messageId: string): Effect.Effect => + sql` + select * from messages where id = ${messageId} + `.pipe(Effect.flatMap((rows) => { + if (rows.length > 0) return Effect.succeed(rows) + return sql` + select * from messages where id = ${messageId} + ` + })) +} + diff --git a/testdata/baselines/reference/effect-v4/wrapWithEffectGen.refactors.txt b/testdata/baselines/reference/effect-v4/wrapWithEffectGen.refactors.txt index 392208f..7ef1c6e 100644 --- a/testdata/baselines/reference/effect-v4/wrapWithEffectGen.refactors.txt +++ b/testdata/baselines/reference/effect-v4/wrapWithEffectGen.refactors.txt @@ -160,7 +160,7 @@ export const test1 = Effect.succeed(42) export const test3 = test1 -export const test2 = pipe(Effect.succeed(42), Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test2 = pipe(Effect.succeed(42), Effect.map((n) => n + 1), Effect.map((n) => n - 1)) export const test4 = pipe( Effect.succeed(42), @@ -226,7 +226,7 @@ export const test1 = Effect.succeed(42) export const test3 = test1 -export const test2 = pipe(Effect.succeed(42), Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test2 = pipe(Effect.succeed(42), Effect.map((n) => n + 1), Effect.map((n) => n - 1)) export const test4 = pipe( Effect.succeed(42), @@ -297,7 +297,7 @@ export const test2 = Effect.succeed(42).pipe( Effect.map((n) => n - 1) ) -export const test4 = Effect.succeed(42).pipe(Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test4 = Effect.succeed(42).pipe(Effect.map((n) => n + 1), Effect.map((n) => n - 1)) === [R5] Refactor 2: "Rewrite to datafirst" === @@ -381,7 +381,7 @@ export const test2 = Effect.succeed(42).pipe( Effect.map((n) => n - 1) ) -export const test4 = Effect.succeed(42).pipe(Effect.map(n => n + 1), Effect.map(n => n - 1)) +export const test4 = Effect.succeed(42).pipe(Effect.map((n) => n + 1), Effect.map((n) => n - 1)) === [R6] Refactor 2: "Wrap with Effect.gen" === diff --git a/testdata/tests/effect-v4-refactors/togglePipeStyle_nestedCallback.ts b/testdata/tests/effect-v4-refactors/togglePipeStyle_nestedCallback.ts new file mode 100644 index 0000000..99be3e2 --- /dev/null +++ b/testdata/tests/effect-v4-refactors/togglePipeStyle_nestedCallback.ts @@ -0,0 +1,19 @@ +// refactor: 11:9-11:10 +import * as Effect from "effect/Effect" + +type SqlResult = ReadonlyArray<{ id: number }> + +const sql = (_strings: TemplateStringsArray, ..._args: ReadonlyArray): Effect.Effect => + Effect.succeed([]) + +export const insertEnvelope = { + pg: () => (_row: { id: string }, messageId: string) => + sql` + select * from messages where id = ${messageId} + `.pipe(Effect.flatMap((rows) => { + if (rows.length > 0) return Effect.succeed(rows) + return sql` + select * from messages where id = ${messageId} + ` + })) +}