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.
24 changes: 24 additions & 0 deletions .changeset/update-effect-beta-107.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
"@effect-app/vue-components": patch
"effect-app": patch
"@effect-app/infra": patch
"@effect-app/cli": patch
"@effect-app/vue": patch
---

Update effect packages to `4.0.0-beta.107` (from `beta.90`): `effect`, `@effect/platform-node`, `@effect/platform-browser`, `@effect/atom-vue`, `@effect/sql-sqlite-node`, `@effect/vitest`, and `fast-check` to `^4.9.0`. Sync `repos/effect` subtree from `Effect-TS/effect` (effect-smol stopped publishing tags after beta.98).

API adaptations for beta.107:

- `concurrency: "inherit"` → `"unbounded"`
- `Schema.ErrorClass` / `TaggedErrorClass` → `Schema.Error` / `TaggedError`
- `Schema.LazyArbitrary` → `Schema.Arbitrary`
- `Schema.DateValid` / `isDateValid` removed (`Schema.Date` rejects invalid dates)
- `SchemaIssue` constructors no longer take `Option` (annotations + input)
- filter meta via `annotations.representation` instead of `annotations.meta`
- `context.defaultValue` → `context.constructorDefault` (single Link)
- Class detection via `~constructor` + static `identifier`
- Redacted detection via `representation.id`
- localized StandardSchema hooks updated for new issue/input model
- provide `NodeCrypto.layer` for cluster sqlite tests
- default `sync-effect` subtree URL → `Effect-TS/effect`
2 changes: 1 addition & 1 deletion .specs/Update-to-latest-Effect.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ If new errors occur, first describe the problem, propose solutions and wait for

## Notes

- subtree url: `https://github.com/Effect-TS/effect-smol.git`, prefix `repos/effect`, tag `effect@<version>`.
- subtree url: `https://github.com/Effect-TS/effect.git`, prefix `repos/effect`, tag `effect@<version>`.
- v4 betas live under the npm `beta` dist-tag (npm `latest` is still v3). Find target with `npm view effect dist-tags`.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"dependencies": {
"date-fns": "^4.4.0",
"fast-check": "^4.8.0",
"fast-check": "^4.9.0",
"vue": "^3.5.35"
},
"devDependencies": {
Expand All @@ -50,15 +50,15 @@
"@effect-app/infra": "workspace:*",
"@effect/language-service": "0.86.2",
"@effect/tsgo": "^0.31.0",
"@effect/platform-node": "4.0.0-beta.90",
"@effect/vitest": "4.0.0-beta.90",
"@effect/platform-node": "4.0.0-beta.107",
"@effect/vitest": "4.0.0-beta.107",
"@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-beta.90",
"effect": "4.0.0-beta.107",
"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-beta.90",
"effect": "4.0.0-beta.90",
"@effect/platform-node": "4.0.0-beta.107",
"effect": "4.0.0-beta.107",
"js-yaml": "4.2.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/gist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export class GistEntryDecoded extends Schema.Opaque<GistEntryDecoded>()(
// if there are any collisions, fail with a combined message
if (messages.length > 0) {
return yield* Effect.fail(
new SchemaIssue.InvalidValue(Option.some(entry.files), { message: messages.join("; ") })
new SchemaIssue.InvalidValue({ message: messages.join("; ") }, entry.files)
)
}

Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ NodeRuntime.runMain(
url: Flag.string("url").pipe(
Flag.optional,
Flag.withDescription(
"Git repository URL (default: https://github.com/Effect-TS/effect-smol.git)"
"Git repository URL (default: https://github.com/Effect-TS/effect.git)"
)
)
},
Expand All @@ -743,7 +743,7 @@ NodeRuntime.runMain(
onSome: (m) => m.split(",").map((p) => p.trim())
}),
subtreePrefix: Option.getOrElse(prefix, () => "repos/effect"),
url: Option.getOrElse(url, () => "https://github.com/Effect-TS/effect-smol.git")
url: Option.getOrElse(url, () => "https://github.com/Effect-TS/effect.git")
})
})
)
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-beta.90",
"@effect/platform-node": "4.0.0-beta.90",
"@effect/vitest": "4.0.0-beta.90",
"@effect/atom-vue": "^4.0.0-beta.107",
"@effect/platform-node": "4.0.0-beta.107",
"@effect/vitest": "4.0.0-beta.107",
"@tanstack/vue-query": "5.96.2",
"@types/node": "25.9.1",
"@vitejs/plugin-vue": "^6.0.7",
"effect": "^4.0.0-beta.90",
"effect": "^4.0.0-beta.107",
"typescript": "~6.0.3",
"vitest": "^4.1.7",
"vue": "^3.5.35"
Expand Down
4 changes: 2 additions & 2 deletions packages/effect-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
"@faker-js/faker": "^8.4.1",
"@types/node": "25.9.1",
"@types/validator": "^13.15.10",
"fast-check": "~4.8.0",
"fast-check": "^4.9.0",
"typescript": "~6.0.3",
"vitest": "^4.1.7"
},
"peerDependencies": {
"effect": "^4.0.0-beta.90"
"effect": "^4.0.0-beta.107"
},
"typesVersions": {
"*": {
Expand Down
2 changes: 1 addition & 1 deletion packages/effect-app/src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export function allLower<T extends Record<string, Context.Service<any, any> | Ef
prev[((cur as string)[0]!.toLowerCase() + (cur as string).slice(1)) as unknown as LowerFirst<typeof cur>] = svc
return prev
}, {} as any),
{ concurrency: "inherit" }
{ concurrency: "unbounded" }
) as any as Effect.Effect<LowerServices<T>, ValuesE<T>, ValuesR<T>>
}

