@nxgt/janus-graphql 0.1.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.
- package/LICENSE +21 -0
- package/README.md +248 -0
- package/dist/context.d.ts +63 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/directives/apply.d.ts +46 -0
- package/dist/directives/apply.d.ts.map +1 -0
- package/dist/directives/guard.d.ts +21 -0
- package/dist/directives/guard.d.ts.map +1 -0
- package/dist/directives/permission/enforce.d.ts +24 -0
- package/dist/directives/permission/enforce.d.ts.map +1 -0
- package/dist/directives/permission/model.d.ts +35 -0
- package/dist/directives/permission/model.d.ts.map +1 -0
- package/dist/directives/permission/path.d.ts +31 -0
- package/dist/directives/permission/path.d.ts.map +1 -0
- package/dist/directives/permission/validate.d.ts +42 -0
- package/dist/directives/permission/validate.d.ts.map +1 -0
- package/dist/directives/read.d.ts +35 -0
- package/dist/directives/read.d.ts.map +1 -0
- package/dist/directives/validate.d.ts +33 -0
- package/dist/directives/validate.d.ts.map +1 -0
- package/dist/directives/words.d.ts +7 -0
- package/dist/directives/words.d.ts.map +1 -0
- package/dist/errors.d.ts +44 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/helpers.d.ts +56 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +645 -0
- package/dist/index.js.map +24 -0
- package/dist/memo.d.ts +16 -0
- package/dist/memo.d.ts.map +1 -0
- package/dist/plugin.d.ts +32 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/sdl.d.ts +12 -0
- package/dist/sdl.d.ts.map +1 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/wiring.d.ts +56 -0
- package/dist/wiring.d.ts.map +1 -0
- package/docs/README.md +18 -0
- package/docs/guide/context.md +156 -0
- package/docs/guide/directives.md +312 -0
- package/docs/guide/errors.md +138 -0
- package/docs/guide/federation.md +70 -0
- package/docs/guide/telemetry.md +45 -0
- package/docs/roadmap.md +59 -0
- package/docs/troubleshooting.md +471 -0
- package/graphql/janus.graphqls +36 -0
- package/package.json +71 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/directives/validate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACN,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAErB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAoB,eAAe,EAAE,MAAM,QAAQ,CAAC;AAGhE,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC3B,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC3C,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;CACjD;AAED,6FAA6F;AAC7F,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,gBAAgB,GACtB,WAAW,GAAG,IAAI,CAWpB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** The phrases the schema-time refusals share. */
|
|
2
|
+
export declare const PREFIX = "applyJanusDirectives()";
|
|
3
|
+
/** `Query.me`, or `Record (read by Record.title)` for a type's directive. */
|
|
4
|
+
export declare function on(where: string, field: string): string;
|
|
5
|
+
/** `'a', 'b'`. */
|
|
6
|
+
export declare function list(names: readonly string[]): string;
|
|
7
|
+
//# sourceMappingURL=words.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"words.d.ts","sourceRoot":"","sources":["../../src/directives/words.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAElD,eAAO,MAAM,MAAM,2BAA2B,CAAC;AAE/C,6EAA6E;AAC7E,wBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,kBAAkB;AAClB,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAErD"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every refusal as a `GraphQLError` whose `extensions` carry a `code` and the
|
|
3
|
+
* HTTP status Yoga answers with: `{ code, http: { status } }`. This package
|
|
4
|
+
* defines no error class of its own — a denial is a `GraphQLError`, and what
|
|
5
|
+
* `@nxgt/janus` throws stays its own until `janusMaskError()` reads it.
|
|
6
|
+
*/
|
|
7
|
+
import { JanusError } from '@nxgt/janus';
|
|
8
|
+
import { GraphQLError } from 'graphql';
|
|
9
|
+
/** What a guard answers without asking `@nxgt/janus`: no user, or not this one. */
|
|
10
|
+
export type DenialCode = 'UNAUTHENTICATED' | 'FORBIDDEN' | 'NOT_FOUND';
|
|
11
|
+
/** A denial: `UNAUTHENTICATED` 401, `FORBIDDEN` 403 or `NOT_FOUND` 404. */
|
|
12
|
+
export declare function denial(code: DenialCode, message?: string): GraphQLError;
|
|
13
|
+
/**
|
|
14
|
+
* A `JanusError` as the client may read it: its code and status, and only
|
|
15
|
+
* what the client can act on — `issues`, `minLength`, `attemptsLeft`. Never
|
|
16
|
+
* `reason`, `login`, `slot` or a cause: those are for your logs.
|
|
17
|
+
*
|
|
18
|
+
* `STORE_FAILED` is `SERVICE_UNAVAILABLE` 503 — **an outage is never a
|
|
19
|
+
* denial** — and no message of the core's reaches the client.
|
|
20
|
+
*/
|
|
21
|
+
export declare function janusGraphQLError(error: JanusError): GraphQLError;
|
|
22
|
+
/**
|
|
23
|
+
* A rejection handler: a `JanusError` becomes its `GraphQLError`, anything
|
|
24
|
+
* else goes on as it is. `.then(undefined, rethrown)`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function rethrown(error: unknown): never;
|
|
27
|
+
/** Yoga's and envelop's `maskError` signature. */
|
|
28
|
+
export type MaskError = (error: unknown, message: string, isDev?: boolean) => Error;
|
|
29
|
+
/**
|
|
30
|
+
* Yoga's `maskedErrors.maskError`: a `JanusError` a resolver let through is
|
|
31
|
+
* answered with its code and status — `STORE_FAILED` as 503, never masked
|
|
32
|
+
* into a 500 and never a denial — and every other error goes to `fallback`.
|
|
33
|
+
*
|
|
34
|
+
* Without a `fallback`, a `GraphQLError` is kept and anything else becomes
|
|
35
|
+
* `message`, with no detail. Pass Yoga's own `maskError` to keep its
|
|
36
|
+
* development-mode details:
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { createYoga, maskError } from 'graphql-yoga';
|
|
40
|
+
* createYoga({ schema, plugins, maskedErrors: { maskError: janusMaskError(maskError) } });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function janusMaskError(fallback?: MaskError): MaskError;
|
|
44
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAmC,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,mFAAmF;AACnF,MAAM,MAAM,UAAU,GAAG,iBAAiB,GAAG,WAAW,GAAG,WAAW,CAAC;AAEvE,2EAA2E;AAC3E,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAKvE;AAaD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,CAQjE;AA4CD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAE9C;AAED,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,CACvB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,OAAO,KACX,KAAK,CAAC;AAEX;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,SAAkB,GAAG,SAAS,CAiBtE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two calls a resolver makes itself: `requireUser` where a directive
|
|
3
|
+
* would not do, and `can` for a check the schema cannot express.
|
|
4
|
+
*/
|
|
5
|
+
import type { CheckArgs, CheckableOf, ModelConfig, ObjectRef, ObjectTypeOf, Permissions } from '@nxgt/janus/permissions';
|
|
6
|
+
/** What `requireUser()` takes. */
|
|
7
|
+
export interface RequireUserOptions<T extends string> {
|
|
8
|
+
/**
|
|
9
|
+
* Only a user of this type, or of one of these — never an empty list,
|
|
10
|
+
* which no user could pass: any other is `FORBIDDEN`.
|
|
11
|
+
*/
|
|
12
|
+
readonly type?: T | readonly [T, ...T[]];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The signed-in user, narrowed to `type` when it is given — or a denial:
|
|
16
|
+
* `UNAUTHENTICATED` 401 for an anonymous request, `FORBIDDEN` 403 for a user
|
|
17
|
+
* of another type. A store that cannot answer is `SERVICE_UNAVAILABLE` 503,
|
|
18
|
+
* never either of them.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const staff = await requireUser(ctx, { type: 'staff' });
|
|
22
|
+
* staff.username; // typed: a staff member
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function requireUser<U extends {
|
|
26
|
+
readonly type: string;
|
|
27
|
+
}, const T extends U['type'] = U['type']>(ctx: {
|
|
28
|
+
readonly janus: {
|
|
29
|
+
user(): Promise<U | null>;
|
|
30
|
+
};
|
|
31
|
+
}, options?: RequireUserOptions<T>): Promise<Extract<U, {
|
|
32
|
+
readonly type: T;
|
|
33
|
+
}>>;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the request's user holds `permission` on `object`, typed as
|
|
36
|
+
* `access.can` is: the permission must be one the object's type declares,
|
|
37
|
+
* the object must carry every field its `fromField`s read, and `{ ctx }` is
|
|
38
|
+
* required exactly when a condition is reachable. Anonymous answers `false`.
|
|
39
|
+
*
|
|
40
|
+
* **A failure throws**: a store that cannot answer is `SERVICE_UNAVAILABLE`
|
|
41
|
+
* 503, never `false`.
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* if (!(await can(ctx, 'edit', { type: 'record', ...record }))) return null;
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function can<C extends ModelConfig, const T extends ObjectTypeOf<C>, const P extends CheckableOf<C, T>>(ctx: {
|
|
48
|
+
readonly janus: {
|
|
49
|
+
user(): Promise<{
|
|
50
|
+
readonly type: string;
|
|
51
|
+
readonly id: string;
|
|
52
|
+
} | null>;
|
|
53
|
+
readonly access: Pick<Permissions<C>, 'can'>;
|
|
54
|
+
};
|
|
55
|
+
}, permission: P, object: ObjectRef<C, T>, ...options: CheckArgs<C, T, P>): Promise<boolean>;
|
|
56
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,SAAS,EACT,WAAW,EACX,WAAW,EACX,SAAS,EACT,YAAY,EACZ,WAAW,EACX,MAAM,yBAAyB,CAAC;AAIjC,kCAAkC;AAClC,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,MAAM;IACnD;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;CACzC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAChC,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACnC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAErC,GAAG,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE;QAAE,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;KAAE,CAAA;CAAE,EACtD,OAAO,GAAE,kBAAkB,CAAC,CAAC,CAAM,GACjC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,CAAC,CAiB3C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,GAAG,CACxB,CAAC,SAAS,WAAW,EACrB,KAAK,CAAC,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EAC/B,KAAK,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAEjC,GAAG,EAAE;IACJ,QAAQ,CAAC,KAAK,EAAE;QACf,IAAI,IAAI,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC,CAAC;QACvE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;KAC7C,CAAC;CACF,EACD,UAAU,EAAE,CAAC,EACb,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EACvB,GAAG,OAAO,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC5B,OAAO,CAAC,OAAO,CAAC,CAalB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nxgt/janus-graphql` — `@nxgt/janus` in a GraphQL server.
|
|
3
|
+
*
|
|
4
|
+
* - `useJanus({ auth, access?, type?, loaders?, conditions? })` — the
|
|
5
|
+
* envelop plugin: `ctx.janus` on every request, and the directives —
|
|
6
|
+
* `@authenticated`, `@permission` — applied to the schema;
|
|
7
|
+
* - `janusTypeDefs` — the directives' SDL, also shipped as
|
|
8
|
+
* `graphql/janus.graphqls`;
|
|
9
|
+
* - `applyJanusDirectives(schema, { auth })` — the schema transform alone;
|
|
10
|
+
* - `requireUser(ctx, { type? })` and `can(ctx, permission, object)` — the
|
|
11
|
+
* calls a resolver makes itself;
|
|
12
|
+
* - `janusMaskError(fallback?)` — Yoga's `maskError`: a `JanusError` as its
|
|
13
|
+
* code and status, `STORE_FAILED` as 503 and never as 401 or 403.
|
|
14
|
+
* - `janusGraphQLError(error)` — a `JanusError` as the `GraphQLError` the
|
|
15
|
+
* client reads, and `denial(code, message?)` — a denial of your own.
|
|
16
|
+
*
|
|
17
|
+
* It defines no error class: a denial is a `GraphQLError`, and what it lets
|
|
18
|
+
* through is `@nxgt/janus`'s own.
|
|
19
|
+
*/
|
|
20
|
+
export { applyJanusDirectives, type JanusDirectivesOptions, } from './directives/apply';
|
|
21
|
+
export { type DenialCode, denial, janusGraphQLError, janusMaskError, type MaskError, } from './errors';
|
|
22
|
+
export { can, type RequireUserOptions, requireUser } from './helpers';
|
|
23
|
+
export { useJanus } from './plugin';
|
|
24
|
+
export { janusTypeDefs } from './sdl';
|
|
25
|
+
export type { Auth, JanusContext, JanusOnContext, JanusOptions, UserOfAuth, } from './types';
|
|
26
|
+
export type { Conditions, LoadedObject, Loaders } from './wiring';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACN,oBAAoB,EACpB,KAAK,sBAAsB,GAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,KAAK,UAAU,EACf,MAAM,EACN,iBAAiB,EACjB,cAAc,EACd,KAAK,SAAS,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,GAAG,EAAE,KAAK,kBAAkB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,YAAY,EACX,IAAI,EACJ,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,UAAU,GACV,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
|