-
Notifications
You must be signed in to change notification settings - Fork 33
/
iterate.ts
87 lines (74 loc) · 2.84 KB
/
iterate.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { getNamedType, GraphQLSchema, isObjectType, isInputObjectType, GraphQLField, GraphQLInputType } from 'graphql';
export type IndexedObject<V> = { [key: string]: V } | ReadonlyArray<V>;
export type IFieldIteratorFn = (fieldDef: GraphQLField<any, any>, typeName: string, fieldName: string) => void;
export type IDefaultValueIteratorFn = (type: GraphQLInputType, value: any) => void;
export function forEachField(schema: GraphQLSchema, fn: IFieldIteratorFn): void {
const typeMap = schema.getTypeMap();
Object.keys(typeMap).forEach((typeName) => {
const type = typeMap[typeName];
// TODO: maybe have an option to include these?
if (!getNamedType(type).name.startsWith('__') && isObjectType(type)) {
const fields = type.getFields();
Object.keys(fields).forEach((fieldName) => {
const field = fields[fieldName];
fn(field, typeName, fieldName);
});
}
});
}
export function forEachDefaultValue(schema: GraphQLSchema, fn: IDefaultValueIteratorFn): void {
const typeMap = schema.getTypeMap();
Object.keys(typeMap).forEach((typeName) => {
const type = typeMap[typeName];
if (!getNamedType(type).name.startsWith('__')) {
if (isObjectType(type)) {
const fields = type.getFields();
Object.keys(fields).forEach((fieldName) => {
const field = fields[fieldName];
field.args.forEach((arg) => {
arg.defaultValue = fn(arg.type, arg.defaultValue);
});
});
} else if (isInputObjectType(type)) {
const fields = type.getFields();
Object.keys(fields).forEach((fieldName) => {
const field = fields[fieldName];
field.defaultValue = fn(field.type, field.defaultValue);
});
}
}
});
}
// A more powerful version of each that has the ability to replace or remove
// array or object keys.
export function updateEachKey<V>(
arrayOrObject: IndexedObject<V>,
// The callback can return nothing to leave the key untouched, null to remove
// the key from the array or object, or a non-null V to replace the value.
updater: (value: V, key: string) => void | null | V
) {
let deletedCount = 0;
Object.keys(arrayOrObject).forEach((key) => {
const result = updater(arrayOrObject[key], key);
if (typeof result === 'undefined') {
return;
}
if (result === null) {
delete arrayOrObject[key];
deletedCount++;
return;
}
arrayOrObject[key] = result;
});
if (deletedCount > 0 && Array.isArray(arrayOrObject)) {
// Remove any holes from the array due to deleted elements.
arrayOrObject.splice(0).forEach((elem) => {
arrayOrObject.push(elem);
});
}
}
export function each<V>(arrayOrObject: IndexedObject<V>, callback: (value: V, key: string) => void) {
Object.keys(arrayOrObject).forEach((key) => {
callback(arrayOrObject[key], key);
});
}