@effect/language-service 0.10.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -71,6 +71,7 @@ Few options can be provided alongside the initialization of the Language Service
71
71
  - Pipe to datafirst: Transform a pipe() call into a series of datafirst function calls (where available).
72
72
  - Toggle return type signature: With a single refactor, adds or removes type annotations from the definition.
73
73
  - Remove unnecessary `Effect.gen` definitions that contains a single `yield` statement.
74
+ - Wrap an `Effect` expression with `Effect.gen`
74
75
 
75
76
  ## Configuring diagnostics
76
77
 
package/index.js CHANGED
@@ -1166,24 +1166,7 @@ var transformAsyncAwaitToEffectGen = fn("AST.transformAsyncAwaitToEffectGen")(
1166
1166
  return ts.visitEachChild(_, visitor, ts.nullTransformationContext);
1167
1167
  }
1168
1168
  const generatorBody = visitor(node.body);
1169
- const generator = ts.factory.createFunctionExpression(
1170
- void 0,
1171
- ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1172
- void 0,
1173
- [],
1174
- [],
1175
- void 0,
1176
- generatorBody
1177
- // NOTE(mattia): intended, to use same routine for both ConciseBody and Body
1178
- );
1179
- const effectGenCallExp = ts.factory.createCallExpression(
1180
- ts.factory.createPropertyAccessExpression(
1181
- ts.factory.createIdentifier(effectModuleName),
1182
- "gen"
1183
- ),
1184
- void 0,
1185
- [generator]
1186
- );
1169
+ const effectGenCallExp = yield* createEffectGenCallExpression(effectModuleName, generatorBody);
1187
1170
  let currentFlags = ts.getCombinedModifierFlags(node);
1188
1171
  currentFlags &= ~ts.ModifierFlags.Async;
1189
1172
  const newModifiers = ts.factory.createModifiersFromModifierFlags(currentFlags);
@@ -1405,6 +1388,47 @@ var parseDataForExtendsClassCompletion = fn(
1405
1388
  { accessedObject, classDeclaration, className: classDeclaration.name, replacementSpan }
1406
1389
  );
1407
1390
  });
1391
+ var createEffectGenCallExpression = fn("AST.createEffectGenCallExpression")(function* (effectModuleIdentifierName, node) {
1392
+ const ts = yield* service(TypeScriptApi);
1393
+ const generator = ts.factory.createFunctionExpression(
1394
+ void 0,
1395
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1396
+ void 0,
1397
+ [],
1398
+ [],
1399
+ void 0,
1400
+ node
1401
+ // NOTE(mattia): intended, to use same routine for both ConciseBody and Body
1402
+ );
1403
+ return ts.factory.createCallExpression(
1404
+ ts.factory.createPropertyAccessExpression(
1405
+ ts.factory.createIdentifier(effectModuleIdentifierName),
1406
+ "gen"
1407
+ ),
1408
+ void 0,
1409
+ [generator]
1410
+ );
1411
+ });
1412
+ var createEffectGenCallExpressionWithBlock = fn(
1413
+ "AST.createEffectGenCallExpressionWithBlock"
1414
+ )(function* (effectModuleIdentifierName, statement) {
1415
+ const ts = yield* service(TypeScriptApi);
1416
+ return yield* createEffectGenCallExpression(
1417
+ effectModuleIdentifierName,
1418
+ ts.factory.createBlock(Array.isArray(statement) ? statement : [statement], false)
1419
+ );
1420
+ });
1421
+ var createReturnYieldStarStatement = fn("AST.createReturnYieldStarStatement")(
1422
+ function* (expr) {
1423
+ const ts = yield* service(TypeScriptApi);
1424
+ return ts.factory.createReturnStatement(
1425
+ ts.factory.createYieldExpression(
1426
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1427
+ expr
1428
+ )
1429
+ );
1430
+ }
1431
+ );
1408
1432
 
1409
1433
  // src/core/LSP.ts
1410
1434
  var RefactorNotApplicableError = class {
@@ -1945,6 +1969,13 @@ function covariantTypeArgument(type) {
1945
1969
  }
1946
1970
  return succeed(signatures[0].getReturnType());
1947
1971
  }
