Skip to content

Commit

Permalink
Improve type
Browse files Browse the repository at this point in the history
  • Loading branch information
iamchanii committed Jul 17, 2024
1 parent 5ba3be9 commit 1137774
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 247 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-apricots-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"pothos-plugin-effect": major
---

Update pothos v4
239 changes: 9 additions & 230 deletions packages/pothos-plugin-effect/MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,235 +1,14 @@
# Migration from v0.x
# Migration from v1

The 1.0 release contains a large number of breaking changes. If you're using pothos-plugin-effect from 0.x (thanksfully), follow the instructions below.
## Breaking API Changes

## `t.effect` is not field builder.
### Renamed options

`t.effect` is provided as a utility function rather than in the field builder. Use `t.effect` inside any kind of Pothos field resolver function to resolve the Effect.
The name of the plugin option field has been changed to `effect` to be more consistent with other offical Pothos plugins.

<table>
<thead>
<tr>
<th><code>Before (0.x)</code></th>
<th><code>After (1.0.0 ~)</code></th>
</thead>
<tbody>
<tr>
<td>

```ts
t.effect({
type: "Int",
effect: {},
resolve: () => Effect.succeed(1),
});
```

</td>
<td>

```ts
t.int({
resolve: () => t.effect(Effect.succeed(1)),
});

t.string({
resolve: () => t.effect(Effect.succeed("Hello, World!")),
});

t.field({
type: "Float",
nullable: true,
resolve: () => t.effect(Effect.succeedNone),
});
```

</td>
</tr>
</tbody>
</table>

## Removed service/context/layer configuration options at field level.

