Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2 #45

Merged
merged 2 commits into from
Jul 17, 2024
Merged

V2 #45

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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
"@changesets/cli": "^2.27.1"
},
"resolutions": {
"@vitest/coverage-v8": "1.5.2",
"vitest": "1.5.2",
"@vitest/coverage-v8": "2",
"vitest": "2",
"nanobundle": "2.0.0",
"typescript": "5.5.0-beta",
"graphql": "*"
Expand Down
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.
12 changes: 6 additions & 6 deletions packages/pothos-plugin-effect/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
},
"license": "MIT",
"devDependencies": {
"@pothos/core": "3.41.0",
"@pothos/plugin-errors": "3.11.1",
"@pothos/plugin-prisma": "3.63.1",
"@pothos/plugin-relay": "3.46.0",
"@pothos/plugin-with-input": "^3.10.1",
"@pothos/core": "^4.0.2",
"@pothos/plugin-errors": "^4.0.2",
"@pothos/plugin-prisma": "^4.0.5",
"@pothos/plugin-relay": "^4.0.2",
"@pothos/plugin-with-input": "^4.0.2",
"@prisma/client": "5.9.1",
"@types/better-sqlite3": "^7.6.9",
"@types/node": "20.11.13",
Expand All @@ -59,7 +59,7 @@
"vitest": "*"
},
"peerDependencies": {
"@pothos/core": "^3",
"@pothos/core": "^4",
"effect": ">=3.0.0 <4",
"graphql": "^16 || ^17"
},
Expand Down
2 changes: 2 additions & 0 deletions packages/pothos-plugin-effect/prisma/pothos-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default interface PrismaTypes {
posts: {
Shape: Post[];
Name: "Post";
Nullable: false;
};
};
};
Expand All @@ -36,6 +37,7 @@ export default interface PrismaTypes {
author: {
Shape: User;
Name: "User";
Nullable: false;
};
};
};
Expand Down
28 changes: 20 additions & 8 deletions packages/pothos-plugin-effect/src/field-builder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FieldKind, RootFieldBuilder, SchemaTypes } from '@pothos/core';
import { Runtime } from 'effect';
import { executeEffect, executeStream } from 'effect-utils';
import { Effect, Runtime } from 'effect';
import { executeEffect, executeStream, isStream } from 'effect-utils';

const fieldBuilderProto =
RootFieldBuilder.prototype as PothosSchemaTypes.RootFieldBuilder<
Expand All @@ -11,14 +11,14 @@ const fieldBuilderProto =

fieldBuilderProto.executeEffect = function (effectFieldResult) {
const effectRuntime =
this.builder.options.effectOptions?.effectRuntime ?? Runtime.defaultRuntime;
this.builder.options.effect?.effectRuntime ?? Runtime.defaultRuntime;

return executeEffect(effectFieldResult, effectRuntime) as never;
};

fieldBuilderProto.executeStream = function (effectFieldResult) {
const effectRuntime =
this.builder.options.effectOptions?.effectRuntime ?? Runtime.defaultRuntime;
this.builder.options.effect?.effectRuntime ?? Runtime.defaultRuntime;

return executeStream(effectFieldResult, effectRuntime) as never;
};
Expand All @@ -31,8 +31,13 @@ fieldBuilderProto.effect = function (options) {
if ('resolve' in options) {
const effectFieldResult = options.resolve(root, args, context, info);

// @ts-ignore
return this.executeEffect(effectFieldResult);
if (Effect.isEffect(effectFieldResult)) {
return this.executeEffect(effectFieldResult);
}

if (isStream(effectFieldResult)) {
return this.executeStream(effectFieldResult);
}
}
},
// @ts-ignore
Expand All @@ -56,8 +61,15 @@ fieldBuilderProto.effectWithInput = function (options) {
if ('resolve' in options) {
const effectFieldResult = options.resolve(root, args, context, info);

// @ts-ignore
return this.executeEffect(effectFieldResult);
if (Effect.isEffect(effectFieldResult)) {
// @ts-ignore
return this.executeEffect(effectFieldResult);
}

if (isStream(effectFieldResult)) {
// @ts-ignore
return this.executeStream(effectFieldResult);
}
}
},
// @ts-ignore
Expand Down
Loading
Loading