1972
+ function invariantTypeArgument(type) {
1973
+ const signatures = type.getCallSignatures();
1974
+ if (signatures.length !== 1) {
1975
+ return typeParserIssue("Invariant type has no call signature", type);
1976
+ }
1977
+ return succeed(signatures[0].getReturnType());
1978
+ }
1948
1979
  var pipeableType = fn("TypeParser.pipeableType")(function* (type, atLocation) {
1949
1980
  const typeChecker = yield* service(TypeCheckerApi);
1950
1981
  const pipeSymbol = typeChecker.getPropertyOfType(type, "pipe");
@@ -1969,6 +2000,17 @@ var varianceStructCovariantType = fn("TypeParser.varianceStructCovariantType")(
1969
2000
  return yield* covariantTypeArgument(propertyType);
1970
2001
  }
1971
2002
  );
2003
+ var varianceStructInvariantType = fn("TypeParser.varianceStructInvariantType")(
2004
+ function* (type, atLocation, propertyName) {
2005
+ const typeChecker = yield* service(TypeCheckerApi);
2006
+ const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
2007
+ if (!propertySymbol) {
2008
+ return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
2009
+ }
2010
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
2011
+ return yield* invariantTypeArgument(propertyType);
2012
+ }
2013
+ );
1972
2014
  var effectVarianceStruct = fn("TypeParser.effectVarianceStruct")(function* (type, atLocation) {
1973
2015
  return {
1974
2016
  A: yield* varianceStructCovariantType(type, atLocation, "_A"),
@@ -2175,6 +2217,37 @@ var returnYieldEffectBlock = fn("TypeParser.returnYieldEffectBlock")(function* (
2175
2217
  body
2176
2218
  );
2177
2219
  });
2220
+ var effectSchemaVarianceStruct = fn("TypeParser.effectSchemaVarianceStruct")(
2221
+ function* (type, atLocation) {
2222
+ return {
2223
+ A: yield* varianceStructInvariantType(type, atLocation, "_A"),
2224
+ I: yield* varianceStructInvariantType(type, atLocation, "_I"),
2225
+ R: yield* varianceStructCovariantType(type, atLocation, "_R")
2226
+ };
2227
+ }
2228
+ );
2229
+ var effectSchemaType = fn("TypeParser.effectSchemaType")(function* (type, atLocation) {
2230
+ const ts = yield* service(TypeScriptApi);
2231
+ const typeChecker = yield* service(TypeCheckerApi);
2232
+ yield* pipeableType(type, atLocation);
2233
+ const ast = typeChecker.getPropertyOfType(type, "ast");
2234
+ if (!ast) return yield* typeParserIssue("Has no 'ast' property", type, atLocation);
2235
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
2236
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
2237
+ );
2238
+ propertiesSymbols.sort((a, b) => b.name.indexOf("TypeId") - a.name.indexOf("TypeId"));
2239
+ for (const propertySymbol of propertiesSymbols) {
2240
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
2241
+ const varianceArgs = yield* option(effectSchemaVarianceStruct(
2242
+ propertyType,
2243
+ atLocation
2244
+ ));
2245
+ if (isSome2(varianceArgs)) {
2246
+ return varianceArgs.value;
2247
+ }
2248
+ }
2249
+ return yield* typeParserIssue("Type has no schema variance struct", type, atLocation);
2250
+ });
2178
2251
 
2179
2252
  // src/diagnostics/floatingEffect.ts
2180
2253
  var floatingEffect = createDiagnostic({
@@ -2535,7 +2608,7 @@ function prependEffectTypeArguments(sourceFile, position, quickInfo) {
2535
2608
  var asyncAwaitToGen = createRefactor({
2536
2609
  name: "effect/asyncAwaitToGen",
2537
2610
  description: "Convert to Effect.gen",
2538
- apply: (sourceFile, textRange) => gen2(function* () {
2611
+ apply: fn("asyncAwaitToGen.apply")(function* (sourceFile, textRange) {
2539
2612
  const ts = yield* service(TypeScriptApi);
2540
2613
  const typeChecker = yield* service(TypeCheckerApi);
2541
2614
  const maybeNode = pipe(
@@ -2607,7 +2680,7 @@ var asyncAwaitToGen = createRefactor({
2607
2680
  var asyncAwaitToGenTryPromise = createRefactor({
2608
2681
  name: "effect/asyncAwaitToGenTryPromise",
2609
2682
  description: "Convert to Effect.gen with failures",
2610
- apply: (sourceFile, textRange) => gen2(function* () {
2683
+ apply: fn("asyncAwaitToGenTryPromise.apply")(function* (sourceFile, textRange) {
2611
2684
  const ts = yield* service(TypeScriptApi);
2612
2685
  const typeChecker = yield* service(TypeCheckerApi);
2613
2686
  const maybeNode = pipe(
@@ -2709,34 +2782,32 @@ var asyncAwaitToGenTryPromise = createRefactor({
2709
2782
  var effectGenToFn = createRefactor({
2710
2783
  name: "effect/effectGenToFn",
2711
2784
  description: "Convert to Effect.fn",
2712
- apply: (sourceFile, textRange) => gen2(function* () {
2785
+ apply: fn("effectGenToFn.apply")(function* (sourceFile, textRange) {
2713
2786
  const ts = yield* service(TypeScriptApi);
2714
- function parseEffectGenNode(node) {
2715
- return gen2(function* () {
2716
- const effectGen2 = yield* effectGen(node);
2717
- let pipeArgs2 = ts.factory.createNodeArray([]);
2718
- let nodeToReplace2 = node.parent;
2719
- if (ts.isPropertyAccessExpression(node.parent) && node.parent.name.text === "pipe" && ts.isCallExpression(node.parent.parent)) {
2720
- pipeArgs2 = node.parent.parent.arguments;
2721
- nodeToReplace2 = node.parent.parent.parent;
2787
+ const parseEffectGenNode = fn("asyncAwaitToGen.apply")(function* (node) {
2788
+ const effectGen2 = yield* effectGen(node);
2789
+ let pipeArgs2 = ts.factory.createNodeArray([]);
2790
+ let nodeToReplace2 = node.parent;
2791
+ if (ts.isPropertyAccessExpression(node.parent) && node.parent.name.text === "pipe" && ts.isCallExpression(node.parent.parent)) {
2792
+ pipeArgs2 = node.parent.parent.arguments;
2793
+ nodeToReplace2 = node.parent.parent.parent;
2794
+ }
2795
+ while (nodeToReplace2) {
2796
+ if (ts.isArrowFunction(nodeToReplace2) || ts.isFunctionDeclaration(nodeToReplace2) || ts.isMethodDeclaration(nodeToReplace2)) {
2797
+ return { ...effectGen2, pipeArgs: pipeArgs2, nodeToReplace: nodeToReplace2 };
2722
2798
  }
2723
- while (nodeToReplace2) {
2724
- if (ts.isArrowFunction(nodeToReplace2) || ts.isFunctionDeclaration(nodeToReplace2) || ts.isMethodDeclaration(nodeToReplace2)) {
2725
- return { ...effectGen2, pipeArgs: pipeArgs2, nodeToReplace: nodeToReplace2 };
2726
- }
2727
- if (ts.isConciseBody(nodeToReplace2) || ts.isReturnStatement(nodeToReplace2)) {
2728
- nodeToReplace2 = nodeToReplace2.parent;
2729
- continue;
2730
- }
2731
- if (ts.isBlock(nodeToReplace2) && nodeToReplace2.statements.length === 1) {
2732
- nodeToReplace2 = nodeToReplace2.parent;
2733
- continue;
2734
- }
2735
- break;
2799
+ if (ts.isConciseBody(nodeToReplace2) || ts.isReturnStatement(nodeToReplace2)) {
2800
+ nodeToReplace2 = nodeToReplace2.parent;
2801
+ continue;
2736
2802
  }
2737
- return yield* fail(new RefactorNotApplicableError());
2738
- });
2739
- }
2803
+ if (ts.isBlock(nodeToReplace2) && nodeToReplace2.statements.length === 1) {
2804
+ nodeToReplace2 = nodeToReplace2.parent;
2805
+ continue;
2806
+ }
2807
+ break;
2808
+ }
2809
+ return yield* fail(new RefactorNotApplicableError());
2810
+ });
2740
2811
  const maybeNode = yield* pipe(
2741
2812
  yield* getAncestorNodesInRange(sourceFile, textRange),
2742
2813
  map2(parseEffectGenNode),
@@ -2791,7 +2862,7 @@ var effectGenToFn = createRefactor({
2791
2862
  var functionToArrow = createRefactor({
2792
2863
  name: "effect/functionToArrow",
2793
2864
  description: "Convert to arrow",
2794
- apply: (sourceFile, textRange) => gen2(function* () {
2865
+ apply: fn("functionToArrow.apply")(function* (sourceFile, textRange) {
2795
2866
  const ts = yield* service(TypeScriptApi);
2796
2867
  const maybeNode = pipe(
2797
2868
  yield* getAncestorNodesInRange(sourceFile, textRange),
@@ -2843,11 +2914,180 @@ var functionToArrow = createRefactor({
2843
2914
  })
2844
2915
  });
2845
2916
 
2917
+ // src/refactors/makeSchemaOpaque.ts
2918
+ var makeSchemaOpaque = createRefactor({
2919
+ name: "effect/makeSchemaOpaque",
2920
+ description: "Make Schema opaque",
2921
+ apply: fn("makeSchemaOpaque.apply")(function* (sourceFile, textRange) {
2922
+ const ts = yield* service(TypeScriptApi);
2923
+ const typeChecker = yield* service(TypeCheckerApi);
2924
+ const findSchema = fn("makeSchemaOpaque.apply.findSchema")(
2925
+ function* (node) {
2926
+ if (!ts.isVariableDeclaration(node)) {
2927
+ return yield* fail("parent should be variable declaration");
2928
+ }
2929
+ const identifier2 = node.name;
2930
+ if (!ts.isIdentifier(identifier2)) return yield* fail("name should be an identifier");
2931
+ const initializer = node.initializer;
2932
+ if (!initializer) return yield* fail("should have an initializer");
2933
+ const variableDeclarationList2 = node.parent;
2934
+ if (!variableDeclarationList2 || !ts.isVariableDeclarationList(variableDeclarationList2)) {
2935
+ return yield* fail("parent is not a variable declaration list");
2936
+ }
2937
+ const variableStatement2 = variableDeclarationList2.parent;
2938
+ if (!variableStatement2 || !ts.isVariableStatement(variableStatement2)) {
2939
+ return yield* fail("parent not variable declaration statement");
2940
+ }
2941
+ const type = typeChecker.getTypeAtLocation(initializer);
2942
+ const types2 = yield* effectSchemaType(type, initializer);
2943
+ return { identifier: identifier2, variableStatement: variableStatement2, variableDeclarationList: variableDeclarationList2, types: types2 };
2944
+ }
2945
+ );
2946
+ const maybeNode = yield* pipe(
2947
+ yield* getAncestorNodesInRange(sourceFile, textRange),
2948
+ map2(findSchema),
2949
+ firstSuccessOf,
2950
+ option
2951
+ );
2952
+ if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
2953
+ const { identifier, types, variableDeclarationList, variableStatement } = maybeNode.value;
2954
+ return {
2955
+ kind: "refactor.rewrite.effect.makeSchemaOpaque",
2956
+ description: `Make Schema opaque`,
2957
+ apply: pipe(
2958
+ gen2(function* () {
2959
+ const changeTracker = yield* service(ChangeTracker);
2960
+ const effectSchemaName = match2(
2961
+ yield* option(
2962
+ findImportedModuleIdentifierByPackageAndNameOrBarrel(
2963
+ sourceFile,
2964
+ "effect",
2965
+ "Schema"
2966
+ )
2967
+ ),
2968
+ {
2969
+ onNone: () => "Schema",
2970
+ onSome: (_) => _.text
2971
+ }
2972
+ );
2973
+ const newIdentifier = ts.factory.createIdentifier(identifier.text + "_");
2974
+ const opaqueInferred = ts.factory.createExpressionWithTypeArguments(
2975
+ ts.factory.createPropertyAccessExpression(
2976
+ ts.factory.createPropertyAccessExpression(
2977
+ ts.factory.createIdentifier(effectSchemaName),
2978
+ ts.factory.createIdentifier("Schema")
2979
+ ),
2980
+ ts.factory.createIdentifier("Type")
2981
+ ),
2982
+ [ts.factory.createTypeQueryNode(
2983
+ ts.factory.createIdentifier(newIdentifier.text)
2984
+ )]
2985
+ );
2986
+ const opaqueType = types.A.isUnion() ? ts.factory.createTypeAliasDeclaration(
2987
+ variableStatement.modifiers,
2988
+ identifier.text,
2989
+ [],
2990
+ opaqueInferred
2991
+ ) : ts.factory.createInterfaceDeclaration(
2992
+ variableStatement.modifiers,
2993
+ identifier.text,
2994
+ void 0,
2995
+ [ts.factory.createHeritageClause(
2996
+ ts.SyntaxKind.ExtendsKeyword,
2997
+ [opaqueInferred]
2998
+ )],
2999
+ []
3000
+ );
3001
+ const encodedInferred = ts.factory.createExpressionWithTypeArguments(
3002
+ ts.factory.createPropertyAccessExpression(
3003
+ ts.factory.createPropertyAccessExpression(
3004
+ ts.factory.createIdentifier(effectSchemaName),
3005
+ ts.factory.createIdentifier("Schema")
3006
+ ),
3007
+ ts.factory.createIdentifier("Encoded")
3008
+ ),
3009
+ [ts.factory.createTypeQueryNode(
3010
+ ts.factory.createIdentifier(newIdentifier.text)
3011
+ )]
3012
+ );
3013
+ const encodedType = types.I.isUnion() ? ts.factory.createTypeAliasDeclaration(
3014
+ variableStatement.modifiers,
3015
+ identifier.text + "Encoded",
3016
+ [],
3017
+ encodedInferred
3018
+ ) : ts.factory.createInterfaceDeclaration(
3019
+ variableStatement.modifiers,
3020
+ identifier.text + "Encoded",
3021
+ void 0,
3022
+ [ts.factory.createHeritageClause(
3023
+ ts.SyntaxKind.ExtendsKeyword,
3024
+ [encodedInferred]
3025
+ )],
3026
+ []
3027
+ );
3028
+ const contextInferred = ts.factory.createExpressionWithTypeArguments(
3029
+ ts.factory.createPropertyAccessExpression(
3030
+ ts.factory.createPropertyAccessExpression(
3031
+ ts.factory.createIdentifier(effectSchemaName),
3032
+ ts.factory.createIdentifier("Schema")
3033
+ ),
3034
+ ts.factory.createIdentifier("Context")
3035
+ ),
3036
+ [ts.factory.createTypeQueryNode(
3037
+ ts.factory.createIdentifier(newIdentifier.text)
3038
+ )]
3039
+ );
3040
+ const contextType = ts.factory.createTypeAliasDeclaration(
3041
+ variableStatement.modifiers,
3042
+ identifier.text + "Context",
3043
+ [],
3044
+ contextInferred
3045
+ );
3046
+ changeTracker.replaceNode(
3047
+ sourceFile,
3048
+ identifier,
3049
+ newIdentifier
3050
+ );
3051
+ changeTracker.insertNodeAfter(sourceFile, variableStatement, opaqueType);
3052
+ changeTracker.insertNodeAfter(sourceFile, variableStatement, encodedType);
3053
+ changeTracker.insertNodeAfter(sourceFile, variableStatement, contextType);
3054
+ const newSchemaType = ts.factory.createTypeReferenceNode(
3055
+ ts.factory.createQualifiedName(
3056
+ ts.factory.createIdentifier(effectSchemaName),
3057
+ ts.factory.createIdentifier("Schema")
3058
+ ),
3059
+ [
3060
+ ts.factory.createTypeReferenceNode(opaqueType.name),
3061
+ ts.factory.createTypeReferenceNode(encodedType.name),
3062
+ ts.factory.createTypeReferenceNode(contextType.name)
3063
+ ]
3064
+ );
3065
+ const newConstDeclaration = ts.factory.createVariableStatement(
3066
+ variableStatement.modifiers,
3067
+ ts.factory.createVariableDeclarationList(
3068
+ [ts.factory.createVariableDeclaration(
3069
+ identifier.text,
3070
+ void 0,
3071
+ newSchemaType,
3072
+ ts.factory.createIdentifier(newIdentifier.text)
3073
+ )],
3074
+ variableDeclarationList.flags
3075
+ )
3076
+ );
3077
+ changeTracker.insertNodeAfter(sourceFile, variableStatement, newConstDeclaration);
3078
+ changeTracker.insertText(sourceFile, variableStatement.end, "\n");
3079
+ }),
3080
+ provideService(TypeScriptApi, ts)
3081
+ )
3082
+ };
3083
+ })
3084
+ });
3085
+
2846
3086
  // src/refactors/pipeableToDatafirst.ts
2847
3087
  var pipeableToDatafirst = createRefactor({
2848
3088
  name: "effect/pipeableToDatafirst",
2849
3089
  description: "Rewrite to datafirst",
2850
- apply: (sourceFile, textRange) => gen2(function* () {
3090
+ apply: fn("pipeableToDatafirst.apply")(function* (sourceFile, textRange) {
2851
3091
  const ts = yield* service(TypeScriptApi);
2852
3092
  const typeChecker = yield* service(TypeCheckerApi);
2853
3093
  function isPipeCall(node2) {
@@ -2930,7 +3170,7 @@ var pipeableToDatafirst = createRefactor({
2930
3170
  var removeUnnecessaryEffectGen = createRefactor({
2931
3171
  name: "effect/removeUnnecessaryEffectGen",
2932
3172
  description: "Remove unnecessary Effect.gen",
2933
- apply: (sourceFile, textRange) => gen2(function* () {
3173
+ apply: fn("removeUnnecessaryEffectGen.apply")(function* (sourceFile, textRange) {
2934
3174
  for (const nodeToReplace of yield* getAncestorNodesInRange(sourceFile, textRange)) {
2935
3175
  const maybeNode = yield* pipe(
2936
3176
  effectGen(nodeToReplace),
@@ -2956,7 +3196,7 @@ var removeUnnecessaryEffectGen = createRefactor({
2956
3196
  var toggleLazyConst = createRefactor({
2957
3197
  name: "effect/toggleLazyConst",
2958
3198
  description: "Toggle lazy const",
2959
- apply: (sourceFile, textRange) => gen2(function* () {
3199
+ apply: fn("toggleLazyConst.apply")(function* (sourceFile, textRange) {
2960
3200
  const ts = yield* service(TypeScriptApi);
2961
3201
  const maybeNode = pipe(
2962
3202
  yield* getAncestorNodesInRange(sourceFile, textRange),
@@ -2996,7 +3236,7 @@ var toggleLazyConst = createRefactor({
2996
3236
  var toggleReturnTypeAnnotation = createRefactor({
2997
3237
  name: "effect/toggleReturnTypeAnnotation",
2998
3238
  description: "Toggle return type annotation",
2999
- apply: (sourceFile, textRange) => gen2(function* () {
3239
+ apply: fn("toggleReturnTypeAnnotation.apply")(function* (sourceFile, textRange) {
3000
3240
  const ts = yield* service(TypeScriptApi);
3001
3241
  const typeChecker = yield* service(TypeCheckerApi);
3002
3242
  const maybeNode = pipe(
@@ -3046,7 +3286,7 @@ var toggleReturnTypeAnnotation = createRefactor({
3046
3286
  var toggleTypeAnnotation = createRefactor({
3047
3287
  name: "effect/toggleTypeAnnotation",
3048
3288
  description: "Toggle type annotation",
3049
- apply: (sourceFile, textRange) => gen2(function* () {
3289
+ apply: fn("toggleTypeAnnotation.apply")(function* (sourceFile, textRange) {
3050
3290
  const ts = yield* service(TypeScriptApi);
3051
3291
  const typeChecker = yield* service(TypeCheckerApi);
3052
3292
  const maybeNode = pipe(
@@ -3103,11 +3343,76 @@ var toggleTypeAnnotation = createRefactor({
3103
3343
  })
3104
3344
  });
3105
3345
 
3346
+ // src/refactors/wrapWithEffectGen.ts
3347
+ var wrapWithEffectGen = createRefactor({
3348
+ name: "effect/wrapWithEffectGen",
3349
+ description: "Wrap with Effect.gen",
3350
+ apply: fn("wrapWithEffectGen.apply")(function* (sourceFile, textRange) {
3351
+ const ts = yield* service(TypeScriptApi);
3352
+ const typeChecker = yield* service(TypeCheckerApi);
3353
+ const findEffectToWrap = fn("wrapWithEffectGen.apply.findEffectToWrap")(
3354
+ function* (node) {
3355
+ if (!ts.isExpression(node)) return yield* fail("is not an expression");
3356
+ const parent = node.parent;
3357
+ if (parent != null && ts.isVariableDeclaration(parent) && parent.initializer !== node) return yield* fail("is LHS of variable declaration");
3358
+ const type = typeChecker.getTypeAtLocation(node);
3359
+ yield* effectType(type, node);
3360
+ return node;
3361
+ }
3362
+ );
3363
+ const maybeNode = yield* pipe(
3364
+ yield* getAncestorNodesInRange(sourceFile, textRange),
3365
+ map2(findEffectToWrap),
3366
+ firstSuccessOf,
3367
+ option
3368
+ );
3369
+ if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
3370
+ return {
3371
+ kind: "refactor.rewrite.effect.wrapWithEffectGen",
3372
+ description: `Wrap with Effect.gen`,
3373
+ apply: pipe(
3374
+ gen2(function* () {
3375
+ const changeTracker = yield* service(ChangeTracker);
3376
+ const effectGen2 = yield* pipe(
3377
+ createEffectGenCallExpressionWithBlock(
3378
+ yield* getEffectModuleIdentifierName(sourceFile),
3379
+ yield* createReturnYieldStarStatement(maybeNode.value)
3380
+ )
3381
+ );
3382
+ changeTracker.replaceNode(sourceFile, maybeNode.value, effectGen2);
3383
+ }),
3384
+ provideService(TypeScriptApi, ts),
3385
+ provideService(TypeCheckerApi, typeChecker)
3386
+ )
3387
+ };
3388
+ })
3389
+ });
3390
+ var getEffectModuleIdentifierName = fn("getEffectModuleIdentifierName")(
3391
+ function* (sourceFile) {
3392
+ return match2(
3393
+ yield* option(
3394
+ findImportedModuleIdentifier(
3395
+ sourceFile,
3396
+ (node) => pipe(
3397
+ importedEffectModule(node),
3398
+ option,
3399
+ map3(isSome2)
3400
+ )
3401
+ )
3402
+ ),
3403
+ {
3404
+ onNone: () => "Effect",
3405
+ onSome: (node) => node.text
3406
+ }
3407
+ );
3408
+ }
3409
+ );
3410
+
3106
3411
  // src/refactors/wrapWithPipe.ts
3107
3412
  var wrapWithPipe = createRefactor({
3108
3413
  name: "effect/wrapWithPipe",
3109
3414
  description: "Wrap with pipe",
3110
- apply: (sourceFile, textRange) => gen2(function* () {
3415
+ apply: fn("wrapWithPipe.apply")(function* (sourceFile, textRange) {
3111
3416
  if (textRange.end - textRange.pos === 0) {
3112
3417
  return yield* fail(new RefactorNotApplicableError());
3113
3418
  }
@@ -3128,11 +3433,13 @@ var refactors = [
3128
3433
  asyncAwaitToGen,
3129
3434
  asyncAwaitToGenTryPromise,
3130
3435
  functionToArrow,
3436
+ makeSchemaOpaque,
3131
3437
  pipeableToDatafirst,
3132
3438
  removeUnnecessaryEffectGen,
3133
3439
  toggleLazyConst,
3134
3440
  toggleReturnTypeAnnotation,
3135
3441
  toggleTypeAnnotation,
3442
+ wrapWithEffectGen,
3136
3443
  wrapWithPipe,
3137
3444
  effectGenToFn
3138
3445
  ];