@effect/language-service 0.14.0 → 0.15.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
@@ -46,10 +46,12 @@ Your `tsconfig.json` should look like this:
46
46
  }
47
47
  ```
48
48
 
49
+ To get diagnostics you need to install `ts-patch` which will make it possible to run `tspc`.
50
+
49
51
  Running `tspc` in your project will now also run the plugin and give you the diagnostics at compile time.
50
52
 
51
53
  ```ts
52
- $ npm tspc
54
+ $ npx tspc
53
55
  index.ts:3:1 - error TS3: Effect must be yielded or assigned to a variable.
54
56
 
55
57
  3 Effect.succeed(1)
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  var __defProp = Object.defineProperty;
3
- var __export = (target, all2) => {
4
- for (var name in all2)
5
- __defProp(target, name, { get: all2[name], enumerable: true });
3
+ var __export = (target, all3) => {
4
+ for (var name in all3)
5
+ __defProp(target, name, { get: all3[name], enumerable: true });
6
6
  };
7
7
 
8
8
  // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Function.js
@@ -1045,7 +1045,7 @@ var map3 = dual(2, (fa, f) => new Nano((ctx) => {
1045
1045
  }));
1046
1046
  var orElse3 = (f) => (fa) => new Nano((ctx) => {
1047
1047
  const result = fa.run(ctx);
1048
- if (result._tag === "Left") return f().run(ctx);
1048
+ if (result._tag === "Left") return f(result.left).run(ctx);
1049
1049
  return result;
1050
1050
  });
1051
1051
  var firstSuccessOf = (arr) => reduce(arr.slice(1), arr[0], (arr2, fa) => orElse3(() => fa)(arr2));
@@ -1095,6 +1095,14 @@ var option = (fa) => new Nano((ctx) => {
1095
1095
  return result;
1096
1096
  }
1097
1097
  });
1098
+ var all2 = (...args) => gen2(function* () {
1099
+ const results = [];
1100
+ for (const arg of args) {
1101
+ const result = yield* arg;
1102
+ results.push(result);
1103
+ }
1104
+ return results;
1105
+ });
1098
1106
 
1099
1107
  // src/core/TypeScriptApi.ts
1100
1108
  var TypeScriptApi = Tag("TypeScriptApi");
@@ -3511,6 +3519,460 @@ var toggleTypeAnnotation = createRefactor({
3511
3519
  })
3512
3520
  });
3513
3521
 
