@nxgt/janus-graphql 0.1.1 → 0.3.0

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.
Files changed (41) hide show
  1. package/README.md +110 -21
  2. package/dist/connection/connection.d.ts +36 -0
  3. package/dist/connection/connection.d.ts.map +1 -0
  4. package/dist/connection/credential.d.ts +34 -0
  5. package/dist/connection/credential.d.ts.map +1 -0
  6. package/dist/connection/types.d.ts +57 -0
  7. package/dist/connection/types.d.ts.map +1 -0
  8. package/dist/context.d.ts +11 -2
  9. package/dist/context.d.ts.map +1 -1
  10. package/dist/directives/apply.d.ts +10 -9
  11. package/dist/directives/apply.d.ts.map +1 -1
  12. package/dist/directives/guard.d.ts +2 -1
  13. package/dist/directives/guard.d.ts.map +1 -1
  14. package/dist/directives/read.d.ts +9 -1
  15. package/dist/directives/read.d.ts.map +1 -1
  16. package/dist/directives/validate.d.ts +7 -2
  17. package/dist/directives/validate.d.ts.map +1 -1
  18. package/dist/fresh.d.ts +37 -0
  19. package/dist/fresh.d.ts.map +1 -0
  20. package/dist/index.d.ts +12 -5
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +170 -23
  23. package/dist/index.js.map +14 -10
  24. package/dist/options.d.ts +17 -0
  25. package/dist/options.d.ts.map +1 -0
  26. package/dist/plugin.d.ts +8 -3
  27. package/dist/plugin.d.ts.map +1 -1
  28. package/dist/sdl.d.ts.map +1 -1
  29. package/dist/types.d.ts +6 -1
  30. package/dist/types.d.ts.map +1 -1
  31. package/docs/README.md +5 -3
  32. package/docs/guide/context.md +36 -3
  33. package/docs/guide/directives.md +64 -5
  34. package/docs/guide/errors.md +2 -1
  35. package/docs/guide/federation.md +2 -1
  36. package/docs/guide/step-up.md +186 -0
  37. package/docs/guide/subscriptions.md +251 -0
  38. package/docs/roadmap.md +29 -9
  39. package/docs/troubleshooting.md +218 -11
  40. package/graphql/janus.graphqls +8 -0
  41. package/package.json +11 -2
