@envelop/generic-auth 3.0.0 → 4.0.0-alpha-bed7c7d.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/index.d.ts +30 -16
- package/index.js +76 -50
- package/index.mjs +76 -50
- package/package.json +4 -1
- package/utils.d.ts +0 -2
package/index.d.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { DefaultContext, Plugin } from '@envelop/core';
|
|
2
|
-
import { DirectiveNode, GraphQLError,
|
|
3
|
-
export * from './utils';
|
|
2
|
+
import { DirectiveNode, FieldNode, GraphQLError, GraphQLObjectType } from 'graphql';
|
|
4
3
|
export declare class UnauthenticatedError extends GraphQLError {
|
|
5
4
|
}
|
|
6
5
|
export declare type ResolveUserFn<UserType, ContextType = DefaultContext> = (context: ContextType) => null | UserType | Promise<UserType | null>;
|
|
7
|
-
export declare type
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
export declare type ValidateUserFnParams<UserType> = {
|
|
7
|
+
/** The user object. */
|
|
8
|
+
user: UserType;
|
|
9
|
+
/** The field node from the operation that is being validated. */
|
|
10
|
+
fieldNode: FieldNode;
|
|
11
|
+
/** The object type which has the field that is being validated. */
|
|
12
|
+
objectType: GraphQLObjectType;
|
|
13
|
+
/** The directive node used for the authentication (If using an SDL flow). */
|
|
14
|
+
fieldAuthDirectiveNode: DirectiveNode | undefined;
|
|
15
|
+
/** The extensions used for authentication (If using an extension based flow). */
|
|
16
|
+
fieldAuthExtension: unknown | undefined;
|
|
17
|
+
};
|
|
18
|
+
export declare type ValidateUserFn<UserType> = (params: ValidateUserFnParams<UserType>) => void | UnauthenticatedError;
|
|
13
19
|
export declare const DIRECTIVE_SDL = "\n directive @auth on FIELD_DEFINITION\n";
|
|
14
20
|
export declare const SKIP_AUTH_DIRECTIVE_SDL = "\n directive @skipAuth on FIELD_DEFINITION\n";
|
|
15
21
|
export declare type GenericAuthPluginOptions<UserType extends {} = {}, ContextType extends DefaultContext = DefaultContext> = {
|
|
@@ -20,11 +26,6 @@ export declare type GenericAuthPluginOptions<UserType extends {} = {}, ContextTy
|
|
|
20
26
|
* Make sure to either return `null` or the user object.
|
|
21
27
|
*/
|
|
22
28
|
resolveUserFn: ResolveUserFn<UserType, ContextType>;
|
|
23
|
-
/**
|
|
24
|
-
* Here you can implement any custom to check if the user is valid and have access to the server.
|
|
25
|
-
* This method is being triggered in different flows, besed on the mode you chose to implement.
|
|
26
|
-
*/
|
|
27
|
-
validateUser?: ValidateUserFn<UserType, ContextType>;
|
|
28
29
|
/**
|
|
29
30
|
* Overrides the default field name for injecting the user into the execution `context`.
|
|
30
31
|
* @default currentUser
|
|
@@ -42,6 +43,12 @@ export declare type GenericAuthPluginOptions<UserType extends {} = {}, ContextTy
|
|
|
42
43
|
* @default skipAuth
|
|
43
44
|
*/
|
|
44
45
|
authDirectiveName?: 'skipAuth' | string;
|
|
46
|
+
/**
|
|
47
|
+
* Customize how the user is validated. E.g. apply authorization role based validation.
|
|
48
|
+
* The validation is applied during the extended validation phase.
|
|
49
|
+
* @default `defaultProtectAllValidateFn`
|
|
50
|
+
*/
|
|
51
|
+
validateUser?: ValidateUserFn<UserType>;
|
|
45
52
|
} | {
|
|
46
53
|
/**
|
|
47
54
|
* Just resolves the user and inject to authenticated user into the `context`.
|
|
@@ -53,14 +60,21 @@ export declare type GenericAuthPluginOptions<UserType extends {} = {}, ContextTy
|
|
|
53
60
|
* resolves the user and inject to authenticated user into the `context`.
|
|
54
61
|
* And checks for `@auth` directives usages to run validation automatically.
|
|
55
62
|
*/
|
|
56
|
-
mode: 'protect-
|
|
63
|
+
mode: 'protect-single';
|
|
57
64
|
/**
|
|
58
65
|
* Overrides the default directive name
|
|
59
66
|
* @default auth
|
|
60
67
|
*/
|
|
61
68
|
authDirectiveName?: 'auth' | string;
|
|
69
|
+
/**
|
|
70
|
+
* Customize how the user is validated. E.g. apply authorization role based validation.
|
|
71
|
+
* The validation is applied during the extended validation phase.
|
|
72
|
+
* @default `defaultProtectSingleValidateFn`
|
|
73
|
+
*/
|
|
74
|
+
validateUser?: ValidateUserFn<UserType>;
|
|
62
75
|
});
|
|
63
|
-
export declare function
|
|
76
|
+
export declare function defaultProtectAllValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | UnauthenticatedError;
|
|
77
|
+
export declare function defaultProtectSingleValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | UnauthenticatedError;
|
|
64
78
|
export declare const useGenericAuth: <UserType extends {} = {}, ContextType extends DefaultContext = DefaultContext>(options: GenericAuthPluginOptions<UserType, ContextType>) => Plugin<{
|
|
65
|
-
validateUser: ValidateUserFn<UserType
|
|
79
|
+
validateUser: ValidateUserFn<UserType>;
|
|
66
80
|
}>;
|
package/index.js
CHANGED
|
@@ -3,16 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
const graphql = require('graphql');
|
|
6
|
-
|
|
7
|
-
function getDirective(info, name) {
|
|
8
|
-
var _a;
|
|
9
|
-
const { parentType, fieldName, schema } = info;
|
|
10
|
-
const schemaType = schema.getType(parentType.name);
|
|
11
|
-
const field = schemaType.getFields()[fieldName];
|
|
12
|
-
const astNode = field.astNode;
|
|
13
|
-
const authDirective = (_a = astNode === null || astNode === void 0 ? void 0 : astNode.directives) === null || _a === void 0 ? void 0 : _a.find(d => d.name.value === name);
|
|
14
|
-
return authDirective || null;
|
|
15
|
-
}
|
|
6
|
+
const extendedValidation = require('@envelop/extended-validation');
|
|
16
7
|
|
|
17
8
|
class UnauthenticatedError extends graphql.GraphQLError {
|
|
18
9
|
}
|
|
@@ -22,62 +13,97 @@ const DIRECTIVE_SDL = /* GraphQL */ `
|
|
|
22
13
|
const SKIP_AUTH_DIRECTIVE_SDL = /* GraphQL */ `
|
|
23
14
|
directive @skipAuth on FIELD_DEFINITION
|
|
24
15
|
`;
|
|
25
|
-
function
|
|
26
|
-
if (!
|
|
27
|
-
|
|
16
|
+
function defaultProtectAllValidateFn(params) {
|
|
17
|
+
if (params.user == null && !params.fieldAuthDirectiveNode && !params.fieldAuthExtension) {
|
|
18
|
+
const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
|
|
19
|
+
return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [params.fieldNode]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function defaultProtectSingleValidateFn(params) {
|
|
23
|
+
if (params.user == null && (params.fieldAuthDirectiveNode || params.fieldAuthExtension)) {
|
|
24
|
+
const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
|
|
25
|
+
return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [params.fieldNode]);
|
|
28
26
|
}
|
|
29
27
|
}
|
|
30
28
|
const useGenericAuth = (options) => {
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
if (options.mode === 'protect-all') {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
async onResolverCalled({ args, root, context, info }) {
|
|
43
|
-
const authDirectiveNode = getDirective(info, options.authDirectiveName || 'skipAuth');
|
|
44
|
-
if (authDirectiveNode)
|
|
45
|
-
return;
|
|
46
|
-
await context.validateUser(context[fieldName], context);
|
|
47
|
-
},
|
|
29
|
+
var _a, _b;
|
|
30
|
+
const contextFieldName = options.contextFieldName || 'currentUser';
|
|
31
|
+
if (options.mode === 'protect-all' || options.mode === 'protect-single') {
|
|
32
|
+
const directiveName = (_a = options.authDirectiveName) !== null && _a !== void 0 ? _a : (options.mode === 'protect-all' ? 'skipAuth' : 'auth');
|
|
33
|
+
const validateUser = (_b = options.validateUser) !== null && _b !== void 0 ? _b : (options.mode === 'protect-all' ? defaultProtectAllValidateFn : defaultProtectSingleValidateFn);
|
|
34
|
+
const extractAuthMeta = (input) => {
|
|
35
|
+
var _a, _b, _c;
|
|
36
|
+
return {
|
|
37
|
+
fieldAuthExtension: (_a = input.extensions) === null || _a === void 0 ? void 0 : _a[directiveName],
|
|
38
|
+
fieldAuthDirectiveNode: (_c = (_b = input.astNode) === null || _b === void 0 ? void 0 : _b.directives) === null || _c === void 0 ? void 0 : _c.find(directive => directive.name.value === directiveName),
|
|
39
|
+
};
|
|
48
40
|
};
|
|
49
|
-
}
|
|
50
|
-
else if (options.mode === 'resolve-only') {
|
|
51
41
|
return {
|
|
42
|
+
onPluginInit({ addPlugin }) {
|
|
43
|
+
addPlugin(extendedValidation.useExtendedValidation({
|
|
44
|
+
rules: [
|
|
45
|
+
function AuthorizationExtendedValidationRule(context, args) {
|
|
46
|
+
const user = args.contextValue[contextFieldName];
|
|
47
|
+
const handleField = (fieldNode, objectType) => {
|
|
48
|
+
const field = objectType.getFields()[fieldNode.name.value];
|
|
49
|
+
if (field == null) {
|
|
50
|
+
// field is null/undefined if this is an introspection field
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const { fieldAuthExtension, fieldAuthDirectiveNode } = extractAuthMeta(field);
|
|
54
|
+
const error = validateUser({
|
|
55
|
+
user,
|
|
56
|
+
fieldNode,
|
|
57
|
+
objectType,
|
|
58
|
+
fieldAuthDirectiveNode,
|
|
59
|
+
fieldAuthExtension,
|
|
60
|
+
});
|
|
61
|
+
if (error) {
|
|
62
|
+
context.reportError(error);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
Field(node) {
|
|
67
|
+
const fieldType = graphql.getNamedType(context.getParentType());
|
|
68
|
+
if (graphql.isIntrospectionType(fieldType)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (graphql.isObjectType(fieldType)) {
|
|
72
|
+
handleField(node, fieldType);
|
|
73
|
+
}
|
|
74
|
+
else if (graphql.isUnionType(fieldType)) {
|
|
75
|
+
for (const objectType of fieldType.getTypes()) {
|
|
76
|
+
handleField(node, objectType);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (graphql.isInterfaceType(fieldType)) {
|
|
80
|
+
for (const objectType of args.schema.getImplementations(fieldType).objects) {
|
|
81
|
+
handleField(node, objectType);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
}));
|
|
90
|
+
},
|
|
52
91
|
async onContextBuilding({ context, extendContext }) {
|
|
53
92
|
const user = await options.resolveUserFn(context);
|
|
54
93
|
extendContext({
|
|
55
|
-
[
|
|
56
|
-
validateUser: () => validateUser(user, context),
|
|
94
|
+
[contextFieldName]: user,
|
|
57
95
|
});
|
|
58
96
|
},
|
|
59
97
|
};
|
|
60
98
|
}
|
|
61
|
-
else if (options.mode === '
|
|
99
|
+
else if (options.mode === 'resolve-only') {
|
|
62
100
|
return {
|
|
63
101
|
async onContextBuilding({ context, extendContext }) {
|
|
64
102
|
const user = await options.resolveUserFn(context);
|
|
65
103
|
extendContext({
|
|
66
|
-
[
|
|
67
|
-
validateUser,
|
|
104
|
+
[contextFieldName]: user,
|
|
68
105
|
});
|
|
69
106
|
},
|
|
70
|
-
async onResolverCalled({ args, root, context, info }) {
|
|
71
|
-
const authDirectiveNode = getDirective(info, options.authDirectiveName || 'auth');
|
|
72
|
-
if (authDirectiveNode) {
|
|
73
|
-
await context.validateUser(context[fieldName], context, {
|
|
74
|
-
info,
|
|
75
|
-
context: context,
|
|
76
|
-
args,
|
|
77
|
-
root,
|
|
78
|
-
}, authDirectiveNode);
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
107
|
};
|
|
82
108
|
}
|
|
83
109
|
return {};
|
|
@@ -86,6 +112,6 @@ const useGenericAuth = (options) => {
|
|
|
86
112
|
exports.DIRECTIVE_SDL = DIRECTIVE_SDL;
|
|
87
113
|
exports.SKIP_AUTH_DIRECTIVE_SDL = SKIP_AUTH_DIRECTIVE_SDL;
|
|
88
114
|
exports.UnauthenticatedError = UnauthenticatedError;
|
|
89
|
-
exports.
|
|
90
|
-
exports.
|
|
115
|
+
exports.defaultProtectAllValidateFn = defaultProtectAllValidateFn;
|
|
116
|
+
exports.defaultProtectSingleValidateFn = defaultProtectSingleValidateFn;
|
|
91
117
|
exports.useGenericAuth = useGenericAuth;
|
package/index.mjs
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import { GraphQLError } from 'graphql';
|
|
2
|
-
|
|
3
|
-
function getDirective(info, name) {
|
|
4
|
-
var _a;
|
|
5
|
-
const { parentType, fieldName, schema } = info;
|
|
6
|
-
const schemaType = schema.getType(parentType.name);
|
|
7
|
-
const field = schemaType.getFields()[fieldName];
|
|
8
|
-
const astNode = field.astNode;
|
|
9
|
-
const authDirective = (_a = astNode === null || astNode === void 0 ? void 0 : astNode.directives) === null || _a === void 0 ? void 0 : _a.find(d => d.name.value === name);
|
|
10
|
-
return authDirective || null;
|
|
11
|
-
}
|
|
1
|
+
import { GraphQLError, getNamedType, isIntrospectionType, isObjectType, isUnionType, isInterfaceType } from 'graphql';
|
|
2
|
+
import { useExtendedValidation } from '@envelop/extended-validation';
|
|
12
3
|
|
|
13
4
|
class UnauthenticatedError extends GraphQLError {
|
|
14
5
|
}
|
|
@@ -18,65 +9,100 @@ const DIRECTIVE_SDL = /* GraphQL */ `
|
|
|
18
9
|
const SKIP_AUTH_DIRECTIVE_SDL = /* GraphQL */ `
|
|
19
10
|
directive @skipAuth on FIELD_DEFINITION
|
|
20
11
|
`;
|
|
21
|
-
function
|
|
22
|
-
if (!
|
|
23
|
-
|
|
12
|
+
function defaultProtectAllValidateFn(params) {
|
|
13
|
+
if (params.user == null && !params.fieldAuthDirectiveNode && !params.fieldAuthExtension) {
|
|
14
|
+
const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
|
|
15
|
+
return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [params.fieldNode]);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function defaultProtectSingleValidateFn(params) {
|
|
19
|
+
if (params.user == null && (params.fieldAuthDirectiveNode || params.fieldAuthExtension)) {
|
|
20
|
+
const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
|
|
21
|
+
return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [params.fieldNode]);
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
const useGenericAuth = (options) => {
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
if (options.mode === 'protect-all') {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
async onResolverCalled({ args, root, context, info }) {
|
|
39
|
-
const authDirectiveNode = getDirective(info, options.authDirectiveName || 'skipAuth');
|
|
40
|
-
if (authDirectiveNode)
|
|
41
|
-
return;
|
|
42
|
-
await context.validateUser(context[fieldName], context);
|
|
43
|
-
},
|
|
25
|
+
var _a, _b;
|
|
26
|
+
const contextFieldName = options.contextFieldName || 'currentUser';
|
|
27
|
+
if (options.mode === 'protect-all' || options.mode === 'protect-single') {
|
|
28
|
+
const directiveName = (_a = options.authDirectiveName) !== null && _a !== void 0 ? _a : (options.mode === 'protect-all' ? 'skipAuth' : 'auth');
|
|
29
|
+
const validateUser = (_b = options.validateUser) !== null && _b !== void 0 ? _b : (options.mode === 'protect-all' ? defaultProtectAllValidateFn : defaultProtectSingleValidateFn);
|
|
30
|
+
const extractAuthMeta = (input) => {
|
|
31
|
+
var _a, _b, _c;
|
|
32
|
+
return {
|
|
33
|
+
fieldAuthExtension: (_a = input.extensions) === null || _a === void 0 ? void 0 : _a[directiveName],
|
|
34
|
+
fieldAuthDirectiveNode: (_c = (_b = input.astNode) === null || _b === void 0 ? void 0 : _b.directives) === null || _c === void 0 ? void 0 : _c.find(directive => directive.name.value === directiveName),
|
|
35
|
+
};
|
|
44
36
|
};
|
|
45
|
-
}
|
|
46
|
-
else if (options.mode === 'resolve-only') {
|
|
47
37
|
return {
|
|
38
|
+
onPluginInit({ addPlugin }) {
|
|
39
|
+
addPlugin(useExtendedValidation({
|
|
40
|
+
rules: [
|
|
41
|
+
function AuthorizationExtendedValidationRule(context, args) {
|
|
42
|
+
const user = args.contextValue[contextFieldName];
|
|
43
|
+
const handleField = (fieldNode, objectType) => {
|
|
44
|
+
const field = objectType.getFields()[fieldNode.name.value];
|
|
45
|
+
if (field == null) {
|
|
46
|
+
// field is null/undefined if this is an introspection field
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const { fieldAuthExtension, fieldAuthDirectiveNode } = extractAuthMeta(field);
|
|
50
|
+
const error = validateUser({
|
|
51
|
+
user,
|
|
52
|
+
fieldNode,
|
|
53
|
+
objectType,
|
|
54
|
+
fieldAuthDirectiveNode,
|
|
55
|
+
fieldAuthExtension,
|
|
56
|
+
});
|
|
57
|
+
if (error) {
|
|
58
|
+
context.reportError(error);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
Field(node) {
|
|
63
|
+
const fieldType = getNamedType(context.getParentType());
|
|
64
|
+
if (isIntrospectionType(fieldType)) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (isObjectType(fieldType)) {
|
|
68
|
+
handleField(node, fieldType);
|
|
69
|
+
}
|
|
70
|
+
else if (isUnionType(fieldType)) {
|
|
71
|
+
for (const objectType of fieldType.getTypes()) {
|
|
72
|
+
handleField(node, objectType);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else if (isInterfaceType(fieldType)) {
|
|
76
|
+
for (const objectType of args.schema.getImplementations(fieldType).objects) {
|
|
77
|
+
handleField(node, objectType);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
}));
|
|
86
|
+
},
|
|
48
87
|
async onContextBuilding({ context, extendContext }) {
|
|
49
88
|
const user = await options.resolveUserFn(context);
|
|
50
89
|
extendContext({
|
|
51
|
-
[
|
|
52
|
-
validateUser: () => validateUser(user, context),
|
|
90
|
+
[contextFieldName]: user,
|
|
53
91
|
});
|
|
54
92
|
},
|
|
55
93
|
};
|
|
56
94
|
}
|
|
57
|
-
else if (options.mode === '
|
|
95
|
+
else if (options.mode === 'resolve-only') {
|
|
58
96
|
return {
|
|
59
97
|
async onContextBuilding({ context, extendContext }) {
|
|
60
98
|
const user = await options.resolveUserFn(context);
|
|
61
99
|
extendContext({
|
|
62
|
-
[
|
|
63
|
-
validateUser,
|
|
100
|
+
[contextFieldName]: user,
|
|
64
101
|
});
|
|
65
102
|
},
|
|
66
|
-
async onResolverCalled({ args, root, context, info }) {
|
|
67
|
-
const authDirectiveNode = getDirective(info, options.authDirectiveName || 'auth');
|
|
68
|
-
if (authDirectiveNode) {
|
|
69
|
-
await context.validateUser(context[fieldName], context, {
|
|
70
|
-
info,
|
|
71
|
-
context: context,
|
|
72
|
-
args,
|
|
73
|
-
root,
|
|
74
|
-
}, authDirectiveNode);
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
103
|
};
|
|
78
104
|
}
|
|
79
105
|
return {};
|
|
80
106
|
};
|
|
81
107
|
|
|
82
|
-
export { DIRECTIVE_SDL, SKIP_AUTH_DIRECTIVE_SDL, UnauthenticatedError,
|
|
108
|
+
export { DIRECTIVE_SDL, SKIP_AUTH_DIRECTIVE_SDL, UnauthenticatedError, defaultProtectAllValidateFn, defaultProtectSingleValidateFn, useGenericAuth };
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envelop/generic-auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-alpha-bed7c7d.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@envelop/core": "^2.0.0",
|
|
7
7
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
8
8
|
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@envelop/extended-validation": "^1.3.1"
|
|
11
|
+
},
|
|
9
12
|
"repository": {
|
|
10
13
|
"type": "git",
|
|
11
14
|
"url": "https://github.com/dotansimha/envelop.git",
|
package/utils.d.ts
DELETED