directus

Форк
0
/
sanitize-gql-schema.ts 
107 строк · 2.8 Кб
1
import type { Relation, SchemaOverview } from '@directus/types';
2
import { useLogger } from '../../../logger.js';
3

4
/**
5
 * Regex was taken from the spec
6
 * https://spec.graphql.org/June2018/#sec-Names
7
 */
8
const GRAPHQL_NAME_REGEX = /^[_A-Za-z][_0-9A-Za-z]*$/;
9

10
/**
11
 * Manually curated list of GraphQL reserved names to cover the most likely naming footguns.
12
 * This list is not exhaustive and does not cover generated type names.
13
 */
14
const GRAPHQL_RESERVED_NAMES = [
15
	'Subscription',
16
	'Query',
17
	'Mutation',
18
	'Int',
19
	'Float',
20
	'String',
21
	'Boolean',
22
	'DateTime',
23
	'ID',
24
	'uid',
25
	'Point',
26
	'PointList',
27
	'Polygon',
28
	'MultiPolygon',
29
	'JSON',
30
	'Hash',
31
	'Date',
32
	'Void',
33
];
34

35
/**
36
 * Filters out invalid collections to prevent graphql from errorring on schema generation
37
 *
38
 * @param schema
39
 * @returns sanitized schema
40
 */
41
export function sanitizeGraphqlSchema(schema: SchemaOverview) {
42
	const logger = useLogger();
43

44
	const collections = Object.entries(schema.collections).filter(([collectionName, _data]) => {
45
		// double underscore __ is reserved for GraphQL introspection
46
		if (collectionName.startsWith('__') || !collectionName.match(GRAPHQL_NAME_REGEX)) {
47
			logger.warn(
48
				`GraphQL skipping collection "${collectionName}" because it is not a valid name matching /^[_A-Za-z][_0-9A-Za-z]*$/ or starts with __`,
49
			);
50

51
			return false;
52
		}
53

54
		if (GRAPHQL_RESERVED_NAMES.includes(collectionName)) {
55
			logger.warn(`GraphQL skipping collection "${collectionName}" because it is a reserved keyword`);
56

57
			return false;
58
		}
59

60
		return true;
61
	});
62

63
	schema.collections = Object.fromEntries(collections);
64

65
	const collectionExists = (collection: string) => Boolean(schema.collections[collection]);
66

67
	const skipRelation = (relation: Relation) => {
68
		const relationName = relation.schema?.constraint_name ?? `${relation.collection}.${relation.field}`;
69

70
		logger.warn(
71
			`GraphQL skipping relation "${relationName}" because it links to a non-existent or invalid collection.`,
72
		);
73

74
		return false;
75
	};
76

77
	schema.relations = schema.relations.filter((relation) => {
78
		if (relation.collection && !collectionExists(relation.collection)) {
79
			return skipRelation(relation);
80
		}
81

82
		if (relation.related_collection && !collectionExists(relation.related_collection)) {
83
			return skipRelation(relation);
84
		}
85

86
		if (relation.meta) {
87
			if (relation.meta.many_collection && !collectionExists(relation.meta.many_collection)) {
88
				return skipRelation(relation);
89
			}
90

91
			if (relation.meta.one_collection && !collectionExists(relation.meta.one_collection)) {
92
				return skipRelation(relation);
93
			}
94

95
			if (
96
				relation.meta.one_allowed_collections &&
97
				relation.meta.one_allowed_collections.some((allowed_collection) => !collectionExists(allowed_collection))
98
			) {
99
				return skipRelation(relation);
100
			}
101
		}
102

103
		return true;
104
	});
105

106
	return schema;
107
}
108

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.