@@ -15,6 +15,7 @@ for what causes each.
15
15
  - [`TypeError: applyJanusDirectives(): @authenticated on … names the user type '…', which is not one of …`](#typeerror-applyjanusdirectives-authenticated-on--names-the-user-type--which-is-not-one-of-)
16
16
  - [`TypeError: applyJanusDirectives(): @authenticated on … names no user type`](#typeerror-applyjanusdirectives-authenticated-on--names-no-user-type)
17
17
  - [`TypeError: applyJanusDirectives(): the @authenticated on … admit no user type in common`](#typeerror-applyjanusdirectives-the-authenticated-on--admit-no-user-type-in-common)
18
+ - [`TypeError: applyJanusDirectives(): @fresh on … asks maxAge: …`](#typeerror-applyjanusdirectives-fresh-on--asks-maxage-)
18
19
  - [`TypeError: applyJanusDirectives(): @permission on … needs the permissions() instance`](#typeerror-applyjanusdirectives-permission-on--needs-the-permissions-instance)
19
20
  - [`TypeError: applyJanusDirectives(): @permission on … names the object type '…', which is not one of …`](#typeerror-applyjanusdirectives-permission-on--names-the-object-type--which-is-not-one-of-)
20
21
  - [`TypeError: applyJanusDirectives(): @permission on … asks '…', which … does not declare`](#typeerror-applyjanusdirectives-permission-on--asks--which--does-not-declare)
@@ -23,20 +24,35 @@ for what causes each.
23
24
  - [`TypeError: applyJanusDirectives(): @permission on … reads the …'s id from …, and … reads '…' of the object itself (fromField)`](#typeerror-applyjanusdirectives-permission-on--reads-the-s-id-from--and--reads--of-the-object-itself-fromfield)
24
25
  - [`TypeError: applyJanusDirectives(): @permission on … asks '…' of …, which reaches a when()`](#typeerror-applyjanusdirectives-permission-on--asks--of--which-reaches-a-when)
25
26
  - [`TypeError: applyJanusDirectives(): @permission on … finds loaders.…, which is not a function`](#typeerror-applyjanusdirectives-permission-on--finds-loaders-which-is-not-a-function)
26
- - [`Unknown directive "@authenticated"`, or `"@permission"`](#unknown-directive-authenticated-or-permission)
27
+ - [`Unknown directive "@authenticated"`, `"@fresh"` or `"@permission"`](#unknown-directive-authenticated-fresh-or-permission)
28
+ - [`Argument "@fresh(maxAge:)" of type "Int!" is required`, or `Argument "maxAge" has invalid value …`](#argument-freshmaxage-of-type-int-is-required-or-argument-maxage-has-invalid-value-)
27
29
  - [`TypeError: applyJanusDirectives(): type '…' is not a user type of auth`](#typeerror-applyjanusdirectives-type--is-not-a-user-type-of-auth)
28
30
  - [`TypeError: useJanus(): auth is not what janus() answered`](#typeerror-usejanus-auth-is-not-what-janus-answered)
29
31
  - [`TypeError: useJanus(): access is not what permissions() answered`](#typeerror-usejanus-access-is-not-what-permissions-answered)
32
+ - [`TypeError: useJanus(): clock is not a Clock`](#typeerror-usejanus-clock-is-not-a-clock)
33
+ - [`TypeError: janusConnection(): auth is not what janus() answered`, `access …`, `clock …`](#typeerror-janusconnection-auth-is-not-what-janus-answered-access--clock-)
34
+ - [`TypeError: janusConnection(): upgrade is not a function`](#typeerror-janusconnection-upgrade-is-not-a-function)
35
+
36
+ **Over graphql-ws**
37
+ - [The socket closed `4403: Forbidden` right after connecting](#the-socket-closed-4403-forbidden-right-after-connecting)
38
+ - [The socket closed `4500`](#the-socket-closed-4500)
39
+ - [A stream keeps its events after its session was revoked](#a-stream-keeps-its-events-after-its-session-was-revoked)
40
+ - [`TypeError: janusConnection(): the connection's extra is not an object`](#typeerror-janusconnection-the-connections-extra-is-not-an-object)
30
41
 
31
42
  **In a response**
32
43
  - [`UNAUTHENTICATED` for a signed-in user](#unauthenticated-for-a-signed-in-user)
33
44
  - [`FORBIDDEN` where the user should be allowed](#forbidden-where-the-user-should-be-allowed)
45
+ - [`STEP_UP_REQUIRED`, 403](#step_up_required-403)
46
+ - [`STEP_UP_REQUIRED` for a user who just signed in](#step_up_required-for-a-user-who-just-signed-in)
34
47
  - [`SERVICE_UNAVAILABLE`, 503, on every guarded field](#service_unavailable-503-on-every-guarded-field)
35
48
  - [`Unexpected error.`, 500, where a `JanusError` was thrown](#unexpected-error-500-where-a-januserror-was-thrown)
36
49
  - [`TypeError: … ctx.janus is not set`](#typeerror--ctxjanus-is-not-set)
37
- - [`TypeError: useJanus(): the GraphQL context has no request to authenticate`](#typeerror-usejanus-the-graphql-context-has-no-request-to-authenticate)
50
+ - [`TypeError: …: the GraphQL context has no request to authenticate`](#typeerror--the-graphql-context-has-no-request-to-authenticate)
38
51
  - [`TypeError: can(): ctx.janus.access is not set`](#typeerror-can-ctxjanusaccess-is-not-set)
39
52
  - [`TypeError: requireUser(): type is an empty list, which no user could pass`](#typeerror-requireuser-type-is-an-empty-list-which-no-user-could-pass)
53
+ - [`TypeError: requireFresh(): maxAge is a duration with its unit`](#typeerror-requirefresh-maxage-is-a-duration-with-its-unit)
54
+ - [`TypeError: requireFresh(): maxAge: "…" is not a duration`](#typeerror-requirefresh-maxage--is-not-a-duration)
55
+ - [`TypeError: requireFresh(): maxAge: a duration must be above zero`](#typeerror-requirefresh-maxage-a-duration-must-be-above-zero)
40
56
  - [`@permission on … resolved no object id from … — answered NOT_FOUND`](#permission-on--resolved-no-object-id-from---answered-not_found)
41
57
  - [`NOT_FOUND` where the user should be allowed](#not_found-where-the-user-should-be-allowed)
42
58
  - [A 403 that tells a user the object exists](#a-403-that-tells-a-user-the-object-exists)
@@ -52,6 +68,9 @@ for what causes each.
52
68
  - [`'…' does not exist in type 'Loaders<…>'`, or `'Conditions<…>'`](#-does-not-exist-in-type-loaders-or-conditions)
53
69
  - [`Type '{ …: … }' is not assignable to type 'never'`, on `loaders`](#type-----is-not-assignable-to-type-never-on-loaders)
54
70
  - [`Source has 0 element(s) but target requires 1`, on `requireUser()`](#source-has-0-elements-but-target-requires-1-on-requireuser)
71
+ - [`Argument of type '600' is not assignable to parameter of type '`${number}ms` | …'`, on `requireFresh()`](#argument-of-type-600-is-not-assignable-to-parameter-of-type-numberms---on-requirefresh)
72
+ - [`Expected 2 arguments, but got 1`, on `requireFresh()`](#expected-2-arguments-but-got-1-on-requirefresh)
73
+ - [`Type 'number' is not assignable to type 'Clock'`](#type-number-is-not-assignable-to-type-clock)
55
74
 
56
75
  ## At start-up
57
76
 
@@ -95,6 +114,24 @@ type Ward @authenticated(type: ["staff"]) {
95
114
  **Fix:** widen one of them, or move the field to a type whose directive
96
115
  admits the users it is for.
97
116
 
117
+ ### `TypeError: applyJanusDirectives(): @fresh on … asks maxAge: …`
118
+
119
+ **When:** at start-up, for a schema that uses `@fresh`.
120
+
121
+ **Why:** `maxAge` is not above zero — `@fresh(maxAge: 0)` or a negative
122
+ number — so no session could ever be fresh enough, and every request would
123
+ be refused. The message names the field, and the location the directive was
124
+ written on when it is not the field: `@fresh on Account (read by
125
+ Account.email)`.
126
+
127
+ **Fix:** write a number of **seconds** above zero:
128
+
129
+ ```graphql
130
+ type Mutation {
131
+ changeEmail(email: String!): User @fresh(maxAge: 600) # ten minutes
132
+ }
133
+ ```
134
+
98
135
  ### `TypeError: applyJanusDirectives(): @permission on … needs the permissions() instance`
99
136
 
100
137
  **When:** at start-up, for a schema that uses `@permission`.
@@ -192,7 +229,7 @@ than a function of it, from JavaScript or past a cast.
192
229
 
193
230
  **Fix:** `loaders: { record: (id) => records.find(id) }`.
194
231
 
195
- ### `Unknown directive "@authenticated"`, or `"@permission"`
232
+ ### `Unknown directive "@authenticated"`, `"@fresh"` or `"@permission"`
196
233
 
197
234
  **Why:** graphql-js builds the schema before `useJanus()` sees it, and the
198
235
  directive is not declared.
@@ -202,6 +239,18 @@ directive is not declared.
202
239
  generator reading files takes
203
240
  `node_modules/@nxgt/janus-graphql/graphql/janus.graphqls`.
204
241
 
242
+ ### `Argument "@fresh(maxAge:)" of type "Int!" is required`, or `Argument "maxAge" has invalid value …`
243
+
244
+ graphql 16 words the first `Directive "@fresh" argument "maxAge" of type
245
+ "Int!" is required, but it was not provided.`
246
+
247
+ **Why:** graphql-js refuses the directive at start-up: `@fresh` without
248
+ `maxAge`, when the schema is built; or with a value that is not an `Int` —
249
+ a fraction, a string such as `"10m"` — when `useJanus()` reads it.
250
+
251
+ **Fix:** a whole number of seconds: `@fresh(maxAge: 600)`. A duration with a
252
+ unit belongs to `requireFresh(ctx, '10m')`, in a resolver.
253
+
205
254
  ### `TypeError: applyJanusDirectives(): type '…' is not a user type of auth`
206
255
 
207
256
  **When:** at start-up, with `useJanus({ auth, type })` or
@@ -228,6 +277,83 @@ its place, or the module that exports `auth` not loaded yet.
228
277
  **Fix:** `useJanus({ auth, access })`, with `access` what `permissions()`
229
278
  answered — or leave `access` out when no field uses `@permission` or `can()`.
230
279
 
280
+ ### `TypeError: useJanus(): clock is not a Clock`
281
+
282
+ **Why:** `clock` has no `now()` — a timestamp such as `Date.now()`, or a
283
+ `Date`, passed from JavaScript or cast past the compiler.
284
+
285
+ **Fix:** pass the clock given to `janus()` — `fixedClock(…)` from
286
+ `@nxgt/janus` in a spec — or leave `clock` out for the system's:
287
+ `useJanus({ auth, clock })`.
288
+
289
+ ### `TypeError: janusConnection(): auth is not what janus() answered`, `access …`, `clock …`
290
+
291
+ **Why:** the same checks as `useJanus()`'s, named for `janusConnection()`:
292
+ `auth` is not what `janus()` answered, `access` not what `permissions()`
293
+ answered, `clock` not a `Clock`.
294
+
295
+ **Fix:** `janusConnection({ auth })`, with the `access` and `clock` given to
296
+ `useJanus()` when you pass them at all.
297
+
298
+ ### `TypeError: janusConnection(): upgrade is not a function`
299
+
300
+ **Why:** `upgrade` is how `onConnect` finds the upgrade request on a
301
+ transport whose `extra` does not carry it, and it was given something else.
302
+
303
+ **Fix:** a function of graphql-ws's context, or nothing — `ctx.extra.request`
304
+ is then read, as `graphql-ws/use/ws` sets it:
305
+
306
+ ```ts
307
+ janusConnection({ auth, upgrade: (ctx: { readonly extra: { readonly socket: Upgraded } }) => ctx.extra.socket.data.request });
308
+ ```
309
+
310
+ ## Over graphql-ws
311
+
312
+ ### The socket closed `4403: Forbidden` right after connecting
313
+
314
+ **Why:** `onConnect` found no credential that authenticates: none at all,
315
+ an unknown or lapsed token, a user gone or inactive, a user of another
316
+ type than `janusConnection({ type })`, or a `connectionParams.authorization`
317
+ that is not a string. A `Bearer` `connectionParams.authorization` is
318
+ read before the upgrade request, and **the first present wins**: a lapsed
319
+ token there refuses the connection even beside a live cookie. One of
320
+ another scheme (`Basic …`) does not count, and the cookie is read.
321
+
322
+ **Fix:** send `connectionParams: { authorization: 'Bearer <token>' }` —
323
+ the key lower-case — or connect from a browser holding the session cookie,
324
+ to the origin that set it. On Bun, pass `upgrade`, or the cookie is never
325
+ read. graphql-ws's client retries a `4403`; a `connectionParams` function
326
+ is asked again each time.
327
+
328
+ ### The socket closed `4500`
329
+
330
+ **Why:** the sessions store could not answer while `onConnect`
331
+ authenticated — `STORE_FAILED`. `graphql-ws/use/ws` closes the socket
332
+ `4500` and logs the error with `console.error`. It is an outage, **never a
333
+ refusal**: `4403` would tell the client its session is bad.
334
+
335
+ **Fix:** the store. graphql-ws's client does not retry a `4500` by default;
336
+ set `shouldRetry` to retry an outage.
337
+
338
+ ### A stream keeps its events after its session was revoked
339
+
340
+ **Why:** an operation is authenticated once, when it subscribes, and
341
+ each event's `@authenticated` reads that answer. The next operation on
342
+ the connection is refused `UNAUTHENTICATED`, and a reconnection `4403`.
343
+
344
+ **Fix:** close the session's sockets when you revoke it
345
+ ([the subscriptions guide](guide/subscriptions.md#a-session-revoked-while-connected)).
346
+ A permission revoked needs nothing: `@permission` asks again on every event.
347
+
348
+ ### `TypeError: janusConnection(): the connection's extra is not an object`
349
+
350
+ **Why:** `onConnect` was called with a context whose `extra` is not an
351
+ object — by hand, or by a transport of your own. It remembers the
352
+ connection by that object.
353
+
354
+ **Fix:** pass `onConnect` to graphql-ws's `useServer()` or `makeHandler()`,
355
+ which give it the context they made.
356
+
231
357
  ## In a response
232
358
 
233
359
  ### `UNAUTHENTICATED` for a signed-in user
@@ -251,12 +377,37 @@ says applies to it too.
251
377
  **Fix:** read the directives on the field, on its type, and on every
252
378
  interface the type implements.
253
379
 
380
+ ### `STEP_UP_REQUIRED`, 403
381
+
382
+ **Why:** a field `@fresh(maxAge)` guards, or a `requireFresh(ctx, maxAge)`,
383
+ was reached by a session that proved who it is `maxAge` ago or more — at
384
+ its sign-in, or at its last `auth.stepUp.confirm`. Renewing a sliding
385
+ session does not count. This is the answer working: it tells the client to
386
+ ask for a step-up.
387
+
388
+ **Fix:** in the client, on `extensions.code === 'STEP_UP_REQUIRED'`, run the
389
+ step-up — `requestStepUp`, then `confirmStepUp(challenge, code)` — and send
390
+ the request again. The mutations are in
391
+ [the step-up over GraphQL](guide/step-up.md).
392
+
393
+ ### `STEP_UP_REQUIRED` for a user who just signed in
394
+
395
+ **Why:** `@fresh` reads the time from `useJanus({ clock })`, and the session
396
+ was stamped with `janus()`'s. Two different clocks: `janus({ clock:
397
+ fixedClock(…) })` with `useJanus()` given none, in a spec — the session looks
398
+ days old. Or `maxAge` written as minutes: `@fresh(maxAge: 10)` is ten
399
+ seconds, not ten minutes.
400
+
401
+ **Fix:** give both the same clock — `useJanus({ auth, clock })` — and write
402
+ `maxAge` in seconds: `@fresh(maxAge: 600)` for ten minutes.
403
+
254
404
  ### `SERVICE_UNAVAILABLE`, 503, on every guarded field
255
405
 
256
406
  **Why:** a store could not answer — `STORE_FAILED`. The sessions store for
257
- `@authenticated`, `requireUser()` and `ctx.janus.user()`; the relation store
407
+ `@authenticated`, `@fresh`, `requireUser()`, `requireFresh()` and
408
+ `ctx.janus.user()`; the relation store
258
409
  for `can()` and `@permission` — and a loader of yours that threw
259
- `StoreFailure`. It is never answered `UNAUTHENTICATED` or `FORBIDDEN`.
410
+ `StoreFailure`. It is never answered `UNAUTHENTICATED`, `FORBIDDEN` or `STEP_UP_REQUIRED`.
260
411
 
261
412
  **Fix:** the store: its connection, its credentials, its availability. The
262
413
  message carries nothing of the store's; log the error where you call
@@ -278,14 +429,21 @@ transformed with `applyJanusDirectives()` and served by something else.
278
429
 
279
430
  **Fix:** `plugins: [useJanus({ auth })]`.
280
431
 
281
- ### `TypeError: useJanus(): the GraphQL context has no request to authenticate`
432
+ ### `TypeError: …: the GraphQL context has no request to authenticate`
282
433
 
283
- **Why:** the context was built without `request` — a transport that is not
284
- HTTP, such as a WebSocket subscription.
434
+ **Why:** the context was built without `request`, and for no connection
435
+ `janusConnection().onConnect` accepted: a transport that is not HTTP; a
436
+ graphql-ws server without `onConnect`; or Yoga's recipe with the context
437
+ built from something other than `{ ...ctx, … }`, which drops `ctx.extra`,
438
+ where `useJanus()` finds the connection. The message opens with
439
+ `useJanus():` under Yoga, and with `janusConnection().context:` without
440
+ it — the `context` of a server whose `onConnect` is not
441
+ `janusConnection()`'s.
285
442
 
286
- **Fix:** for now, authenticate subscriptions over HTTP (Yoga's server-sent
287
- events carry the request). A connection-level wiring for graphql-ws is on
288
- the [roadmap](roadmap.md).
443
+ **Fix:** over graphql-ws, pass `onConnect: janusConnection({ auth }).onConnect`
444
+ to `useServer()`, and keep the `...ctx` spread in `yoga.getEnveloped()`
445
+ ([the subscriptions guide](guide/subscriptions.md)). Without Yoga, pass
446
+ `context: connection.context` too.
289
447
 
290
448
  ### `TypeError: can(): ctx.janus.access is not set`
291
449
 
@@ -307,6 +465,30 @@ signed-in user:
307
465
  const user = await requireUser(ctx, allowed.length > 0 ? { type: allowed } : {});
308
466
  ```
309
467
 
468
+ ### `TypeError: requireFresh(): maxAge is a duration with its unit`
469
+
470
+ **Why:** `requireFresh(ctx, 600)` — a bare number, from JavaScript or built
471
+ at run time. `@nxgt/janus` would read it as 600 milliseconds, where
472
+ `@fresh(maxAge: 600)` reads ten minutes, so it is refused rather than
473
+ guessed. The compiler refuses a literal number.
474
+
475
+ **Fix:** write the unit: `requireFresh(ctx, '10m')`, or `'600s'`.
476
+
477
+ ### `TypeError: requireFresh(): maxAge: "…" is not a duration`
478
+
479
+ **Why:** the string is not a number followed by `ms`, `s`, `m`, `h` or `d`
480
+ — `'10 minutes'`, `'10 m'`.
481
+
482
+ **Fix:** `requireFresh(ctx, '10m')`.
483
+
484
+ ### `TypeError: requireFresh(): maxAge: a duration must be above zero`
485
+
486
+ **Why:** `requireFresh(ctx, '0m')` — no session is ever fresh within no
487
+ time, so every request would be refused. The compiler lets it through: the
488
+ type reads a number and a unit, not their value.
489
+
490
+ **Fix:** a duration above zero, `requireFresh(ctx, '10m')`.
491
+
310
492
  ### `@permission on … resolved no object id from … — answered NOT_FOUND`
311
493
 
312
494
  **Where:** a warning, through `process.emitWarning` with the code
@@ -469,3 +651,28 @@ throws
469
651
 
470
652
  **Fix:** name at least one user type, `{ type: ['staff'] }`, or leave `type`
471
653
  out to admit any signed-in user.
654
+
655
+ ### `Argument of type '600' is not assignable to parameter of type '`${number}ms` | …'`, on `requireFresh()`
656
+
657
+ The full message ends `` '`${number}ms` | `${number}s` | `${number}m` |
658
+ `${number}h` | `${number}d`' ``; the same for `'10 minutes'`.
659
+
660
+ **Why:** `requireFresh(ctx, maxAge)` takes a duration with its unit. A bare
661
+ number would be milliseconds to `@nxgt/janus` and seconds to `@fresh`, so
662
+ neither is guessed.
663
+
664
+ **Fix:** `requireFresh(ctx, '10m')`.
665
+
666
+ ### `Expected 2 arguments, but got 1`, on `requireFresh()`
667
+
668
+ **Why:** `requireFresh(ctx)` — how recent the proof must be has no default.
669
+
670
+ **Fix:** `requireFresh(ctx, '10m')`.
671
+
672
+ ### `Type 'number' is not assignable to type 'Clock'`
673
+
674
+ **Why:** `useJanus({ auth, clock: Date.now() })` — a timestamp, where a
675
+ clock answers `now()`.
676
+
677
+ **Fix:** pass the clock given to `janus()`, `fixedClock(…)` in a spec, or
678
+ leave `clock` out.
@@ -7,6 +7,14 @@ directive @authenticated(
7
7
  type: [String!]
8
8
  ) on OBJECT | INTERFACE | FIELD_DEFINITION
9
9
 
10
+ """
11
+ Only a session that proved who it is less than `maxAge` seconds ago reaches
12
+ this field, or every field of this type or interface: signed in, or confirmed
13
+ since by a step-up. Anonymous is answered UNAUTHENTICATED, an older session
14
+ STEP_UP_REQUIRED. Where several apply, the smallest `maxAge` holds.
15
+ """
16
+ directive @fresh(maxAge: Int!) on OBJECT | INTERFACE | FIELD_DEFINITION
17
+
10
18
  """
11
19
  What a denied `@permission` answers.
12
20
  """
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nxgt/janus-graphql",
3
- "version": "0.1.1",
4
- "description": "GraphQL for @nxgt/janus: an envelop plugin with the signed-in user on the context, fields guarded by @authenticated and @permission, and every error with the status it deserves",
3
+ "version": "0.3.0",
4
+ "description": "GraphQL for @nxgt/janus: an envelop plugin with the signed-in user on the context, fields guarded by @authenticated, @fresh and @permission, and every error with the status it deserves",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -57,8 +57,11 @@
57
57
  "@graphql-tools/utils": "^12.0.1",
58
58
  "@nxgt/janus": "^0.12.0",
59
59
  "@types/bun": "^1.4.2",
60
+ "@types/ws": "^8.18.1",
60
61
  "graphql": "^17.0.2",
62
+ "graphql-ws": "^6.3.0",
61
63
  "graphql-yoga": "^5.24.1",
64
+ "ws": "^8.22.0",
62
65
  "zod": "^4.6.5"
63
66
  },
64
67
  "peerDependencies": {
@@ -66,6 +69,12 @@
66
69
  "@graphql-tools/utils": ">=10.0.0 <13",
67
70
  "@nxgt/janus": "^0.12.0",
68
71
  "graphql": "^16.9.0 || ^17.0.0",
72
+ "graphql-ws": "^6.0.0",
69
73
  "typescript": "^6.0.3"
74
+ },
75
+ "peerDependenciesMeta": {
76
+ "graphql-ws": {
77
+ "optional": true
78
+ }
70
79
  }
71
80
  }