diff --git a/apps/web/app/models/resume/meta/meta.spec.ts b/apps/web/app/models/resume/meta/meta.spec.ts index f01e3d225..bff500e11 100644 --- a/apps/web/app/models/resume/meta/meta.spec.ts +++ b/apps/web/app/models/resume/meta/meta.spec.ts @@ -1,9 +1,6 @@ -import * as jsonSchema from '@effect/schema/JSONSchema' -import type * as S from '@effect/schema/Schema' +import { JSONSchema } from 'effect' import { describe, expect, test } from 'vitest' - import { expectEffectFailure, expectEffectSuccess } from '~/schemas/test-utils.ts' - import { Meta } from './meta.ts' describe('Meta', () => { @@ -11,7 +8,7 @@ describe('Meta', () => { canonical: 'https://example.com', lastModified: 'Thu, 02 May 2024 18:33:23 GMT', version: 'v6.9', - } satisfies S.Schema.Encoded + } describe('decode', () => { test('handle all missing property', async () => { @@ -95,7 +92,7 @@ describe('Meta', () => { }) test('JSONSchema', () => { - expect(JSON.stringify(jsonSchema.make(Meta), null, '\t')).toMatchFileSnapshot( + expect(JSON.stringify(JSONSchema.make(Meta), null, '\t')).toMatchFileSnapshot( 'meta-schema.snapshot.json', ) }) diff --git a/apps/web/app/models/resume/meta/meta.ts b/apps/web/app/models/resume/meta/meta.ts index d11ce3c8a..500a1c981 100644 --- a/apps/web/app/models/resume/meta/meta.ts +++ b/apps/web/app/models/resume/meta/meta.ts @@ -1,11 +1,11 @@ -import * as S from '@effect/schema/Schema' import { TrimmedNonEmpty, UrlString } from '@suddenlygiovanni/resume/schema-primitive' +import { Schema } from 'effect' -export class Meta extends S.Class('Meta')({ - canonical: S.optionalWith(UrlString, { exact: true }), +export class Meta extends Schema.Class('Meta')({ + canonical: Schema.optionalWith(UrlString, { exact: true }), - lastModified: S.optionalWith( - S.Date.annotations({ + lastModified: Schema.optionalWith( + Schema.Date.annotations({ jsonSchema: { format: 'date-time', type: 'string', @@ -14,7 +14,7 @@ export class Meta extends S.Class('Meta')({ { exact: true }, ), - version: S.optionalWith( + version: Schema.optionalWith( TrimmedNonEmpty.annotations({ title: 'version', description: 'A version field which follows semver - e.g. v1.0.0', @@ -23,7 +23,7 @@ export class Meta extends S.Class('Meta')({ { exact: true }, ), }) { - static decode = S.decode(this) + static decode = Schema.decode(this) - static encode = S.encode(this) + static encode = Schema.encode(this) } diff --git a/apps/web/app/root.tsx b/apps/web/app/root.tsx index dfdafd164..fce37ec62 100644 --- a/apps/web/app/root.tsx +++ b/apps/web/app/root.tsx @@ -1,4 +1,3 @@ -import * as Schema from '@effect/schema/Schema' import { invariantResponse } from '@epic-web/invariant' import type { ActionFunctionArgs, @@ -8,7 +7,8 @@ import type { } from '@remix-run/node' import { Links, Meta, Scripts, ScrollRestoration, json, useLoaderData } from '@remix-run/react' import { Types, makeOpenGraphWebsite } from '@suddenlygiovanni/open-graph-protocol' -import * as Either from 'effect/Either' +import { Either, Schema } from 'effect' + import type { JSX, ReactElement, ReactNode } from 'react' import { Layout } from '@suddenlygiovanni/ui/components/layout/layout.tsx' diff --git a/apps/web/app/routes/resume/format-date-locale-short.spec.ts b/apps/web/app/routes/resume/format-date-locale-short.spec.ts index 52bf62bde..e5ee0347d 100644 --- a/apps/web/app/routes/resume/format-date-locale-short.spec.ts +++ b/apps/web/app/routes/resume/format-date-locale-short.spec.ts @@ -1,13 +1,14 @@ -import { ParseError } from '@effect/schema/ParseResult' -import { getOrThrow, isLeft } from 'effect/Either' +import { Either } from 'effect' + +import { ParseError } from 'effect/ParseResult' import { describe, expect, test } from 'vitest' import { formatDateLocaleShort } from './format-date-locale-short.ts' describe('formatDateLocaleShort', () => { test('should return an error for an empty string', () => { const result = formatDateLocaleShort('') - expect(isLeft(result)).toBe(true) - if (isLeft(result)) { + expect(Either.isLeft(result)).toBe(true) + if (Either.isLeft(result)) { expect(result.left).toBeInstanceOf(ParseError) } }) @@ -16,8 +17,8 @@ describe('formatDateLocaleShort', () => { const invalidDateString = '19/04/2022' const result = formatDateLocaleShort(invalidDateString) - expect(isLeft(result)).toBe(true) - if (isLeft(result)) { + expect(Either.isLeft(result)).toBe(true) + if (Either.isLeft(result)) { expect(result.left).toBeInstanceOf(ParseError) } }) @@ -27,7 +28,7 @@ describe('formatDateLocaleShort', () => { const isoDateString2 = '2022-04-30' const result1 = formatDateLocaleShort(isoDateString1) const result2 = formatDateLocaleShort(isoDateString2) - expect(getOrThrow(result1)).toBe('Apr 2022') - expect(getOrThrow(result2)).toBe('Apr 2022') + expect(Either.getOrThrow(result1)).toBe('Apr 2022') + expect(Either.getOrThrow(result2)).toBe('Apr 2022') }) }) diff --git a/apps/web/app/routes/resume/format-date-locale-short.ts b/apps/web/app/routes/resume/format-date-locale-short.ts index 8d5291e79..e50a350e1 100644 --- a/apps/web/app/routes/resume/format-date-locale-short.ts +++ b/apps/web/app/routes/resume/format-date-locale-short.ts @@ -1,6 +1,6 @@ -import type { ParseError } from '@effect/schema/ParseResult' -import * as Schema from '@effect/schema/Schema' +import { Schema } from 'effect' import type { Either } from 'effect/Either' +import type { ParseError } from 'effect/ParseResult' /** * Given a string date, this function validates and transforms it to a US locale short date format. diff --git a/apps/web/app/schemas/parse-yml.ts b/apps/web/app/schemas/parse-yml.ts index 921453c3e..ceed5b63b 100644 --- a/apps/web/app/schemas/parse-yml.ts +++ b/apps/web/app/schemas/parse-yml.ts @@ -1,11 +1,11 @@ -import { AST, ParseResult, Schema } from '@effect/schema' // biome-ignore lint/style/useNamingConvention: I want to have the same style of using JSON. import * as YAML from '@std/yaml' +import { ParseResult, Schema, SchemaAST } from 'effect' export const YmlString = Schema.String.annotations({ - [AST.IdentifierAnnotationId]: 'YmlString', - [AST.TitleAnnotationId]: 'YmlString', - [AST.DescriptionAnnotationId]: 'a YML string', + [SchemaAST.IdentifierAnnotationId]: 'YmlString', + [SchemaAST.TitleAnnotationId]: 'YmlString', + [SchemaAST.DescriptionAnnotationId]: 'a YML string', }) /** diff --git a/apps/web/app/schemas/test-utils.ts b/apps/web/app/schemas/test-utils.ts index f212b4905..82a1ee9e5 100644 --- a/apps/web/app/schemas/test-utils.ts +++ b/apps/web/app/schemas/test-utils.ts @@ -1,10 +1,7 @@ -import type { ParseOptions } from '@effect/schema/AST' -import type * as ParseResult from '@effect/schema/ParseResult' -import * as S from '@effect/schema/Schema' -import { formatErrorSync } from '@effect/schema/TreeFormatter' -import * as Effect from 'effect/Effect' -import * as Either from 'effect/Either' -import * as Option from 'effect/Option' +import { Effect, Either, Option, Schema } from 'effect' +import { type ParseError, TreeFormatter } from 'effect/ParseResult' +import type { ParseOptions } from 'effect/SchemaAST' + import { expect } from 'vitest' export const onExcessPropertyError: ParseOptions = { @@ -20,44 +17,44 @@ export const allErrors: ParseOptions = { } export const expectDecodeUnknownSuccess = async ( - schema: S.Schema, + schema: Schema.Schema, input: unknown, // biome-ignore lint/suspicious/noExplicitAny: ok here expected: A = input as any, options?: ParseOptions, -) => expectSuccess(S.decodeUnknown(schema)(input, options), expected) +): Promise => expectSuccess(Schema.decodeUnknown(schema)(input, options), expected) export const expectDecodeUnknownFailure = async ( - schema: S.Schema, + schema: Schema.Schema, input: unknown, message: string, options?: ParseOptions, -) => expectFailure(S.decodeUnknown(schema)(input, options), message) +): Promise => expectFailure(Schema.decodeUnknown(schema)(input, options), message) export const expectEncodeSuccess = async ( - schema: S.Schema, + schema: Schema.Schema, a: A, expected: unknown, options?: ParseOptions, -) => expectSuccess(S.encode(schema)(a, options), expected) +): Promise => expectSuccess(Schema.encode(schema)(a, options), expected) export const expectEncodeFailure = async ( - schema: S.Schema, + schema: Schema.Schema, a: A, message: string, options?: ParseOptions, -) => expectFailure(S.encode(schema)(a, options), message) +): Promise => expectFailure(Schema.encode(schema)(a, options), message) // biome-ignore lint/style/useNamingConvention: -export const printAST = (schema: S.Schema) => { +export const printAST = (schema: Schema.Schema): void => { console.log('%o', schema.ast) } // biome-ignore lint/suspicious/useAwait: export const expectFailure = async ( - effect: Either.Either | Effect.Effect, + effect: Either.Either | Effect.Effect, message: string, -) => { +): Promise => { if (Either.isEither(effect)) { expectEitherLeft(effect, message) } else { @@ -69,7 +66,7 @@ export const expectFailure = async ( export const expectSuccess = async ( effect: Either.Either | Effect.Effect, a: A, -) => { +): Promise => { if (Either.isEither(effect)) { expectEitherRight(effect, a) } else { @@ -78,33 +75,33 @@ export const expectSuccess = async ( } export const expectEffectFailure = async ( - effect: Effect.Effect, + effect: Effect.Effect, message: string, -) => { +): Promise => { expect( - await Effect.runPromise(Effect.either(Effect.mapError(effect, formatErrorSync))), + await Effect.runPromise(Effect.either(Effect.mapError(effect, TreeFormatter.formatErrorSync))), ).toStrictEqual(Either.left(message)) } -export const expectEffectSuccess = async (effect: Effect.Effect, a: A) => { +export const expectEffectSuccess = async ( + effect: Effect.Effect, + a: A, +): Promise => { expect(await Effect.runPromise(Effect.either(effect))).toStrictEqual(Either.right(a)) } -export const expectEitherLeft = ( - e: Either.Either, - message: string, -) => { - expect(Either.mapLeft(e, formatErrorSync)).toStrictEqual(Either.left(message)) +export const expectEitherLeft = (e: Either.Either, message: string): void => { + expect(Either.mapLeft(e, TreeFormatter.formatErrorSync)).toStrictEqual(Either.left(message)) } -export const expectEitherRight = (e: Either.Either, a: A) => { +export const expectEitherRight = (e: Either.Either, a: A): void => { expect(e).toStrictEqual(Either.right(a)) } -export const expectNone = (o: Option.Option) => { +export const expectNone = (o: Option.Option): void => { expect(o).toStrictEqual(Option.none()) } -export const expectSome = (o: Option.Option, a: A) => { +export const expectSome = (o: Option.Option, a: A): void => { expect(o).toStrictEqual(Option.some(a)) } diff --git a/apps/web/app/services/resume-repository.ts b/apps/web/app/services/resume-repository.ts index 78aea94c6..6ecfd3a5a 100644 --- a/apps/web/app/services/resume-repository.ts +++ b/apps/web/app/services/resume-repository.ts @@ -1,5 +1,5 @@ -import { Schema } from '@effect/schema' import { Resume } from '@suddenlygiovanni/resume/schema-resume' +import { Schema } from 'effect' import { Console, Data, Effect, Layer, Option } from 'effect' import { Meta } from '~/models/resume/meta/meta.ts' diff --git a/apps/web/app/utils/env.server.ts b/apps/web/app/utils/env.server.ts index 2c58a5305..82c071673 100644 --- a/apps/web/app/utils/env.server.ts +++ b/apps/web/app/utils/env.server.ts @@ -1,8 +1,7 @@ // biome-ignore lint/correctness/noNodejsModules: import * as process from 'node:process' -import * as Schema from '@effect/schema/Schema' -import { formatError } from '@effect/schema/TreeFormatter' -import * as Either from 'effect/Either' +import { Either, Schema } from 'effect' +import { TreeFormatter } from 'effect/ParseResult' const envSchema = Schema.Struct({ // biome-ignore lint/style/useNamingConvention: @@ -51,7 +50,7 @@ declare global { export function init(): void { const maybeEnv = Schema.decodeUnknownEither(envSchema)(process.env, { errors: 'all' }) if (Either.isLeft(maybeEnv)) { - console.error('❌ Invalid environment variables:', formatError(maybeEnv.left)) + console.error('❌ Invalid environment variables:', TreeFormatter.formatError(maybeEnv.left)) throw new Error('Invalid environment variables') } } diff --git a/apps/web/app/utils/theme.tsx b/apps/web/app/utils/theme.tsx index 90eced4f3..5894e185b 100644 --- a/apps/web/app/utils/theme.tsx +++ b/apps/web/app/utils/theme.tsx @@ -1,6 +1,5 @@ -import * as Schema from '@effect/schema/Schema' import { useFetchers } from '@remix-run/react' -import * as Either from 'effect/Either' +import { Either, Schema } from 'effect' import { useHints } from './client-hints.tsx' import { useRequestInfo } from './request-info.ts' diff --git a/apps/web/package.json b/apps/web/package.json index 2d4399bf9..e5ceb5972 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -5,7 +5,6 @@ } }, "dependencies": { - "@effect/schema": "0.72.2", "@epic-web/client-hints": "1.3.5", "@epic-web/invariant": "1.0.0", "@octokit/core": "6.1.2", @@ -16,10 +15,10 @@ "@remix-run/serve": "2.13.1", "@std/yaml": "npm:@jsr/std__yaml@1.0.5", "@suddenlygiovanni/open-graph-protocol": "workspace:*", - "@suddenlygiovanni/resume": "12.1.12", + "@suddenlygiovanni/resume": "13.0.0", "@suddenlygiovanni/ui": "workspace:*", "cookie": "1.0.1", - "effect": "3.7.2", + "effect": "3.10.4", "isbot": "5.1.17", "react": "18.3.1", "react-dom": "18.3.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 769dee8ed..f4d0128d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,9 +23,6 @@ importers: apps/web: dependencies: - '@effect/schema': - specifier: 0.72.2 - version: 0.72.2(effect@3.7.2) '@epic-web/client-hints': specifier: 1.3.5 version: 1.3.5 @@ -57,8 +54,8 @@ importers: specifier: workspace:* version: link:../../packages/open-graph-protocol '@suddenlygiovanni/resume': - specifier: 12.1.12 - version: 12.1.12(@effect/schema@0.72.2(effect@3.7.2)) + specifier: 13.0.0 + version: 13.0.0 '@suddenlygiovanni/ui': specifier: workspace:* version: link:../../packages/ui @@ -66,8 +63,8 @@ importers: specifier: 1.0.1 version: 1.0.1 effect: - specifier: 3.7.2 - version: 3.7.2 + specifier: 3.10.4 + version: 3.10.4 isbot: specifier: 5.1.17 version: 5.1.17 @@ -591,11 +588,6 @@ packages: peerDependencies: vite: 4.x || 5.x - '@effect/schema@0.72.2': - resolution: {integrity: sha512-/x1BIA2pqcUidNrOMmwYe6Z58KtSgHSc5iJu7bNwIxi2LHMVuUao1BvpI5x6i7T/zkoi4dd1S6qasZzJIYDjdw==} - peerDependencies: - effect: ^3.7.2 - '@emotion/babel-plugin@11.11.0': resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} @@ -2731,11 +2723,9 @@ packages: peerDependencies: storybook: ^8.3.5 - '@suddenlygiovanni/resume@12.1.12': - resolution: {integrity: sha512-oODYc6d6s3LqvRSwXcwn8bFCb4CE04fM6V9TtnAKtCnIUGq7ZEja6tg+vaZ2DlHuyov4ijgJPxrRY1lctvMnVg==, tarball: https://npm.pkg.github.com/download/@suddenlygiovanni/resume/12.1.12/ad1993f3e5e4e6085c757789637eaf32123a7da5} - engines: {node: '>=22'} - peerDependencies: - '@effect/schema': ~0.72.2 + '@suddenlygiovanni/resume@13.0.0': + resolution: {integrity: sha512-X/NtmpUPpaKtv2oACAJWQW6Wnt5NCwgGLHp+R42QHwUuQHN1ZyIsJlsoBklcB+twraYSzfVzCyc3ahk/Wa0U2Q==, tarball: https://npm.pkg.github.com/download/@suddenlygiovanni/resume/13.0.0/f0f8c6d737454b00867b0855e9775ba1525494e4} + engines: {node: '>=22.10'} '@swc/core-darwin-arm64@1.7.26': resolution: {integrity: sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw==} @@ -3684,8 +3674,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - effect@3.7.2: - resolution: {integrity: sha512-pV7l1+LSZFvVObj4zuy4nYiBaC7qZOfrKV6s/Ef4p3KueiQwZFgamazklwyZ+x7Nyj2etRDFvHE/xkThTfQD1w==} + effect@3.10.4: + resolution: {integrity: sha512-D7Mryq8jylT0fIGrgXEn2TublO/BhduRwzlqV5z1l/QFY6grs7UOyyomlAOFMK9ArSYiLgrOSMQ/Cr/cIOeU2Q==} electron-to-chromium@1.4.763: resolution: {integrity: sha512-k4J8NrtJ9QrvHLRo8Q18OncqBCB7tIUyqxRcJnlonQ0ioHKYB988GcDFF3ZePmnb8eHEopDs/wPHR/iGAFgoUQ==} @@ -4004,7 +3994,6 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -4115,7 +4104,6 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -6425,11 +6413,6 @@ snapshots: unplugin: 1.10.1 vite: 5.4.8(@types/node@22.7.9) - '@effect/schema@0.72.2(effect@3.7.2)': - dependencies: - effect: 3.7.2 - fast-check: 3.22.0 - '@emotion/babel-plugin@11.11.0': dependencies: '@babel/helper-module-imports': 7.24.3 @@ -9033,9 +9016,7 @@ snapshots: dependencies: storybook: 8.3.5 - '@suddenlygiovanni/resume@12.1.12(@effect/schema@0.72.2(effect@3.7.2))': - dependencies: - '@effect/schema': 0.72.2(effect@3.7.2) + '@suddenlygiovanni/resume@13.0.0': {} '@swc/core-darwin-arm64@1.7.26': optional: true @@ -10026,7 +10007,9 @@ snapshots: ee-first@1.1.1: {} - effect@3.7.2: {} + effect@3.10.4: + dependencies: + fast-check: 3.22.0 electron-to-chromium@1.4.763: {}