@btravstack/pothos 0.29.0 → 0.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.mts +5 -2
- package/dist/index.mjs +32 -5
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -24,8 +24,8 @@ Every dependency is a peer: Pothos plugins and `graphql` each need one copy.
|
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
26
|
pnpm add @btravstack/pothos @pothos/core @pothos/plugin-errors @pothos/plugin-relay \
|
|
27
|
-
@unthrown/pothos@^0.1.
|
|
28
|
-
@orpc/client@2.0.0-beta.
|
|
27
|
+
@unthrown/pothos@^0.1.2 graphql unthrown zod \
|
|
28
|
+
@orpc/client@2.0.0-beta.34 @orpc/contract@2.0.0-beta.34
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
See
|
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { BasePlugin, FieldKind, FieldNullability, InputFieldMap, InputShapeFromFields, ObjectRef, OutputType, SchemaTypes, ShapeFromTypeParam, TypeParam } from "@pothos/core";
|
|
2
|
+
import { AsyncResult } from "unthrown";
|
|
3
|
+
import { GraphQLFieldResolver } from "graphql";
|
|
2
4
|
import { ResultConnectionOptions } from "@unthrown/pothos/relay";
|
|
3
5
|
import { CaseOf, Caseable, Refusals, ResultFieldOptions } from "@unthrown/pothos";
|
|
4
|
-
import { AsyncResult } from "unthrown";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
import { AnySchema, ErrorMap, ProcedureContract } from "@orpc/contract";
|
|
7
8
|
import { ConnectionShapeForType, DefaultConnectionArguments } from "@pothos/plugin-relay";
|
|
8
9
|
//#region src/plugin.d.ts
|
|
9
10
|
declare const pluginName = "orpc";
|
|
10
|
-
declare class PothosOrpcPlugin<Types extends SchemaTypes> extends BasePlugin<Types> {
|
|
11
|
+
declare class PothosOrpcPlugin<Types extends SchemaTypes> extends BasePlugin<Types> {
|
|
12
|
+
wrapArgMappers(resolve: GraphQLFieldResolver<unknown, Types["Context"], object>): GraphQLFieldResolver<unknown, Types["Context"], object>;
|
|
13
|
+
}
|
|
11
14
|
declare global {
|
|
12
15
|
export namespace PothosSchemaTypes {
|
|
13
16
|
interface Plugins<Types extends SchemaTypes> {
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import SchemaBuilder, { BasePlugin, RootFieldBuilder } from "@pothos/core";
|
|
2
|
+
import { Err, P, TaggedError, fromPromise, fromSafePromise, fromSafeThrowable } from "unthrown";
|
|
3
|
+
import { GraphQLError } from "graphql";
|
|
2
4
|
import { ORPCError } from "@orpc/client";
|
|
3
5
|
import "@unthrown/pothos/relay";
|
|
4
6
|
import { outcomeOf } from "@unthrown/pothos";
|
|
5
|
-
import { GraphQLError } from "graphql";
|
|
6
|
-
import { Err, P, TaggedError, fromPromise, fromSafePromise, fromSafeThrowable } from "unthrown";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
+
//#region src/access-refusal.ts
|
|
9
|
+
const accessMarker = Symbol("AccessRefusal");
|
|
10
|
+
var AccessRefusal = class extends GraphQLError {
|
|
11
|
+
[accessMarker] = this;
|
|
12
|
+
constructor(code) {
|
|
13
|
+
super("Service refused access", { extensions: { code } });
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const accessRefusal = (cause) => {
|
|
17
|
+
const marked = typeof cause === "object" && cause !== null && accessMarker in cause ? cause[accessMarker] : cause;
|
|
18
|
+
if (marked instanceof AccessRefusal) return marked;
|
|
19
|
+
return typeof cause === "object" && cause !== null && "cause" in cause && cause.cause instanceof AccessRefusal ? cause.cause : void 0;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
8
22
|
//#region src/contract.ts
|
|
9
23
|
/**
|
|
10
24
|
* The one Zod schema a procedure's contract declares for its input, typed as
|
|
@@ -55,7 +69,7 @@ const refusalsOf = (registry, procedure) => Object.fromEntries([...Object.keys(p
|
|
|
55
69
|
const Refusal = ACCESS_CODES.has(code) ? void 0 : registry[code];
|
|
56
70
|
return Refusal === void 0 ? [] : [[code, Refusal]];
|
|
57
71
|
}));
|
|
58
|
-
const accessRefusalOf = (cause) => cause instanceof ORPCError && (cause.code === "UNAUTHORIZED" || cause.code === "FORBIDDEN") ? new
|
|
72
|
+
const accessRefusalOf = (cause) => cause instanceof ORPCError && (cause.code === "UNAUTHORIZED" || cause.code === "FORBIDDEN") ? new AccessRefusal(cause.code) : void 0;
|
|
59
73
|
/**
|
|
60
74
|
* `call` handed the input the procedure's contract accepts, its answer decoded
|
|
61
75
|
* by `output`. `UNAUTHORIZED` and `FORBIDDEN`, declared or not, leave the
|
|
@@ -76,7 +90,10 @@ function withoutAccess(called) {
|
|
|
76
90
|
* **It answers a `Promise`, and that is the boundary**: a DataLoader's batch
|
|
77
91
|
* function answers a value or an `Error` per key.
|
|
78
92
|
*/
|
|
79
|
-
const loadProcedure = async (registry, procedure, call, input, output) =>
|
|
93
|
+
const loadProcedure = async (registry, procedure, call, input, output) => {
|
|
94
|
+
const called = await callProcedure(procedure, input, call, output);
|
|
95
|
+
return called.isDefect() && called.cause instanceof AccessRefusal ? called.cause : outcomeOf(called, refusalsOf(registry, procedure));
|
|
96
|
+
};
|
|
80
97
|
/**
|
|
81
98
|
* The `errors` option of a field that reads `procedure` through
|
|
82
99
|
* `loadProcedure`: the registered refusals it can answer, as the field's
|
|
@@ -105,7 +122,17 @@ const defineProcedureFields = () => {
|
|
|
105
122
|
//#endregion
|
|
106
123
|
//#region src/plugin.ts
|
|
107
124
|
const pluginName = "orpc";
|
|
108
|
-
var PothosOrpcPlugin = class extends BasePlugin {
|
|
125
|
+
var PothosOrpcPlugin = class extends BasePlugin {
|
|
126
|
+
wrapArgMappers(resolve) {
|
|
127
|
+
return (parent, args, context, info) => fromSafePromise(Promise.resolve(resolve(parent, args, context, info))).map((value) => {
|
|
128
|
+
const refusal = accessRefusal(value);
|
|
129
|
+
if (refusal !== void 0) throw refusal;
|
|
130
|
+
return value;
|
|
131
|
+
}).recoverDefect((cause) => {
|
|
132
|
+
throw accessRefusal(cause) ?? cause;
|
|
133
|
+
}).get();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
109
136
|
SchemaBuilder.registerPlugin(pluginName, PothosOrpcPlugin);
|
|
110
137
|
defineProcedureFields();
|
|
111
138
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btravstack/pothos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.1",
|
|
4
4
|
"description": "Pothos fields that call oRPC procedures, each declared error answered as a typed GraphQL refusal",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphql",
|
|
@@ -41,20 +41,22 @@
|
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@btravstack/tsconfig": "0.4.0",
|
|
44
|
-
"@orpc/client": "2.0.0-beta.
|
|
45
|
-
"@orpc/contract": "2.0.0-beta.
|
|
44
|
+
"@orpc/client": "2.0.0-beta.34",
|
|
45
|
+
"@orpc/contract": "2.0.0-beta.34",
|
|
46
46
|
"@pothos/core": "4.15.1",
|
|
47
47
|
"@pothos/plugin-errors": "4.9.3",
|
|
48
48
|
"@pothos/plugin-relay": "4.8.1",
|
|
49
49
|
"@types/node": "26.6.4",
|
|
50
|
-
"@unthrown/pothos": "0.1.
|
|
51
|
-
"@unthrown/vitest": "5.12.
|
|
50
|
+
"@unthrown/pothos": "0.1.2",
|
|
51
|
+
"@unthrown/vitest": "5.12.1",
|
|
52
52
|
"@vitest/coverage-v8": "5.0.3",
|
|
53
|
+
"dataloader": "2.2.3",
|
|
53
54
|
"graphql": "17.0.2",
|
|
55
|
+
"graphql-yoga": "5.24.1",
|
|
54
56
|
"tsdown": "0.23.0",
|
|
55
57
|
"typescript": "7.0.2",
|
|
56
58
|
"typescript-consumer": "npm:typescript@5.9.3",
|
|
57
|
-
"unthrown": "5.12.
|
|
59
|
+
"unthrown": "5.12.1",
|
|
58
60
|
"vitest": "5.0.3",
|
|
59
61
|
"zod": "4.6.5"
|
|
60
62
|
},
|
|
@@ -64,9 +66,9 @@
|
|
|
64
66
|
"@pothos/core": "^4.15.0",
|
|
65
67
|
"@pothos/plugin-errors": "^4.9.0",
|
|
66
68
|
"@pothos/plugin-relay": "^4.8.0",
|
|
67
|
-
"@unthrown/pothos": "^0.1.
|
|
69
|
+
"@unthrown/pothos": "^0.1.2",
|
|
68
70
|
"graphql": "^16.10.0 || ^17.0.0",
|
|
69
|
-
"unthrown": "^5.12.
|
|
71
|
+
"unthrown": "^5.12.1",
|
|
70
72
|
"zod": "^4.3.0"
|
|
71
73
|
},
|
|
72
74
|
"engines": {
|