Instead, you can [configure a custom effect runtime](./README.md#configure-custom-runtime).

<table>
<thead>
<tr>
<th><code>Before (0.x)</code></th>
<th><code>After (1.0.0 ~)</code></th>
</thead>
<tbody>
<tr>
<td>

```ts
t.effect({
type: User,
effect: {
services: [
UserService,
UserService.of({
/* ... */
}),
],
contexts: [
/* ... */
],
layers: [
/* ... */
],
},
resolve: () =>
Effect.gen(function* (_) {
const userService = yield* _(UserService);

return yield* _(userService.getUserOrThrow());
}),
});
```diff
const builder = new SchemaBuilder<{}>({
- effectOptions: {...}
+ effect: {...}
})
```

</td>
<td>

```ts
declare const effectRuntime: Runtime.Runtime<UserService>;

const builder = new SchemaBuilder<{
EffectRuntime: typeof effectRuntime;
}>({
plugins: [EffectPlugin],
effectOptions: { effectRuntime },
});

// in builder:

t.field({
type: User,
resolve: () =>
t.effect(
Effect.gen(function* (_) {
const userService = yield* _(UserService);

return yield* _(userService.getUserOrThrow());
})
),
});
```

</td>
</tr>
</tbody>
</table>

## Removed `t.effectConnection`

Instead, you can directly use the `resolveArrayConnection`/`resolveCursorConnection`/`resolveOffsetConnection` which imported from [`@pothos/plugin-relay`](https://pothos-graphql.dev/docs/plugins/relay), with `t.effect`. Below is an example code for using `resolveArrayConnection`:

<table>
<thead>
<tr>
<th><code>Before (0.x)</code></th>
<th><code>After (1.0.0 ~)</code></th>
</thead>
<tbody>
<tr>
<td>

```ts
t.effectConnection({
type: "Int",
effect: {
/* ... */
},
resolve: () => Effect.succeed([1, 2, 3, 4]),
});
```

</td>
<td>

```ts
t.connection({
type: "Int",
resolve: async (_root, args) =>
resolveArrayConnection(
{ args },
await t.effect(Effect.succeed([1, 2, 3, 4]))
),
});

t.connection({
type: "Int",
resolve: async (_root, args) =>
resolveCursorConnection(
{ args, toCursor: (id) => id },
(_params) => t.effect(Effect.succeed([1, 2, 3, 4]))
),
});

t.connection({
type: "Int",
resolve: async (_root, args) =>
resolveOffsetConnection({ args }, (_params) =>
t.effect(Effect.succeed([1, 2, 3, 4]))
),
});
```

</td>
</tr>
</tbody>
</table>

## Removed `t.prismaEffect` (aka Prisma Integration)

`t.effect` works even if the end result of the Effect is a Promise.

<table>
<thead>
<tr>
<th><code>Before (0.x)</code></th>
<th><code>After (1.0.0 ~)</code></th>
</thead>
<tbody>
<tr>
<td>

```ts
t.prismaEffect({
type: "User",
effect: {
/* ... */
},
resolve: (query) =>
PrismaEffect.user.findFirstOrThrow({
...query,
}),
});
```

</td>
<td>

```ts
t.prismaField({
type: "User",
resolve: (query) =>
t.effect(
Effect.succeed(
prisma.user.findFirstOrThrow({
...query,
})
)
),
});
```

</td>
</tr>
</tbody>
</table>

## Removed error type inferring

Removed `errors.types` inference functionality provided by integration with the errors plugin.
6 changes: 3 additions & 3 deletions packages/pothos-plugin-effect/src/global-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
ShapeFromTypeParam,
TypeParam,
} from '@pothos/core';
import type { Runtime } from 'effect';
import type { Effect, Runtime } from 'effect';
import type { EffectPlugin } from './index.js';
import type * as PluginTypes from './types.js';

Expand Down Expand Up @@ -45,7 +45,7 @@ declare global {
Nullable extends FieldNullability<Type>,
Args extends InputFieldMap,
ResolveShape,
ResolveReturnShape,
ResolveReturnShape extends Effect.Effect<any>,
>(
options: PluginTypes.EffectFieldOptions<
Types,
Expand All @@ -65,7 +65,7 @@ declare global {
Nullable extends FieldNullability<Type>,
Args extends InputFieldMap,
ResolveShape,
ResolveReturnShape,
ResolveReturnShape extends Effect.Effect<any>,
Fields extends InputFieldMap,
InputName extends string,
ArgRequired extends boolean,
Expand Down
33 changes: 19 additions & 14 deletions packages/pothos-plugin-effect/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,28 @@ type Resolver<
Args,
Context,
Type,
Return,
Return extends Effect.Effect<any>,
> = (
parent: Parent,
args: Args,
context: Context,
info: GraphQLResolveInfo,
) => [Type] extends [readonly (infer Item)[] | null | undefined]
? ListResolveValue<R, Type, Item, Return>
: Effect.Effect<
MaybePromise<MaybeOption<Type>>,
unknown,
InferRequirements<R>
>;
) => [Effect.Effect.Success<Return>] extends [Type]
? [Type] extends [readonly (infer Item)[] | null | undefined]
? ListResolveValue<R, Type, Item, Return>
: Effect.Effect<
MaybePromise<MaybeOption<Type>>,
unknown,
InferRequirements<R>
>
: `Error: The resolved Effect is an invalid type.`;

type ListResolveValue<R extends Runtime.Runtime<never>, Type, Item, Return> = [
Return,
] extends [Stream.Stream<unknown>]
type ListResolveValue<
R extends Runtime.Runtime<never>,
Type,
Item,
Return extends Effect.Effect<any>,
> = [Return] extends [Stream.Stream<unknown>]
? GeneratorResolver<Type, Item> | Return
: null extends Type
? Effect.Effect<
Expand Down Expand Up @@ -85,7 +90,7 @@ interface FieldOptionsByKind<
Nullable extends FieldNullability<Type>,
Args extends InputFieldMap,
ResolveShape,
ResolveReturnShape,
ResolveReturnShape extends Effect.Effect<any>,
> {
Query: Omit<
PothosSchemaTypes.QueryFieldOptions<
Expand Down Expand Up @@ -208,7 +213,7 @@ export type EffectFieldOptions<
Args extends InputFieldMap,
Kind extends FieldKind,
ResolveShape,
ResolveReturnShape,
ResolveReturnShape extends Effect.Effect<any>,
> = FieldOptionsByKind<
Types,
ParentShape,
Expand All @@ -227,7 +232,7 @@ export type EffectFieldWithInputOptions<
Args extends InputFieldMap,
Kind extends FieldKind,
ResolveShape,
ResolveReturnShape,
ResolveReturnShape extends Effect.Effect<any>,
Fields extends InputFieldMap,
InputName extends string,
ArgRequired extends boolean,
Expand Down

0 comments on commit 1137774

Please sign in to comment.