Skip to content

Commit 719df33

Browse files
committed
wip(ApiParser): GraphQL type constructor from elasticsearch API code
1 parent 2258df6 commit 719df33

File tree

10 files changed

+581
-26
lines changed

10 files changed

+581
-26
lines changed

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"exports": "always-multiline",
1919
"functions": "ignore",
2020
}],
21-
"no-plusplus": 0
21+
"no-plusplus": 0,
22+
"import/no-extraneous-dependencies": 0
2223
},
2324
"env": {
2425
"jasmine": true,

.flowconfig

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
[ignore]
2-
.*/node_modules/.*
2+
.*/node_modules/ajv.*
3+
.*/node_modules/acorn.*
4+
.*/node_modules/async.*
5+
.*/node_modules/babel.*
6+
.*/node_modules/bluebird.*
7+
.*/node_modules/caniuse-db.*
8+
.*/node_modules/config-chain.*
9+
.*/node_modules/conventional-changelog.*
10+
.*/node_modules/core-js.*
11+
.*/node_modules/cssstyle.*
12+
.*/node_modules/diff.*
13+
.*/node_modules/es5-ext.*
14+
.*/node_modules/escope.*
15+
.*/node_modules/escodegen.*
16+
.*/node_modules/eslint.*
17+
.*/node_modules/github.*
18+
.*/node_modules/fsevents.*
19+
.*/node_modules/jsdoctypeparser.*
20+
.*/node_modules/jsdom.*
21+
.*/node_modules/iconv.*
22+
.*/node_modules/istanbul.*
23+
.*/node_modules/handlebars.*
24+
.*/node_modules/markdown.*
25+
.*/node_modules/node-notifier.*
26+
.*/node_modules/npmconf.*
27+
.*/node_modules/prettier.*
28+
.*/node_modules/source-map.*
29+
.*/node_modules/travis.*
30+
.*/node_modules/uglify.*
31+
.*/node_modules/yargs.*
332

433
[include]
534

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ node_modules
4444

4545
coverage
4646
.nyc_output
47+
flow-typed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"babel-preset-env": "^1.1.8",
3737
"cz-conventional-changelog": "^2.0.0",
3838
"dox": "^0.9.0",
39+
"elasticsearch": "^12.1.3",
3940
"eslint": "^3.14.1",
4041
"eslint-config-airbnb-base": "^11.0.1",
4142
"eslint-config-prettier": "^1.0.2",

scripts/apiParser/search.txt renamed to scripts/apiParser/__mocks__/apiPartial.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint-disable */
2+
13
/**
24
* Perform a [search](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-search.html) request
35
*
@@ -417,3 +419,75 @@ api.updateByQuery = ca({
417419
],
418420
method: 'POST'
419421
});
422+
423+
/**
424+
* Perform a [cat.allocation](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/cat-allocation.html) request
425+
*
426+
* @param {Object} params - An object with parameters used to carry out this action
427+
* @param {<<api-param-type-string,`String`>>} params.format - a short version of the Accept header, e.g. json, yaml
428+
* @param {<<api-param-type-string,`String`>>} params.bytes - The unit in which to display byte values
429+
* @param {<<api-param-type-boolean,`Boolean`>>} params.local - Return local information, do not retrieve the state from master node (default: false)
430+
* @param {<<api-param-type-duration-string,`DurationString`>>} params.masterTimeout - Explicit operation timeout for connection to master node
431+
* @param {<<api-param-type-string,`String`>>, <<api-param-type-string-array,`String[]`>>, <<api-param-type-boolean,`Boolean`>>} params.h - Comma-separated list of column names to display
432+
* @param {<<api-param-type-boolean,`Boolean`>>} params.help - Return help information
433+
* @param {<<api-param-type-string,`String`>>, <<api-param-type-string-array,`String[]`>>, <<api-param-type-boolean,`Boolean`>>} params.s - Comma-separated list of column names or column aliases to sort by
434+
* @param {<<api-param-type-boolean,`Boolean`>>} params.v - Verbose mode. Display column headers
435+
* @param {<<api-param-type-string,`String`>>, <<api-param-type-string-array,`String[]`>>, <<api-param-type-boolean,`Boolean`>>} params.nodeId - A comma-separated list of node IDs or names to limit the returned information
436+
*/
437+
api.cat.prototype.allocation = ca({
438+
params: {
439+
format: {
440+
type: 'string'
441+
},
442+
bytes: {
443+
type: 'enum',
444+
options: [
445+
'b',
446+
'k',
447+
'kb',
448+
'm',
449+
'mb',
450+
'g',
451+
'gb',
452+
't',
453+
'tb',
454+
'p',
455+
'pb'
456+
]
457+
},
458+
local: {
459+
type: 'boolean'
460+
},
461+
masterTimeout: {
462+
type: 'time',
463+
name: 'master_timeout'
464+
},
465+
h: {
466+
type: 'list'
467+
},
468+
help: {
469+
type: 'boolean',
470+
'default': false
471+
},
472+
s: {
473+
type: 'list'
474+
},
475+
v: {
476+
type: 'boolean',
477+
'default': false
478+
}
479+
},
480+
urls: [
481+
{
482+
fmt: '/_cat/allocation/<%=nodeId%>',
483+
req: {
484+
nodeId: {
485+
type: 'list'
486+
}
487+
}
488+
},
489+
{
490+
fmt: '/_cat/allocation'
491+
}
492+
]
493+
});

scripts/apiParser/createTypes.js

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/* @flow */
2+
/* eslint-disable no-param-reassign */
3+
4+
import dox from 'dox';
5+
import fs from 'fs';
6+
import {
7+
GraphQLString,
8+
GraphQLFloat,
9+
GraphQLBoolean,
10+
GraphQLInputObjectType,
11+
GraphQLEnumType,
12+
} from 'graphql';
13+
import { GraphQLJSON, upperFirst } from 'graphql-compose';
14+
15+
import type { GraphQLArgumentConfig } from 'graphql/type/definition';
16+
17+
export type ElasticParamConfigT = {
18+
type: string,
19+
name?: string,
20+
options?: mixed,
21+
default?: mixed,
22+
};
23+
24+
export type ElasticCaSettingsT = {
25+
params: {
26+
[name: string]: ElasticParamConfigT,
27+
},
28+
urls: {
29+
fmt: string,
30+
req: {
31+
[name: string]: ElasticParamConfigT,
32+
},
33+
}[],
34+
};
35+
36+
export const apiSources = {
37+
elastic5: '../../node_modules/elasticsearch/src/lib/apis/5_x.js',
38+
};
39+
40+
export function loadApiFile(absolutePath: string): string {
41+
const str = fs.readFileSync(absolutePath, 'utf8');
42+
43+
// remove invalid markup
44+
// {<<api-param-type-boolean,`Boolean`>>} converted to {Boolean}
45+
const strCleaned = str.replace(/{<<.+`(.*)`.+}/gi, '{$1}');
46+
47+
return strCleaned;
48+
}
49+
50+
export function parseSource(source: string) {
51+
const result = {};
52+
53+
if (!source || typeof source !== 'string') {
54+
throw Error('Empty source. It should be non-empty string.');
55+
}
56+
57+
const parsed = dox.parseComments(source, { raw: true });
58+
if (!parsed || !Array.isArray(parsed)) {
59+
throw Error('Incorrect responce from dox.parseComments');
60+
}
61+
62+
parsed.forEach(item => {
63+
if (!item.ctx || !item.ctx.string) {
64+
return;
65+
}
66+
67+
let description;
68+
if (item.description && item.description.full) {
69+
description = cleanupDescription(item.description.full);
70+
}
71+
72+
const params = {};
73+
if (Array.isArray(item.tags)) {
74+
item.tags.forEach(tag => {
75+
if (!tag || tag.type !== 'param') return;
76+
if (tag.name === 'params') return;
77+
78+
const name = cleanupParamName(tag.name);
79+
if (!name) return;
80+
81+
params[name] = {
82+
name,
83+
description: cleanupDescription(tag.description),
84+
};
85+
});
86+
}
87+
88+
// parseParamsFromCode(item.code);
89+
90+
result[item.ctx.string] = {
91+
description,
92+
params,
93+
};
94+
});
95+
96+
// console.dir(parsed, {depth: 4, colors: 1})
97+
98+
return result;
99+
}
100+
101+
export function cleanupDescription(str: ?string): ?string {
102+
if (typeof str === 'string') {
103+
if (str.startsWith('- ')) {
104+
str = str.substr(2);
105+
}
106+
str = str.trim();
107+
108+
return str;
109+
}
110+
return undefined;
111+
}
112+
113+
export function cleanupParamName(str: ?string): ?string {
114+
if (typeof str === 'string') {
115+
if (str.startsWith('param.')) {
116+
str = str.substr(6);
117+
}
118+
str = str.trim();
119+
120+
return str;
121+
}
122+
return undefined;
123+
}
124+
125+
export function codeToSettings(code: string): mixed {
126+
// find code in ca({});
127+
const reg = /ca\((\{(.|\n)+\})\);/g;
128+
const matches = reg.exec(code);
129+
if (matches[1]) {
130+
return eval('(' + matches[1] + ')'); // eslint-disable-line no-eval
131+
}
132+
return undefined;
133+
}
134+
135+
export function settingsToParams(settings: ElasticCaSettingsT): mixed {
136+
const result = {};
137+
const { params, urls } = settings;
138+
if (params) {
139+
Object.keys(params).forEach(k => {
140+
const fieldConfig = paramToGraphQLArgConfig(params[k], k);
141+
if (fieldConfig) {
142+
result[k] = fieldConfig;
143+
}
144+
});
145+
}
146+
147+
if (Array.isArray(urls)) {
148+
urls.forEach(url => {
149+
if (url.req) {
150+
Object.keys(url.req).forEach(k => {
151+
const fieldConfig = paramToGraphQLArgConfig(url.req[k], k);
152+
if (fieldConfig) {
153+
result[k] = fieldConfig;
154+
}
155+
});
156+
}
157+
});
158+
}
159+
160+
return result;
161+
}
162+
163+
export function paramToGraphQLArgConfig(
164+
paramCfg: ElasticParamConfigT,
165+
fieldName: string
166+
): GraphQLArgumentConfig {
167+
const result: GraphQLArgumentConfig = {
168+
type: paramTypeToGraphQL(paramCfg, fieldName),
169+
};
170+
if (paramCfg.default) {
171+
result.defaultValue = paramCfg.default;
172+
}
173+
174+
return result;
175+
}
176+
177+
export function paramTypeToGraphQL(
178+
paramCfg: ElasticParamConfigT,
179+
fieldName: string
180+
): GraphQLInputObjectType {
181+
switch (paramCfg.type) {
182+
case 'string':
183+
return GraphQLString;
184+
case 'boolean':
185+
return GraphQLBoolean;
186+
case 'number':
187+
return GraphQLFloat;
188+
case 'time':
189+
return GraphQLString;
190+
case 'list':
191+
return GraphQLJSON;
192+
case 'enum':
193+
if (Array.isArray(paramCfg.options)) {
194+
const values = paramCfg.options.reduce(
195+
(result, val) => {
196+
// $FlowFixMe
197+
result[val] = { value: val }; // eslint-disable-line no-param-reassign
198+
return result;
199+
},
200+
{}
201+
);
202+
203+
return new GraphQLEnumType({
204+
name: `Elastic${upperFirst(fieldName)}`,
205+
values,
206+
});
207+
}
208+
return GraphQLString;
209+
default:
210+
console.log(`New type '${paramCfg.type}' in elastic params setting.`); // eslint-disable-line
211+
return GraphQLJSON;
212+
}
213+
}

0 commit comments

Comments
 (0)