Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
6 changes: 6 additions & 0 deletions .changeset/update-effect-4.0.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"effect-app": patch
"@effect-app/cli": patch
---

Upgrade Effect packages to npm `4.0.0`.
3 changes: 3 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"effecttsgo/schema-sync-in-effect": "off",
"effecttsgo/strict-effect-provide": "off",
"effecttsgo/unsafe-effect-type-assertion": "off",
"effecttsgo/unstable-api-usage": "off",
"effecttsgo/floating-effect": "off",
"effecttsgo/multiple-effect-provide": "off",
"effecttsgo/unknown-in-effect-catch": "off",
"effecttsgo/missing-effect-service-dependency": "error",
"effecttsgo/effect-fn-opportunity": "warn",
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@
"@effect-app/cli": "2.1.0-beta.35",
"@effect-app/eslint-codegen-model": "workspace:*",
"@effect-app/infra": "workspace:*",
"@effect/language-service": "0.87.2",
"@effect/tsgo": "^0.45.0",
"@effect/platform-node": "4.0.0-rc.115",
"@effect/vitest": "4.0.0-rc.115",
"@effect/language-service": "0.87.3",
"@effect/tsgo": "^0.47.2",
"@effect/platform-node": "4.0.0",
"@effect/vitest": "4.0.0",
"@tsconfig/strictest": "^2.0.8",
"@types/node": "25.9.1",
"@typescript-eslint/eslint-plugin": "8.60.0",
"@typescript-eslint/parser": "8.60.0",
"@typescript/native-preview": "7.0.0-dev.20260626.1",
"dprint": "^0.54.0",
"effect": "4.0.0-rc.115",
"effect": "4.0.0",
"effect-app": "workspace:*",
"eslint": "^10.4.1",
"json5": "^2.2.3",
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"effect-app-cli": "./bin.js"
},
"dependencies": {
"@effect/platform-node": "4.0.0-rc.115",
"effect": "4.0.0-rc.115",
"@effect/platform-node": "4.0.0",
"effect": "4.0.0",
"js-yaml": "4.2.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/argv-patch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Join wrap args into a single argv element so that
// `effect-app-cli index-multi tsc --build` works without quoting.
// The new effect/unstable/cli lexer classifies --flags as LongOption tokens
// The new effect/cli lexer classifies --flags as LongOption tokens
// and discards unrecognized ones at the subcommand level.
// By joining all args after the subcommand into one string, the lexer
// sees a single Value token instead of separate LongOption tokens.
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* eslint-disable no-empty-pattern */
// import necessary modules from the libraries
import { NodeRuntime, NodeServices } from "@effect/platform-node"
import { Argument, Command, Flag, Prompt } from "effect/unstable/cli"
import { Argument, Command, Flag, Prompt } from "effect/cli"

import * as Effect from "effect/Effect"
import * as FileSystem from "effect/FileSystem"
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/os-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"
import { ChildProcess } from "effect/unstable/process"
import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
import { ChildProcess } from "effect/process"
import { ChildProcessSpawner } from "effect/process/ChildProcessSpawner"

/**
* Service for executing shell commands using the Effect platform's Command API.
Expand Down
8 changes: 4 additions & 4 deletions packages/e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"effect-app": "workspace:*"
},
"devDependencies": {
"@effect/atom-vue": "^4.0.0-rc.115",
"@effect/platform-node": "4.0.0-rc.115",
"@effect/vitest": "4.0.0-rc.115",
"@effect/atom-vue": "^4.0.0",
"@effect/platform-node": "4.0.0",
"@effect/vitest": "4.0.0",
"@tanstack/vue-query": "5.96.2",
"@types/node": "25.9.1",
"@vitejs/plugin-vue": "^6.0.7",
"effect": "^4.0.0-rc.115",
"effect": "^4.0.0",
"typescript": "~6.0.3",
"vitest": "^4.1.7",
"vue": "^3.5.35"
Expand Down
8 changes: 4 additions & 4 deletions packages/e2e/test/repoInvalidation.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import { DefaultGenericMiddlewares } from "effect-app/middleware"
import { makeRepo, RepositoryRegistryLive } from "effect-app/Model"
import { MiddlewareMaker, RpcContextMap, RpcMiddleware } from "effect-app/rpc"
import * as S from "effect-app/Schema"
import { FetchHttpClient } from "effect/http"
import * as ManagedRuntime from "effect/ManagedRuntime"
import * as NetAddress from "effect/net/NetAddress"
import * as Option from "effect/Option"
import * as Reactivity from "effect/reactivity/Reactivity"
import { RpcSerialization } from "effect/rpc"
import * as Scope from "effect/Scope"
import { FetchHttpClient } from "effect/unstable/http"
import * as NetAddress from "effect/unstable/net/NetAddress"
import * as Reactivity from "effect/unstable/reactivity/Reactivity"
import { RpcSerialization } from "effect/unstable/rpc"
import { createServer } from "http"
import { createApp, effectScope, ref } from "vue"
import { RequestContextMiddleware } from "../../infra/src/internal/RequestContextMiddleware.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/effect-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"vitest": "^4.1.7"
},
"peerDependencies": {
"effect": "^4.0.0-rc.115"
"effect": "^4.0.0"
},
"typesVersions": {
"*": {
Expand Down
26 changes: 13 additions & 13 deletions packages/effect-app/src/Schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as S from "effect/Schema"
import * as EffectSchemaParser from "effect/SchemaParser"
import { type Simplify } from "effect/Struct"
import type * as Tracer from "effect/Tracer"
import type { RequiredKeys } from "effect/Types"
Expand All @@ -10,7 +11,7 @@ import type { FC } from "./Schema/FastCheck.ts"
import { PhoneNumber as PhoneNumberT, type PhoneNumber as PhoneNumberType } from "./Schema/phoneNumber.ts"
import { type AST } from "./Schema/schema.ts"
import * as SchemaAST from "./SchemaAST.ts"
import { copy, extendM, type StructuralCopyOrigin } from "./utils.ts"
import { copy, defineOwn, extendM, type StructuralCopyOrigin } from "./utils.ts"

// ---------------------------------------------------------------------------
// Default helpers — re-exported from effect/Schema
Expand Down Expand Up @@ -158,18 +159,17 @@ export function Struct<const Fields extends S.Struct.Fields>(
const result = S.Struct(fields).annotate(concurrencyUnbounded)
const allowVoidMake = (schema: any): any => {
// Normalize omitted input to an empty object so optional/default-only structs can be constructed with make().
const origMake: any = schema.make
const origMakeOption: any = schema.makeOption
const origMakeEffect: any = schema.makeEffect
schema.make = function(this: any, input: any, options?: any) {
return origMake.call(this, input === undefined ? {} : input, options)
}
schema.makeOption = function(this: any, input: any, options?: any) {
return origMakeOption.call(this, input === undefined ? {} : input, options)
}
schema.makeEffect = function(this: any, input: any, options?: any) {
return origMakeEffect.call(this, input === undefined ? {} : input, options)
}
// Do not read schema.make first: Effect 4 caches it as a non-writable own property.
const origMake = EffectSchemaParser.make(schema)
const origMakeOption = EffectSchemaParser.makeOption(schema)
const origMakeEffect = EffectSchemaParser.makeEffect(schema)
const wrap = (orig: (input: any, options?: any) => any) =>
function(this: any, input: any, options?: any) {
return orig.call(this, input === undefined ? {} : input, options)
}
defineOwn(schema, "make", wrap(origMake))
defineOwn(schema, "makeOption", wrap(origMakeOption))
defineOwn(schema, "makeEffect", wrap(origMakeEffect))
return schema
}
// eslint-disable-next-line @typescript-eslint/unbound-method, @typescript-eslint/no-unsafe-assignment
Expand Down
2 changes: 1 addition & 1 deletion packages/effect-app/src/Schema/SpecialOpenApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* Usage with the OpenApi `Transform` annotation:
*
* ```ts
* import { OpenApi } from "effect/unstable"
* import { OpenApi } from "effect/http-api"
* import { deduplicateOpenApiSchemas } from "./SpecialOpenApi.ts"
*
* const api = HttpApi.make("myApi")
Expand Down
6 changes: 3 additions & 3 deletions packages/effect-app/src/Schema/brand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ export interface BrandedSchema<S extends S.Top, C extends B.Brand<any>> extends
{}

export const fromBrand = <C extends B.Brand<any>>(
constructor: Constructor<C>,
_constructor: Constructor<C>,
options?: BrandAnnotations
) =>
<Self extends S.Top>(self: Self): BrandedSchema<Self, C> => {
const branded = S.fromBrand(options?.identifier ?? "Brand", constructor as any)(self as any)
return options ? (branded as any).pipe(S.annotate(options)) : branded as any
const branded = self.pipe(S.brand("Brand"))
return (options ? branded.pipe(S.annotate(options)) : branded) as BrandedSchema<Self, C>
}

export type Brands<P> = P extends B.Brand<any> ? B.Brand.Brands<P>
Expand Down
3 changes: 2 additions & 1 deletion packages/effect-app/src/Schema/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export const Email = S
S.refine(isValidEmail as Refinement<string, Email>, {
identifier: "Email",
description: "an email according to RFC 5322",
jsonSchema: { format: "email", minLength: 3, maxLength: 998 },
// JSON Schema minLength counts code points; isMinLength(3) is UTF-16 units (ceil(3/2)=2).
jsonSchema: { format: "email", minLength: 2, maxLength: 998 },
// Native Arbitrary cannot invert `isValidEmail`; without a constraint, rejection sampling
// discards (almost) every random string.
arbitraryConstraint: {
Expand Down
2 changes: 1 addition & 1 deletion packages/effect-app/src/client/apiClientFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import * as Layer from "effect/Layer"
import * as ManagedRuntime from "effect/ManagedRuntime"
import * as Option from "effect/Option"
import * as Predicate from "effect/Predicate"
import { Rpc, RpcClient, RpcGroup, RpcSerialization } from "effect/rpc"
import * as Schema from "effect/Schema"
import * as Stream from "effect/Stream"
import * as Struct from "effect/Struct"
import { Rpc, RpcClient, RpcGroup, RpcSerialization } from "effect/unstable/rpc"
import * as Config from "../Config.ts"
import * as Context from "../Context.ts"
import * as DataDependencies from "../DataDependencies.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/effect-app/src/http/Request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { HttpClientResponse } from "effect/http/HttpClientResponse"
import * as Option from "effect/Option"
import type { HttpClientResponse } from "effect/unstable/http/HttpClientResponse"
import * as Effect from "../Effect.ts"
import { HttpClient, HttpClientError, HttpClientRequest, HttpHeaders } from "./internal/lib.ts"

Expand Down
24 changes: 12 additions & 12 deletions packages/effect-app/src/http/internal/lib.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
export * as HttpHeaders from "effect/unstable/http/Headers"
export * as HttpBody from "effect/unstable/http/HttpBody"
export * as HttpClient from "effect/unstable/http/HttpClient"
export * as HttpClientError from "effect/unstable/http/HttpClientError"
export * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
export * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
export * as HttpHeaders from "effect/http/Headers"
export * as HttpBody from "effect/http/HttpBody"
export * as HttpClient from "effect/http/HttpClient"
export * as HttpClientError from "effect/http/HttpClientError"
export * as HttpClientRequest from "effect/http/HttpClientRequest"
export * as HttpClientResponse from "effect/http/HttpClientResponse"
// HttpLayerRouter removed in v4 — use HttpRouter instead
export * as HttpMiddleware from "effect/unstable/http/HttpMiddleware"
export * as HttpRouter from "effect/unstable/http/HttpRouter"
export * as HttpServer from "effect/unstable/http/HttpServer"
export * as HttpServerError from "effect/unstable/http/HttpServerError"
export * as HttpServerRequest from "effect/unstable/http/HttpServerRequest"
export * as HttpServerResponse from "effect/unstable/http/HttpServerResponse"
export * as HttpMiddleware from "effect/http/HttpMiddleware"
export * as HttpRouter from "effect/http/HttpRouter"
export * as HttpServer from "effect/http/HttpServer"
export * as HttpServerError from "effect/http/HttpServerError"
export * as HttpServerRequest from "effect/http/HttpServerRequest"
export * as HttpServerResponse from "effect/http/HttpServerResponse"
2 changes: 1 addition & 1 deletion packages/effect-app/src/rpc/Invalidation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Ref from "effect/Ref"
import { Rpc } from "effect/unstable/rpc"
import { Rpc } from "effect/rpc"
import { type ClientForOptions, makeQueryKey } from "../client/clientFor.ts"
import * as Context from "../Context.ts"
import * as DataDependencies from "../DataDependencies.ts"
Expand Down
4 changes: 2 additions & 2 deletions packages/effect-app/src/rpc/MiddlewareMaker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
import { type NonEmptyArray, type NonEmptyReadonlyArray } from "effect/Array"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"
import { Rpc, type RpcGroup, type RpcSchema } from "effect/rpc"
import { type HandlersFrom } from "effect/rpc/RpcGroup"
import * as S from "effect/Schema"
import type * as Scope from "effect/Scope"
import { type Simplify } from "effect/Types"
import { Rpc, type RpcGroup, type RpcSchema } from "effect/unstable/rpc"
import { type HandlersFrom } from "effect/unstable/rpc/RpcGroup"
import * as Context from "../Context.ts"
import { PreludeLogger } from "../logger.ts"
import { type TypeTestId } from "../TypeTest.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/effect-app/src/rpc/RpcContextMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-explicit-any */

import { type AnyWithProps } from "effect/rpc/Rpc"
import type * as S from "effect/Schema"
import { type AnyWithProps } from "effect/unstable/rpc/Rpc"
import * as Context from "../Context.ts"
import { type RpcDynamic } from "./RpcMiddleware.ts"

Expand Down
4 changes: 2 additions & 2 deletions packages/effect-app/src/rpc/RpcMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { type NonEmptyReadonlyArray } from "effect/Array"
import type * as Effect from "effect/Effect"
import { type Rpc, RpcMiddleware } from "effect/rpc"
import { type TypeId } from "effect/rpc/RpcMiddleware"
import type * as S from "effect/Schema"
import type * as Scope from "effect/Scope"
import type * as Stream from "effect/Stream"
import { type Rpc, RpcMiddleware } from "effect/unstable/rpc"
import { type TypeId } from "effect/unstable/rpc/RpcMiddleware"
import type * as Context from "../Context.ts"
import { type GetEffectContext, type RpcContextMap } from "./RpcContextMap.ts"

Expand Down
2 changes: 1 addition & 1 deletion packages/effect-app/src/setupRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SqlClient } from "effect/sql"
import * as Tracer from "effect/Tracer"
import { SqlClient } from "effect/unstable/sql"
import { DataDependencyRecorder } from "./DataDependencies.ts"
import * as Effect from "./Effect.ts"
import * as Layer from "./Layer.ts"
Expand Down
29 changes: 24 additions & 5 deletions packages/effect-app/src/utils/extend.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
/**
* Own-property define that shadows getter-only prototype fields such as
* Effect 4 `Schema.make`. `Object.assign` uses [[Set]] and cannot.
*/
export const defineOwn = (target: object, key: PropertyKey, value: unknown) => {
Object.defineProperty(target, key, {
value,
writable: true,
enumerable: true,
configurable: true
})
}