3522
+ // src/utils/SchemaGen.ts
3523
+ var TypeParametersNotSupportedError = class {
3524
+ constructor(node) {
3525
+ this.node = node;
3526
+ }
3527
+ _tag = "@effect/language-service/TypeParametersNotSupportedError";
3528
+ toString() {
3529
+ return `Could not process types with type parameters.`;
3530
+ }
3531
+ };
3532
+ var OnlyLiteralPropertiesSupportedError = class {
3533
+ constructor(node) {
3534
+ this.node = node;
3535
+ }
3536
+ _tag = "@effect/language-service/OnlyLiteralPropertiesSupportedError";
3537
+ toString() {
3538
+ return `Could not process ${this.node.getText()} as only literal properties are supported.`;
3539
+ }
3540
+ };
3541
+ var RequiredExplicitTypesError = class {
3542
+ constructor(node) {
3543
+ this.node = node;
3544
+ }
3545
+ _tag = "@effect/language-service/RequiredExplicitTypesError";
3546
+ toString() {
3547
+ return `Could not process ${this.node.getText()} as only explicit types are supported.`;
3548
+ }
3549
+ };
3550
+ var IndexSignatureWithMoreThanOneParameterError = class {
3551
+ constructor(node) {
3552
+ this.node = node;
3553
+ }
3554
+ _tag = "@effect/language-service/IndexSignatureWithMoreThanOneParameterError";
3555
+ toString() {
3556
+ return `Could not process ${this.node.getText()} as only index signatures with one parameter are supported.`;
3557
+ }
3558
+ };
3559
+ var SchemaGenContext = Tag("SchemaGenContext");
3560
+ var makeSchemaGenContext = fn("SchemaGen.makeSchemaGenContext")(function* (sourceFile) {
3561
+ const effectSchemaIdentifier = pipe(
3562
+ yield* option(
3563
+ findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Schema")
3564
+ ),
3565
+ match2({
3566
+ onNone: () => "Schema",
3567
+ onSome: (_) => _.text
3568
+ })
3569
+ );
3570
+ const moduleToImportedName = {};
3571
+ for (const moduleName of ["Option", "Either", "Chunk", "Duration"]) {
3572
+ const importedName = yield* option(
3573
+ findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", moduleName)
3574
+ );
3575
+ if (isSome2(importedName)) moduleToImportedName[moduleName] = importedName.value.text;
3576
+ }
3577
+ const ts = yield* service(TypeScriptApi);
3578
+ return {
3579
+ sourceFile,
3580
+ createApiPropertyAccess: (apiName) => ts.factory.createPropertyAccessExpression(
3581
+ ts.factory.createIdentifier(effectSchemaIdentifier),
3582
+ apiName
3583
+ ),
3584
+ createApiCall: (apiName, args) => ts.factory.createCallExpression(
3585
+ ts.factory.createPropertyAccessExpression(
3586
+ ts.factory.createIdentifier(effectSchemaIdentifier),
3587
+ apiName
3588
+ ),
3589
+ [],
3590
+ args
3591
+ ),
3592
+ entityNameToDataTypeName: (name) => {
3593
+ if (ts.isIdentifier(name)) {
3594
+ switch (name.text) {
3595
+ case "Date":
3596
+ case "Pick":
3597
+ case "Omit":
3598
+ return some2(name.text);
3599
+ case "ReadonlyArray":
3600
+ case "Array":
3601
+ return some2("Array");
3602
+ }
3603
+ return none2();
3604
+ }
3605
+ if (!ts.isIdentifier(name.left)) return none2();
3606
+ for (const moduleName in moduleToImportedName) {
3607
+ if (name.left.text === moduleToImportedName[moduleName] && name.right.text === moduleName) {
3608
+ return some2(moduleName);
3609
+ }
3610
+ }
3611
+ return none2();
3612
+ },
3613
+ ts
3614
+ };
3615
+ });
3616
+ var typeEntityNameToNode = fn(
3617
+ "SchemaGen.typeEntityNameToNode"
3618
+ )(
3619
+ function* (entityName) {
3620
+ const { ts } = yield* service(SchemaGenContext);
3621
+ if (ts.isIdentifier(entityName)) return ts.factory.createIdentifier(entityName.text);
3622
+ const left3 = yield* typeEntityNameToNode(entityName.left);
3623
+ return ts.factory.createPropertyAccessExpression(
3624
+ left3,
3625
+ ts.factory.createIdentifier(entityName.right.text)
3626
+ );
3627
+ }
3628
+ );
3629
+ var parseAllLiterals = fn(
3630
+ "SchemaGen.parseAllLiterals"
3631
+ )(
3632
+ function* (node) {
3633
+ const { ts } = yield* service(SchemaGenContext);
3634
+ if (ts.isLiteralTypeNode(node) && node.literal.kind === ts.SyntaxKind.StringLiteral) {
3635
+ return [ts.factory.createStringLiteral(node.literal.text)];
3636
+ }
3637
+ if (ts.isUnionTypeNode(node)) {
3638
+ return flatten(yield* all2(...node.types.map((_) => parseAllLiterals(_))));
3639
+ }
3640
+ if (ts.isParenthesizedTypeNode(node)) {
3641
+ return yield* parseAllLiterals(node.type);
3642
+ }
3643
+ return yield* fail(node);
3644
+ }
3645
+ );
3646
+ var createUnsupportedNodeComment = (ts, sourceFile, node) => ts.addSyntheticTrailingComment(
3647
+ ts.factory.createIdentifier(""),
3648
+ ts.SyntaxKind.MultiLineCommentTrivia,
3649
+ " Not supported conversion: " + node.getText(sourceFile) + " "
3650
+ );
3651
+ var processNode = (node) => gen2(function* () {
3652
+ const { createApiCall, createApiPropertyAccess, entityNameToDataTypeName, sourceFile, ts } = yield* service(
3653
+ SchemaGenContext
3654
+ );
3655
+ switch (node.kind) {
3656
+ case ts.SyntaxKind.AnyKeyword:
3657
+ return createApiPropertyAccess("Any");
3658
+ case ts.SyntaxKind.NeverKeyword:
3659
+ return createApiPropertyAccess("Never");
3660
+ case ts.SyntaxKind.UnknownKeyword:
3661
+ return createApiPropertyAccess("Unknown");
3662
+ case ts.SyntaxKind.VoidKeyword:
3663
+ return createApiPropertyAccess("Void");
3664
+ case ts.SyntaxKind.NullKeyword:
3665
+ return createApiPropertyAccess("Null");
3666
+ case ts.SyntaxKind.UndefinedKeyword:
3667
+ return createApiPropertyAccess("Undefined");
3668
+ case ts.SyntaxKind.StringKeyword:
3669
+ return createApiPropertyAccess("String");
3670
+ case ts.SyntaxKind.NumberKeyword:
3671
+ return createApiPropertyAccess("Number");
3672
+ case ts.SyntaxKind.BooleanKeyword:
3673
+ return createApiPropertyAccess("Boolean");
3674
+ case ts.SyntaxKind.BigIntKeyword:
3675
+ return createApiPropertyAccess("BigInt");
3676
+ }
3677
+ if (ts.isLiteralTypeNode(node)) {
3678
+ switch (node.literal.kind) {
3679
+ case ts.SyntaxKind.NullKeyword:
3680
+ return createApiPropertyAccess("Null");
3681
+ case ts.SyntaxKind.TrueKeyword:
3682
+ return createApiCall("Literal", [ts.factory.createTrue()]);
3683
+ case ts.SyntaxKind.FalseKeyword:
3684
+ return createApiCall("Literal", [ts.factory.createFalse()]);
3685
+ case ts.SyntaxKind.StringLiteral:
3686
+ return createApiCall("Literal", [ts.factory.createStringLiteral(node.literal.text)]);
3687
+ case ts.SyntaxKind.NumericLiteral:
3688
+ return createApiCall("Literal", [ts.factory.createNumericLiteral(node.literal.text)]);
3689
+ }
3690
+ }
3691
+ if (ts.isUnionTypeNode(node)) {
3692
+ const members = yield* all2(...node.types.map((_) => processNode(_)));
3693
+ return createApiCall("Union", members);
3694
+ }
3695
+ if (ts.isArrayTypeNode(node)) {
3696
+ const typeSchema = yield* processNode(node.elementType);
3697
+ return createApiCall("Array", [typeSchema]);
3698
+ }
3699
+ if (ts.isTypeLiteralNode(node)) {
3700
+ const { properties, records } = yield* processMembers(node.members);
3701
+ return createApiCall(
3702
+ "Struct",
3703
+ [ts.factory.createObjectLiteralExpression(properties, true)].concat(records)
3704
+ );
3705
+ }
3706
+ if (ts.isTypeReferenceNode(node)) {
3707
+ const parsedName = entityNameToDataTypeName(node.typeName);
3708
+ if (isSome2(parsedName)) {
3709
+ switch (parsedName.value) {
3710
+ case "Duration":
3711
+ case "Date":
3712
+ return createApiPropertyAccess(parsedName.value);
3713
+ case "Option":
3714
+ case "Chunk":
3715
+ case "Array": {
3716
+ const elements = yield* all2(
3717
+ ...node.typeArguments ? node.typeArguments.map(processNode) : []
3718
+ );
3719
+ return createApiCall(parsedName.value, elements);
3720
+ }
3721
+ case "Either": {
3722
+ const elements = yield* all2(
3723
+ ...node.typeArguments ? node.typeArguments.map(processNode) : []
3724
+ );
3725
+ if (elements.length >= 2) {
3726
+ return createApiCall(parsedName.value, [
3727
+ ts.factory.createObjectLiteralExpression([
3728
+ ts.factory.createPropertyAssignment("right", elements[0]),
3729
+ ts.factory.createPropertyAssignment("left", elements[1])
3730
+ ])
3731
+ ]);
3732
+ }
3733
+ return createUnsupportedNodeComment(ts, sourceFile, node);
3734
+ }
3735
+ case "Pick":
3736
+ case "Omit": {
3737
+ const typeArguments = fromIterable(node.typeArguments || []);
3738
+ if (typeArguments.length !== 2) {
3739
+ return createUnsupportedNodeComment(ts, sourceFile, node);
3740
+ }
3741
+ const baseType = yield* processNode(typeArguments[0]);
3742
+ const stringLiteralArguments = yield* option(parseAllLiterals(typeArguments[1]));
3743
+ if (isNone2(stringLiteralArguments)) {
3744
+ return createUnsupportedNodeComment(ts, sourceFile, node);
3745
+ }
3746
+ return ts.factory.createCallExpression(
3747
+ ts.factory.createPropertyAccessExpression(
3748
+ baseType,
3749
+ "pipe"
3750
+ ),
3751
+ [],
3752
+ [createApiCall(parsedName.value.toLowerCase(), stringLiteralArguments.value)]
3753
+ );
3754
+ }
3755
+ }
3756
+ }
3757
+ }
3758
+ if (ts.isTypeReferenceNode(node)) {
3759
+ if (!(node.typeArguments && node.typeArguments.length > 0)) {
3760
+ return yield* typeEntityNameToNode(node.typeName);
3761
+ }
3762
+ }
3763
+ return createUnsupportedNodeComment(ts, sourceFile, node);
3764
+ });
3765
+ var processMembers = fn(
3766
+ "SchemaGen.processMembers"
3767
+ )(
3768
+ function* (members) {
3769
+ const { createApiCall, ts } = yield* service(
3770
+ SchemaGenContext
3771
+ );
3772
+ const properties = [];
3773
+ for (const propertySignature of members.filter(ts.isPropertySignature)) {
3774
+ const name = propertySignature.name;
3775
+ if (!(ts.isIdentifier(name) || ts.isStringLiteral(name))) {
3776
+ return yield* fail(new OnlyLiteralPropertiesSupportedError(propertySignature));
3777
+ }
3778
+ if (!propertySignature.type) {
3779
+ return yield* fail(new RequiredExplicitTypesError(propertySignature));
3780
+ }
3781
+ const propertyAssignment = pipe(
3782
+ yield* processNode(propertySignature.type),
3783
+ propertySignature.questionToken ? (_) => createApiCall("optional", [_]) : identity,
3784
+ (_) => ts.factory.createPropertyAssignment(name, _)
3785
+ );
3786
+ properties.push(propertyAssignment);
3787
+ }
3788
+ const records = [];
3789
+ for (const indexSignature of members.filter(ts.isIndexSignatureDeclaration)) {
3790
+ if (indexSignature.parameters.length !== 1) {
3791
+ return yield* fail(new IndexSignatureWithMoreThanOneParameterError(indexSignature));
3792
+ }
3793
+ const parameter = indexSignature.parameters[0];
3794
+ if (!parameter.type) return yield* fail(new RequiredExplicitTypesError(parameter));
3795
+ const parameterType = parameter.type;
3796
+ const key = yield* processNode(parameterType);
3797
+ const value = yield* processNode(indexSignature.type);
3798
+ records.push(
3799
+ ts.factory.createObjectLiteralExpression([
3800
+ ts.factory.createPropertyAssignment("key", key),
3801
+ ts.factory.createPropertyAssignment("value", value)
3802
+ ])
3803
+ );
3804
+ }
3805
+ return { properties, records };
3806
+ }
3807
+ );
3808
+ var processInterfaceDeclaration = fn("SchemaGen.processInterfaceDeclaration")(
3809
+ function* (node, preferClass) {
3810
+ if (node.typeParameters && node.typeParameters.length > 0) {
3811
+ return yield* fail(new TypeParametersNotSupportedError(node));
3812
+ }
3813
+ const { createApiCall, ts } = yield* service(
3814
+ SchemaGenContext
3815
+ );
3816
+ const { properties, records } = yield* processMembers(node.members);
3817
+ if (preferClass && records.length === 0) {
3818
+ return yield* createExportSchemaClassDeclaration(node.name.text, properties);
3819
+ }
3820
+ const schemaStruct = createApiCall(
3821
+ "Struct",
3822
+ [ts.factory.createObjectLiteralExpression(properties, true)].concat(records)
3823
+ );
3824
+ return yield* createExportVariableDeclaration(node.name.text, schemaStruct);
3825
+ }
3826
+ );
3827
+ var processTypeAliasDeclaration = fn("SchemaGen.processInterfaceDeclaration")(
3828
+ function* (node, preferClass) {
3829
+ const { ts } = yield* service(SchemaGenContext);
3830
+ if (node.typeParameters && node.typeParameters.length > 0) {
3831
+ return yield* fail(new TypeParametersNotSupportedError(node));
3832
+ }
3833
+ if (preferClass && ts.isTypeLiteralNode(node.type)) {
3834
+ const { properties, records } = yield* processMembers(node.type.members);
3835
+ if (records.length === 0) {
3836
+ return yield* createExportSchemaClassDeclaration(node.name.text, properties);
3837
+ }
3838
+ }
3839
+ const effectSchema = yield* processNode(node.type);
3840
+ return yield* createExportVariableDeclaration(node.name.text, effectSchema);
3841
+ }
3842
+ );
3843
+ var createExportVariableDeclaration = fn("SchemaGen.createExportVariableDeclaration")(
3844
+ function* (name, initializer) {
3845
+ const ts = yield* service(TypeScriptApi);
3846
+ return ts.factory.createVariableStatement(
3847
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
3848
+ ts.factory.createVariableDeclarationList([
3849
+ ts.factory.createVariableDeclaration(
3850
+ ts.factory.createIdentifier(name),
3851
+ void 0,
3852
+ void 0,
3853
+ initializer
3854
+ )
3855
+ ], ts.NodeFlags.Const)
3856
+ );
3857
+ }
3858
+ );
3859
+ var createExportSchemaClassDeclaration = fn("SchemaGen.createExportSchemaClassDeclaration")(
3860
+ function* (name, members) {
3861
+ const { createApiPropertyAccess } = yield* service(SchemaGenContext);
3862
+ const ts = yield* service(TypeScriptApi);
3863
+ return ts.factory.createClassDeclaration(
3864
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
3865
+ ts.factory.createIdentifier(name),
3866
+ [],
3867
+ [ts.factory.createHeritageClause(
3868
+ ts.SyntaxKind.ExtendsKeyword,
3869
+ [
3870
+ ts.factory.createExpressionWithTypeArguments(
3871
+ ts.factory.createCallExpression(
3872
+ ts.factory.createCallExpression(
3873
+ createApiPropertyAccess("Class"),
3874
+ [ts.factory.createTypeReferenceNode(
3875
+ name
3876
+ )],
3877
+ [ts.factory.createStringLiteral(name)]
3878
+ ),
3879
+ [],
3880
+ [ts.factory.createObjectLiteralExpression(
3881
+ members,
3882
+ true
3883
+ )]
3884
+ ),
3885
+ []
3886
+ )
3887
+ ]
3888
+ )],
3889
+ []
3890
+ );
3891
+ }
3892
+ );
3893
+ var process = fn("SchemaGen.process")(
3894
+ function* (sourceFile, node, preferClass) {
3895
+ const ctx = yield* makeSchemaGenContext(sourceFile);
3896
+ const ts = yield* service(TypeScriptApi);
3897
+ return yield* pipe(
3898
+ ts.isInterfaceDeclaration(node) ? processInterfaceDeclaration(node, preferClass) : processTypeAliasDeclaration(node, preferClass),
3899
+ provideService(SchemaGenContext, ctx)
3900
+ );
3901
+ }
3902
+ );
3903
+ var findNodeToProcess = fn("SchemaGen.findNodeToProcess")(
3904
+ function* (sourceFile, textRange) {
3905
+ const ts = yield* service(TypeScriptApi);
3906
+ return pipe(
3907
+ yield* getAncestorNodesInRange(sourceFile, textRange),
3908
+ filter((node) => ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)),
3909
+ filter((node) => isNodeInRange(textRange)(node.name)),
3910
+ filter((node) => (node.typeParameters || []).length === 0),
3911
+ head
3912
+ );
3913
+ }
3914
+ );
3915
+ var applyAtNode = fn("SchemaGen.applyAtNode")(
3916
+ function* (sourceFile, node, preferClass) {
3917
+ const ts = yield* service(TypeScriptApi);
3918
+ const changeTracker = yield* service(ChangeTracker);
3919
+ const newNode = yield* pipe(
3920
+ process(sourceFile, node, preferClass),
3921
+ orElse3(
3922
+ (error) => succeed(ts.addSyntheticLeadingComment(
3923
+ ts.factory.createIdentifier(""),
3924
+ ts.SyntaxKind.MultiLineCommentTrivia,
3925
+ " " + String(error) + " ",
3926
+ true
3927
+ ))
3928
+ )
3929
+ );
3930
+ changeTracker.insertNodeBefore(sourceFile, node, newNode, true, {
3931
+ leadingTriviaOption: ts.textChanges.LeadingTriviaOption.StartLine
3932
+ });
3933
+ }
3934
+ );
3935
+
3936
+ // src/refactors/typeToEffectSchema.ts
3937
+ var typeToEffectSchema = createRefactor({
3938
+ name: "effect/typeToEffectSchema",
3939
+ description: "Refactor to Schema",
3940
+ apply: fn("typeToEffectSchema.apply")(function* (sourceFile, textRange) {
3941
+ const ts = yield* service(TypeScriptApi);
3942
+ const maybeNode = yield* findNodeToProcess(sourceFile, textRange);
3943
+ if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
3944
+ const node = maybeNode.value;
3945
+ return {
3946
+ kind: "refactor.rewrite.effect.typeToEffectSchema",
3947
+ description: "Refactor to Schema",
3948
+ apply: pipe(
3949
+ applyAtNode(sourceFile, node, false),
3950
+ provideService(TypeScriptApi, ts)
3951
+ )
3952
+ };
3953
+ })
3954
+ });
3955
+
3956
+ // src/refactors/typeToEffectSchemaClass.ts
3957
+ var typeToEffectSchemaClass = createRefactor({
3958
+ name: "effect/typeToEffectSchemaClass",
3959
+ description: "Refactor to Schema.Class",
3960
+ apply: fn("typeToEffectSchemaClass.apply")(function* (sourceFile, textRange) {
3961
+ const ts = yield* service(TypeScriptApi);
3962
+ const maybeNode = yield* findNodeToProcess(sourceFile, textRange);
3963
+ if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
3964
+ const node = maybeNode.value;
3965
+ return {
3966
+ kind: "refactor.rewrite.effect.typeToEffectSchemaClass",
3967
+ description: "Refactor to Schema.Class",
3968
+ apply: pipe(
3969
+ applyAtNode(sourceFile, node, true),
3970
+ provideService(TypeScriptApi, ts)
3971
+ )
3972
+ };
3973
+ })
3974
+ });
3975
+
3514
3976
  // src/refactors/wrapWithEffectGen.ts
3515
3977
  var wrapWithEffectGen = createRefactor({
3516
3978
  name: "effect/wrapWithEffectGen",
@@ -3601,6 +4063,8 @@ var refactors = [
3601
4063
  asyncAwaitToGen,
3602
4064
  asyncAwaitToGenTryPromise,
3603
4065
  functionToArrow,
4066
+ typeToEffectSchema,
4067
+ typeToEffectSchemaClass,
3604
4068
  makeSchemaOpaque,
3605
4069
  makeSchemaOpaqueWithNs,
3606
4070
  pipeableToDatafirst,