diff --git a/.changeset/update-effect-beta-19.md b/.changeset/update-effect-beta-19.md new file mode 100644 index 00000000..da376d51 --- /dev/null +++ b/.changeset/update-effect-beta-19.md @@ -0,0 +1,9 @@ +--- +"@effect/language-service": patch +--- + +Update effect dependency to v4.0.0-beta.19 and fix compatibility issues: + +- Fix `layerMagic` refactor producing `any` types in Layer channels by replacing `Array.partition` (which now uses the v4 `Filter.Filter` API) with a native loop for boolean partition logic +- Add v4 Layer type detection shortcut using `"~effect/Layer"` TypeId property, matching the pattern already used for Effect type detection +- Mark `Effect.filterMap` as unchanged in the outdated API migration database since it was re-added in v4 diff --git a/packages/harness-effect-v4/package.json b/packages/harness-effect-v4/package.json index b2403b40..26d68b02 100644 --- a/packages/harness-effect-v4/package.json +++ b/packages/harness-effect-v4/package.json @@ -5,7 +5,7 @@ "check": "tsc -b tsconfig.json" }, "dependencies": { - "effect": "^4.0.0-beta.14", + "effect": "^4.0.0-beta.19", "@standard-schema/spec": "^1.1.0" } } diff --git a/packages/language-service/package.json b/packages/language-service/package.json index 83d9cdf5..c85218d1 100644 --- a/packages/language-service/package.json +++ b/packages/language-service/package.json @@ -43,9 +43,9 @@ "devDependencies": { "pako": "^2.1.0", "@typescript-eslint/project-service": "^8.52.0", - "@effect/platform-node": "^4.0.0-beta.14", + "@effect/platform-node": "^4.0.0-beta.19", "@types/pako": "^2.0.4", - "effect": "^4.0.0-beta.14", + "effect": "^4.0.0-beta.19", "ts-patch": "^3.3.0" } } diff --git a/packages/language-service/src/core/TypeParser.ts b/packages/language-service/src/core/TypeParser.ts index f9af4aca..e0515819 100644 --- a/packages/language-service/src/core/TypeParser.ts +++ b/packages/language-service/src/core/TypeParser.ts @@ -860,6 +860,16 @@ export function make( // should be pipeable yield* pipeableType(type, atLocation) + if (supportedEffect() === "v4") { + // Effect v4 TypeId shortcut + const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Layer") + if (typeIdSymbol) { + const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation) + return yield* layerVarianceStruct(typeIdType, atLocation) + } + return yield* typeParserIssue("Type is not a layer", type, atLocation) + } + // get the properties to check (exclude non-property and optional properties) const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter((_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration diff --git a/packages/language-service/src/diagnostics/outdatedApi.db.ts b/packages/language-service/src/diagnostics/outdatedApi.db.ts index 17509fef..ae5b0c67 100644 --- a/packages/language-service/src/diagnostics/outdatedApi.db.ts +++ b/packages/language-service/src/diagnostics/outdatedApi.db.ts @@ -75,9 +75,7 @@ export const effectModuleMigrationDb: ModuleMigrationDb = { "failSync": asUnchanged, "fiberId": asUnchanged, "filter": asUnchanged, - "filterMap": asRemoved( - "Use Effect.filter or Effect.map with Option instead." - ), + "filterMap": asUnchanged, "filterOrElse": asUnchanged, "filterOrFail": asUnchanged, "flatMap": asUnchanged, diff --git a/packages/language-service/src/refactors/layerMagic.ts b/packages/language-service/src/refactors/layerMagic.ts index 6daba08c..44a3ea3e 100644 --- a/packages/language-service/src/refactors/layerMagic.ts +++ b/packages/language-service/src/refactors/layerMagic.ts @@ -82,13 +82,19 @@ export const layerMagic = LSP.createRefactor({ Nano.option ) - const [existingBefore, newlyIntroduced] = pipe( + const sorted = pipe( Array.fromIterable(layerOutputTypes), - Array.sort(typeCheckerUtils.deterministicTypeOrder), - Array.partition((_) => - Option.isNone(previouslyProvided) || typeChecker.isTypeAssignableTo(_, previouslyProvided.value) - ) + Array.sort(typeCheckerUtils.deterministicTypeOrder) ) + const existingBefore: Array = [] + const newlyIntroduced: Array = [] + for (const t of sorted) { + if (Option.isNone(previouslyProvided) || typeChecker.isTypeAssignableTo(t, previouslyProvided.value)) { + newlyIntroduced.push(t) + } else { + existingBefore.push(t) + } + } const typeReferences = pipe( newlyIntroduced, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd07a613..329b4eb9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,14 +120,14 @@ importers: specifier: ^1.1.0 version: 1.1.0 effect: - specifier: ^4.0.0-beta.14 - version: 4.0.0-beta.14 + specifier: ^4.0.0-beta.19 + version: 4.0.0-beta.19 packages/language-service: devDependencies: '@effect/platform-node': - specifier: ^4.0.0-beta.14 - version: 4.0.0-beta.14(effect@4.0.0-beta.14)(ioredis@5.9.3) + specifier: ^4.0.0-beta.19 + version: 4.0.0-beta.19(effect@4.0.0-beta.19)(ioredis@5.9.3) '@types/pako': specifier: ^2.0.4 version: 2.0.4 @@ -135,8 +135,8 @@ importers: specifier: ^8.52.0 version: 8.52.0(typescript@5.9.3) effect: - specifier: ^4.0.0-beta.14 - version: 4.0.0-beta.14 + specifier: ^4.0.0-beta.19 + version: 4.0.0-beta.19 pako: specifier: ^2.1.0 version: 2.1.0 @@ -567,29 +567,29 @@ packages: uuid: 11.1.0 dev: false - /@effect/platform-node-shared@4.0.0-beta.14(effect@4.0.0-beta.14): - resolution: {integrity: sha512-rkbflXMBJrugRvTzlqAyLbwGunqtrc9Xv9wY3YnpaxovgzGm1+l7FKZCkeBdtkc4wYkS79ygHVmsSUnOeSTf/Q==} + /@effect/platform-node-shared@4.0.0-beta.19(effect@4.0.0-beta.19): + resolution: {integrity: sha512-548wlbHgtLcsZicSnzU2IDHNDGPSR+Tv8Ovg9TkMLSClbyyUIw/NtL5krwWjwHzOytXpVNsh/odsDwqcotm+HA==} engines: {node: '>=18.0.0'} peerDependencies: - effect: ^4.0.0-beta.14 + effect: ^4.0.0-beta.19 dependencies: '@types/ws': 8.18.1 - effect: 4.0.0-beta.14 + effect: 4.0.0-beta.19 ws: 8.19.0 transitivePeerDependencies: - bufferutil - utf-8-validate dev: true - /@effect/platform-node@4.0.0-beta.14(effect@4.0.0-beta.14)(ioredis@5.9.3): - resolution: {integrity: sha512-q+3DIPsetQ+qTJC68KAEy7MnRn+Utx/Voj/DYW+neuxi48rreA6YmTdQYALoV5YZrLhSRYBd+TsJAgkFu1gxCg==} + /@effect/platform-node@4.0.0-beta.19(effect@4.0.0-beta.19)(ioredis@5.9.3): + resolution: {integrity: sha512-iXloZO3s+eq2Ik30SIxgy1jTDwhUMlC7qsNLxkjyv8127NRWx1+YBjT4osyRdL/tRBrFDAlZwPpFnhilZ7eaew==} engines: {node: '>=18.0.0'} peerDependencies: - effect: ^4.0.0-beta.14 + effect: ^4.0.0-beta.19 ioredis: ^5.7.0 dependencies: - '@effect/platform-node-shared': 4.0.0-beta.14(effect@4.0.0-beta.14) - effect: 4.0.0-beta.14 + '@effect/platform-node-shared': 4.0.0-beta.19(effect@4.0.0-beta.19) + effect: 4.0.0-beta.19 ioredis: 5.9.3 mime: 4.1.0 undici: 7.22.0 @@ -2821,8 +2821,8 @@ packages: fast-check: 3.23.2 dev: false - /effect@4.0.0-beta.14: - resolution: {integrity: sha512-3er8DIukOoOpJc2qCRqejpzBGoUdG1t8pXcvA9blttSP9nxs7Ue6BkOLSQBaq3yIXWUXmL5GPELnDARP5oMbfQ==} + /effect@4.0.0-beta.19: + resolution: {integrity: sha512-SzlmpRx2floIefRnxdyWYi1VRU3e2WD7Xp17FG6kJ6sfI4KbgTT7J7JqOnsGqlFvc+Yuz2xWnOXlevYjE7jLxg==} dependencies: '@standard-schema/spec': 1.1.0 fast-check: 4.5.3