Expand Down
76 changes: 45 additions & 31 deletions packages/effect-app/src/Schema/Class.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type * as Cause from "effect/Cause"
import * as Effect from "effect/Effect"
import * as Option from "effect/Option"
import * as S from "effect/Schema"
import * as SchemaGetter from "effect/SchemaGetter"
import * as SchemaIssue from "effect/SchemaIssue"
Expand All @@ -14,9 +13,11 @@ import * as SchemaParser from "./SchemaParser.ts"

type ClassAnnotations<Self> = S.Annotations.Declaration<Self, readonly [any]>

export interface EnhancedClass<Self, SchemaS extends S.Top & { readonly fields: S.Struct.Fields }, Inherited>
extends S.Class<Self, SchemaS, Inherited>
{
export interface EnhancedClass<
Self,
SchemaS extends S.Constraint & { readonly fields: S.Struct.Fields },
Inherited
> extends S.Class<Self, SchemaS, Inherited> {
/**
* See `copyOrigin` docs in `utils.ts` for return-type design details.
*/
Expand All @@ -39,12 +40,22 @@ export declare const ExtendedSchemaNoEncoded: unique symbol

export type ExtendedSchemaNoEncoded = typeof ExtendedSchemaNoEncoded

type WithEncoded<SchemaS extends S.Top, Encoded> = Omit<SchemaS, "Encoded"> & { readonly Encoded: Encoded }
/**
* Override schema `Encoded` while keeping `Constraint` (intersection, not `Omit`).
* Free type-params for `Encoded` keep the conditional unresolved — callers that
* need Encoded overrides use the intersection form of the class factory return type.
*/
type WithEncoded<SchemaS extends S.Constraint, Encoded> = SchemaS & { readonly Encoded: Encoded }

type ExtendedSchema<SchemaS extends S.Top, Encoded> = [Encoded] extends [ExtendedSchemaNoEncoded] ? SchemaS
type ExtendedSchema<SchemaS extends S.Constraint & { readonly fields: S.Struct.Fields }, Encoded> = [
Encoded
] extends [ExtendedSchemaNoEncoded] ? SchemaS
: WithEncoded<SchemaS, Encoded>

export type Class<Self, S extends S.Top & { readonly fields: S.Struct.Fields }, Inherited> = EnhancedClass<
/** Struct fields schema, optionally with a caller-supplied Encoded override. */
type ClassFieldsSchema<Fields extends S.Struct.Fields, Encoded> = ExtendedSchema<S.Struct<Fields>, Encoded>

export type Class<Self, S extends S.Constraint & { readonly fields: S.Struct.Fields }, Inherited> = EnhancedClass<
Self,
S,
Inherited
Expand Down Expand Up @@ -73,7 +84,7 @@ function makeRelaxedDeclaration(
if (input !== null && typeof input === "object") {
return decodeStruct(input, options)
}
return Effect.fail(new SchemaIssue.InvalidType(self, Option.some(input)))
return Effect.fail(new SchemaIssue.InvalidType(self, input))
},
ast.annotations,
ast.checks,
Expand Down Expand Up @@ -114,7 +125,7 @@ export const Class: <Self = never, Encoded = ExtendedSchemaNoEncoded, Brand = {}
) => [Self] extends [never] ? MissingSelfGeneric<"Class">
: EnhancedClass<
Self,
ExtendedSchema<S.Struct<Fields>, Encoded>,
ClassFieldsSchema<Fields, Encoded>,
Brand
> = (identifier) => (fields, annotations, options) => {
const relaxed = options?.strict === false
Expand Down Expand Up @@ -182,7 +193,7 @@ export const TaggedClass: <Self = never, Encoded = ExtendedSchemaNoEncoded, Bran
) => [Self] extends [never] ? MissingSelfGeneric<"TaggedClass">
: EnhancedClass<
Self,
ExtendedSchema<S.Struct<{ readonly _tag: S.tag<Tag> } & Fields>, Encoded>,
ClassFieldsSchema<{ readonly _tag: S.tag<Tag> } & Fields, Encoded>,
Brand
> = (identifier) => (tag, fields, annotations, options) => {
const relaxed = options?.strict === false
Expand Down Expand Up @@ -227,11 +238,11 @@ export const ErrorClass: <Self = never, Encoded = ExtendedSchemaNoEncoded, Brand
) => [Self] extends [never] ? MissingSelfGeneric<"ErrorClass">
: EnhancedClass<
Self,
ExtendedSchema<S.Struct<Fields>, Encoded>,
ClassFieldsSchema<Fields, Encoded>,
Cause.YieldableError & Brand
> = (identifier) => (fields, annotations, options) => {
const relaxed = options?.strict === false
const Base = (S.ErrorClass as any)(identifier)(fields, { ...concurrencyUnbounded, ...annotations })
const Base = (S.Error as any)(identifier)(fields, { ...concurrencyUnbounded, ...annotations })
const originalAstDescriptor = Object.getOwnPropertyDescriptor(Base, "ast")!
const astCache = new WeakMap<any, SchemaAST.Declaration>()
const copyCache = new WeakMap<any, ReturnType<typeof copyOrigin>>()
Expand Down Expand Up @@ -273,11 +284,11 @@ export const TaggedErrorClass: <Self = never, Encoded = ExtendedSchemaNoEncoded,
) => [Self] extends [never] ? MissingSelfGeneric<"TaggedErrorClass">
: EnhancedClass<
Self,
ExtendedSchema<S.Struct<{ readonly _tag: S.tag<Tag> } & Fields>, Encoded>,
ClassFieldsSchema<{ readonly _tag: S.tag<Tag> } & Fields, Encoded>,
Cause.YieldableError & Brand
> = (identifier) => (tag, fields, annotations, options) => {
const relaxed = options?.strict === false
const Base = (S.TaggedErrorClass as any)(identifier)(tag, fields, { ...concurrencyUnbounded, ...annotations })
const Base = (S.TaggedError as any)(identifier)(tag, fields, { ...concurrencyUnbounded, ...annotations })
const originalAstDescriptor = Object.getOwnPropertyDescriptor(Base, "ast")!
const astCache = new WeakMap<any, SchemaAST.Declaration>()
const copyCache = new WeakMap<any, ReturnType<typeof copyOrigin>>()
Expand Down Expand Up @@ -305,9 +316,9 @@ export const TaggedErrorClass: <Self = never, Encoded = ExtendedSchemaNoEncoded,
} as any
}

