This repository has been archived by the owner on Feb 15, 2022. It is now read-only.
forked from esseswann/graphql-binary
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
96 lines (76 loc) · 2.68 KB
/
index.js
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
88
89
90
91
92
93
94
95
96
const forEach = require('lodash/forEach');
const isEmpty = require('lodash/isEmpty');
const { decodeValue, encodeValue } = require('src/valueHandlers');
const ast = require('src/ast');
const END = 255;
module.exports.encode = (definition, dictionary) => {
const result = [];
encodeFields(definition.definitions[0], dictionary, 'Query', result);
return new Uint8Array(result)
};
// Recursive
function decode(
bytes,
dictionary,
parentKey = 'Query',
accumulator = [],
index = 0
) {
if (bytes[index] === END) // FIXME doing this twice is wrong
return [accumulator, index + 1];
const [field, offset] = decodeField(bytes, dictionary, parentKey, index);
accumulator.push(field);
return decode(bytes, dictionary, parentKey, accumulator, offset);
};
module.exports.decode = decode;
function encodeFields(definition, dictionary, parentKey, result) {
forEach(definition.selectionSet.selections, field =>
encodeField(field, dictionary, parentKey, result));
result.push(END)
}
function encodeField(field, dictionary, parentKey, result) {
const definition = dictionary[parentKey].encode[field.name.value];
if (!definition)
throw new Error(`Field ${field.name.value} is not present in the schema`);
else
result.push(definition.byte);
if (field.arguments.length > 0) {
if (isEmpty(definition.arguments))
throw new Error(`Field ${field.name.value} should not have arguments`);
forEach(field.arguments, argument => {
const argumentDefinition = definition.arguments[argument.name.value];
if (argumentDefinition === undefined)
throw new Error(`Argument ${argument.name.value} for field ${field.name.value} is not present in the schema`);
result.push(argumentDefinition.byte);
encodeValue(argumentDefinition.type, argument.value.value, result)
})
}
if (field.selectionSet)
encodeFields(field, dictionary, definition.type, result)
}
const decodeField = (
bytes,
dictionary,
parentKey,
index = 0,
) => {
const definition = dictionary[parentKey].decode[bytes[index]];
if (definition === undefined)
throw new Error(`Code ${bytes[0]} not present in schema`);
const result = ast[definition.kind](definition.name);
index += 1;
function subFields() { // FIXME this is a bad implementation
const next = dictionary[parentKey].decode[bytes[index]];
if (next && next.isArg) {
const [value, offset, kind] = decodeValue(bytes, index + 1, next.type);
result.arguments.push(ast.ARGUMENT(next.name, kind, value));
index = offset - 1;
return subFields()
} else if (definition.kind === 'OBJECT') {
const [fields, offset] = decode(bytes, dictionary, definition.type, result.selectionSet.selections, index);
index = offset
}
}
subFields();
return [result, index];
};