const assignOwn = <T extends object>(target: T, source: object): T => {
for (const key of Reflect.ownKeys(source)) {
const desc = Object.getOwnPropertyDescriptor(source, key)
if (!desc?.enumerable) continue
defineOwn(target, key, (source as Record<PropertyKey, unknown>)[key])
}
return target
}

export const extend = <T extends {}, X extends {}>(a: T, ext: X) => {
Object.assign(a, ext)
assignOwn(a, ext)
return a as T & X
}

export const extendM = <T extends {}, X extends {}>(a: T, ext: (a: T) => X) => {
Object.assign(a, ext(a))
return a as typeof a & X
}
export const extendM = <T extends {}, X extends {}>(a: T, ext: (a: T) => X) => extend(a, ext(a))
2 changes: 1 addition & 1 deletion packages/effect-app/test/moreStrings.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as S from "effect-app/Schema"
import * as Arbitrary from "effect/Arbitrary"
import * as Effect from "effect/Effect"
import * as Arbitrary from "effect/unstable/arbitrary/Arbitrary"
import { customRandom, urlAlphabet } from "nanoid"
import { test } from "vitest"

Expand Down
4 changes: 2 additions & 2 deletions packages/effect-app/test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ describe("JSON Schema", () => {
title: "Email",
description: "an email according to RFC 5322",
format: "email",
minLength: 3,
minLength: 2,
maxLength: 998
}
}
Expand All @@ -509,7 +509,7 @@ describe("JSON Schema", () => {
title: "Email",
description: "an email according to RFC 5322",
format: "email",
minLength: 3,
minLength: 2,
maxLength: 998
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/infra/docs/workflow-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This package provides two custom durable `WorkflowEngine` implementations for
(single container, per-execution partition key).

Both implement the low-level `WorkflowEngine.Encoded` contract from
`effect/unstable/workflow/WorkflowEngine` and wrap it with `makeUnsafe`. They are
`effect/workflow/WorkflowEngine` and wrap it with `makeUnsafe`. They are
drop-in alternatives to Effect's built-in `ClusterWorkflowEngine`, trading
cluster-grade routing for a much lighter operational footprint: they need only a
database, not the full cluster stack (ShardManager, Runners, MessageStorage).
Expand Down
6 changes: 3 additions & 3 deletions packages/infra/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"devDependencies": {
"@azure/cosmos": "^4.9.3",
"@azure/service-bus": "^7.9.5",
"@effect/sql-sqlite-node": "4.0.0-rc.115",
"@effect/sql-sqlite-node": "4.0.0",
"@sentry/opentelemetry": "10.55.0",
"@types/better-sqlite3": "^7.6.13",
"@types/node": "25.9.1",
Expand All @@ -39,12 +39,12 @@
"peerDependencies": {
"@azure/cosmos": "^4.9.3",
"@azure/service-bus": "^7.9.5",
"@effect/vitest": "^4.0.0-rc.115",
"@effect/vitest": "^4.0.0",
"@sendgrid/helpers": "^8.0.0",
"@sendgrid/mail": "^8.1.6",
"@sentry/node": "10.55.0",
"@sentry/opentelemetry": "10.55.0",
"effect": "^4.0.0-rc.115",
"effect": "^4.0.0",
"jwt-decode": "^4.0.0",
"redis": "^3.1.2",
"redlock": "^4.2.0"
Expand Down
Loading
Loading