export interface Opaque<Self, Encoded, SchemaS extends S.Top, Brand>
extends S.Opaque<Self, ExtendedSchema<SchemaS, Encoded>, Brand>
{}
export interface Opaque<Self, Encoded, SchemaS extends S.Top, Brand> extends S.Opaque<Self, SchemaS, Brand> {
readonly "Encoded": Encoded extends ExtendedSchemaNoEncoded ? SchemaS["Encoded"] : Encoded
}

export const Opaque: <Self, Encoded = ExtendedSchemaNoEncoded, Brand = {}>() => <S extends S.Top>(
schema: S
Expand Down Expand Up @@ -338,22 +349,15 @@ export const Opaque: <Self, Encoded = ExtendedSchemaNoEncoded, Brand = {}>() =>
* (`~type.make.in`) and other derived members are still computed from the struct. See
* a future `OpaqueShape`-style helper if those also need to be supplied.
*/
export interface OpaqueType<Self, Encoded, SchemaS extends S.Top, Brand>
extends S.Opaque<Self, ExtendedSchema<SchemaS, Encoded>, Brand>
{
export interface OpaqueType<Self, Encoded, SchemaS extends S.Top, Brand> extends S.Opaque<Self, SchemaS, Brand> {
readonly "Encoded": Encoded extends ExtendedSchemaNoEncoded ? SchemaS["Encoded"] : Encoded
new(_: never): Self
}

export const OpaqueType: <Self, Encoded = ExtendedSchemaNoEncoded, Brand = {}>() => <S extends S.Top>(
schema: S
) => OpaqueType<Self, Encoded, S, Brand> & Omit<S, keyof S.Top> = S.Opaque as any

// Override both the `Encoded` and make-input (`~type.make.in`) members in one go,
// like `ExtendedSchema` does for `Encoded` alone.
type ExtendedShape<SchemaS extends S.Top, Encoded, MakeIn> =
& Omit<SchemaS, "Encoded" | "~type.make.in">
& { readonly Encoded: Encoded; readonly "~type.make.in": MakeIn }

type OpaqueFacadeConstructorArgs<MakeIn> = {} extends MakeIn ? [props?: MakeIn, options?: S.MakeOptions]
: [props: MakeIn, options?: S.MakeOptions]

Expand All @@ -376,7 +380,9 @@ type OpaqueClassFacadeInput<DecodingServices, EncodingServices> =

type PrototypeFunction = Function & { prototype: object }

const ClassAnnotationId = "~effect/Schema/Class"
// Class schemas expose a constructor descriptor under this key (was previously
// identified via a `~effect/Schema/Class` annotation id).
const ConstructorAnnotationKey = "~constructor"

const getOwnOrInheritedPropertyDescriptor = (value: object, property: PropertyKey): PropertyDescriptor | undefined => {
let current: object | null = value
Expand All @@ -389,13 +395,19 @@ const getOwnOrInheritedPropertyDescriptor = (value: object, property: PropertyKe

const isClassSchemaConstructor = (value: unknown): value is PrototypeFunction => {
if (typeof value !== "function") return false
// Transformed schemas (e.g. `Class.pipe(S.encodeKeys(...))`) are also functions with a
// Declaration AST that still carries `~constructor`, but they are not constructable classes.
// Real Schema.Class constructors expose a static `identifier`.
if (typeof (value as { readonly identifier?: unknown }).identifier !== "string") return false
const ast = (value as { readonly ast?: unknown }).ast
return SchemaAST.isAST(ast) && SchemaAST.isDeclaration(ast) && ast.annotations?.[ClassAnnotationId] !== undefined
return SchemaAST.isAST(ast)
&& SchemaAST.isDeclaration(ast)
&& ast.annotations?.[ConstructorAnnotationKey] !== undefined
}

const getFacadeClassSchema = (schema: OpaqueFacadeInput<any, any>): PrototypeFunction | undefined => {
if (isClassSchemaConstructor(schema)) return schema
const target = "to" in schema ? schema.to : undefined
const target = "to" in schema ? (schema as { readonly to?: unknown }).to : undefined
return isClassSchemaConstructor(target) ? target : undefined
}

Expand Down Expand Up @@ -451,8 +463,10 @@ type OpaqueFacadeStatics<SchemaS extends S.Top> = Omit<SchemaS, Exclude<keyof S.
* {@link OpaqueType}.
*/
export interface OpaqueShape<Self, Encoded, MakeIn, SchemaS extends S.Top, Brand>
extends S.Opaque<Self, ExtendedShape<SchemaS, Encoded, MakeIn>, Brand>
extends S.Opaque<Self, SchemaS, Brand>
{
readonly "Encoded": Encoded
readonly "~type.make.in": MakeIn
new(_: never): Self
}

Expand Down Expand Up @@ -625,7 +639,7 @@ export function OpaqueErrorFacadeClass<
& OpaqueErrorFacadeClass<Self, Encoded, MakeIn, DecodingServices, EncodingServices, Brand>
& OpaqueFacadeStatics<SchemaS>

if (typeof schema === "function") {
if (isClassSchemaConstructor(schema)) {
return schema as SchemaS & FacadeSchema
}

Expand Down
6 changes: 2 additions & 4 deletions packages/effect-app/src/Schema/SpecialJsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
* post-processes the output (e.g. flattens simple allOf).
*/
import type * as JsonSchema from "effect/JsonSchema"
import type * as Schema from "effect/Schema"
import * as SchemaRepresentation from "effect/SchemaRepresentation"
import * as Schema from "effect/Schema"

/**
* Converts a schema to a JSON Schema Document (draft-2020-12), with
Expand All @@ -14,8 +13,7 @@ export function specialJsonSchemaDocument(
schema: Schema.Top,
options?: Schema.ToJsonSchemaOptions
): JsonSchema.Document<"draft-2020-12"> {
const doc = SchemaRepresentation.fromAST(schema.ast)
const jd = SchemaRepresentation.toJsonSchemaDocument(doc, options)
const jd = Schema.toJsonSchemaDocument(schema, options)
const processedDefs: JsonSchema.Definitions = {}
for (const [key, def] of Object.entries(jd.definitions)) {
processedDefs[key] = postProcessJsonSchema(def)
Expand Down
Loading
Loading