apollo-conn-gen 0.0.2
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/dist/cli/json.d.ts +1 -0
- package/dist/cli/json.js +70 -0
- package/dist/cli/json.js.map +1 -0
- package/dist/cli/oas-helpers/index.d.ts +4 -0
- package/dist/cli/oas-helpers/index.js +54 -0
- package/dist/cli/oas-helpers/index.js.map +1 -0
- package/dist/cli/oas.d.ts +1 -0
- package/dist/cli/oas.js +49 -0
- package/dist/cli/oas.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/json/index.d.ts +4 -0
- package/dist/json/index.js +5 -0
- package/dist/json/index.js.map +1 -0
- package/dist/json/io/index.d.ts +1 -0
- package/dist/json/io/index.js +2 -0
- package/dist/json/io/index.js.map +1 -0
- package/dist/json/io/writer.d.ts +15 -0
- package/dist/json/io/writer.js +45 -0
- package/dist/json/io/writer.js.map +1 -0
- package/dist/json/walker/index.d.ts +2 -0
- package/dist/json/walker/index.js +3 -0
- package/dist/json/walker/index.js.map +1 -0
- package/dist/json/walker/jsonContext.d.ts +12 -0
- package/dist/json/walker/jsonContext.js +42 -0
- package/dist/json/walker/jsonContext.js.map +1 -0
- package/dist/json/walker/jsonGen.d.ts +19 -0
- package/dist/json/walker/jsonGen.js +209 -0
- package/dist/json/walker/jsonGen.js.map +1 -0
- package/dist/json/walker/log/trace.d.ts +3 -0
- package/dist/json/walker/log/trace.js +11 -0
- package/dist/json/walker/log/trace.js.map +1 -0
- package/dist/json/walker/naming.d.ts +8 -0
- package/dist/json/walker/naming.js +66 -0
- package/dist/json/walker/naming.js.map +1 -0
- package/dist/json/walker/types/index.d.ts +4 -0
- package/dist/json/walker/types/index.js +5 -0
- package/dist/json/walker/types/index.js.map +1 -0
- package/dist/json/walker/types/jsonArray.d.ts +13 -0
- package/dist/json/walker/types/jsonArray.js +70 -0
- package/dist/json/walker/types/jsonArray.js.map +1 -0
- package/dist/json/walker/types/jsonObj.d.ts +17 -0
- package/dist/json/walker/types/jsonObj.js +76 -0
- package/dist/json/walker/types/jsonObj.js.map +1 -0
- package/dist/json/walker/types/jsonScalar.d.ts +12 -0
- package/dist/json/walker/types/jsonScalar.js +39 -0
- package/dist/json/walker/types/jsonScalar.js.map +1 -0
- package/dist/json/walker/types/jsonType.d.ts +16 -0
- package/dist/json/walker/types/jsonType.js +30 -0
- package/dist/json/walker/types/jsonType.js.map +1 -0
- package/dist/oas/index.d.ts +14 -0
- package/dist/oas/index.js +15 -0
- package/dist/oas/index.js.map +1 -0
- package/dist/oas/io/writer.d.ts +25 -0
- package/dist/oas/io/writer.js +313 -0
- package/dist/oas/io/writer.js.map +1 -0
- package/dist/oas/log/trace.d.ts +3 -0
- package/dist/oas/log/trace.js +7 -0
- package/dist/oas/log/trace.js.map +1 -0
- package/dist/oas/nodes/arr.d.ts +15 -0
- package/dist/oas/nodes/arr.js +47 -0
- package/dist/oas/nodes/arr.js.map +1 -0
- package/dist/oas/nodes/circularRef.d.ts +13 -0
- package/dist/oas/nodes/circularRef.js +39 -0
- package/dist/oas/nodes/circularRef.js.map +1 -0
- package/dist/oas/nodes/comp.d.ts +18 -0
- package/dist/oas/nodes/comp.js +156 -0
- package/dist/oas/nodes/comp.js.map +1 -0
- package/dist/oas/nodes/en.d.ts +14 -0
- package/dist/oas/nodes/en.js +57 -0
- package/dist/oas/nodes/en.js.map +1 -0
- package/dist/oas/nodes/factory.d.ts +17 -0
- package/dist/oas/nodes/factory.js +174 -0
- package/dist/oas/nodes/factory.js.map +1 -0
- package/dist/oas/nodes/get.d.ts +24 -0
- package/dist/oas/nodes/get.js +167 -0
- package/dist/oas/nodes/get.js.map +1 -0
- package/dist/oas/nodes/obj.d.ts +15 -0
- package/dist/oas/nodes/obj.js +177 -0
- package/dist/oas/nodes/obj.js.map +1 -0
- package/dist/oas/nodes/param/param.d.ts +17 -0
- package/dist/oas/nodes/param/param.js +64 -0
- package/dist/oas/nodes/param/param.js.map +1 -0
- package/dist/oas/nodes/props/prop.d.ts +12 -0
- package/dist/oas/nodes/props/prop.js +33 -0
- package/dist/oas/nodes/props/prop.js.map +1 -0
- package/dist/oas/nodes/props/propArray.d.ts +15 -0
- package/dist/oas/nodes/props/propArray.js +75 -0
- package/dist/oas/nodes/props/propArray.js.map +1 -0
- package/dist/oas/nodes/props/propObj.d.ts +16 -0
- package/dist/oas/nodes/props/propObj.js +70 -0
- package/dist/oas/nodes/props/propObj.js.map +1 -0
- package/dist/oas/nodes/props/propRef.d.ts +19 -0
- package/dist/oas/nodes/props/propRef.js +108 -0
- package/dist/oas/nodes/props/propRef.js.map +1 -0
- package/dist/oas/nodes/props/propScalar.d.ts +16 -0
- package/dist/oas/nodes/props/propScalar.js +47 -0
- package/dist/oas/nodes/props/propScalar.js.map +1 -0
- package/dist/oas/nodes/props/referenceObject.d.ts +3 -0
- package/dist/oas/nodes/props/referenceObject.js +2 -0
- package/dist/oas/nodes/props/referenceObject.js.map +1 -0
- package/dist/oas/nodes/ref.d.ts +17 -0
- package/dist/oas/nodes/ref.js +70 -0
- package/dist/oas/nodes/ref.js.map +1 -0
- package/dist/oas/nodes/response.d.ts +14 -0
- package/dist/oas/nodes/response.js +48 -0
- package/dist/oas/nodes/response.js.map +1 -0
- package/dist/oas/nodes/scalar.d.ts +12 -0
- package/dist/oas/nodes/scalar.js +26 -0
- package/dist/oas/nodes/scalar.js.map +1 -0
- package/dist/oas/nodes/type.d.ts +43 -0
- package/dist/oas/nodes/type.js +107 -0
- package/dist/oas/nodes/type.js.map +1 -0
- package/dist/oas/nodes/union.d.ts +16 -0
- package/dist/oas/nodes/union.js +133 -0
- package/dist/oas/nodes/union.js.map +1 -0
- package/dist/oas/oasContext.d.ts +23 -0
- package/dist/oas/oasContext.js +73 -0
- package/dist/oas/oasContext.js.map +1 -0
- package/dist/oas/oasGen.d.ts +28 -0
- package/dist/oas/oasGen.js +166 -0
- package/dist/oas/oasGen.js.map +1 -0
- package/dist/oas/prompts/base/theme.d.ts +1 -0
- package/dist/oas/prompts/base/theme.js +50 -0
- package/dist/oas/prompts/base/theme.js.map +1 -0
- package/dist/oas/prompts/base/utils.d.ts +3 -0
- package/dist/oas/prompts/base/utils.js +8 -0
- package/dist/oas/prompts/base/utils.js.map +1 -0
- package/dist/oas/prompts/prompt.d.ts +19 -0
- package/dist/oas/prompts/prompt.js +176 -0
- package/dist/oas/prompts/prompt.js.map +1 -0
- package/dist/oas/prompts/theme.d.ts +126 -0
- package/dist/oas/prompts/theme.js +2 -0
- package/dist/oas/prompts/theme.js.map +1 -0
- package/dist/oas/utils/gql.d.ts +5 -0
- package/dist/oas/utils/gql.js +35 -0
- package/dist/oas/utils/gql.js.map +1 -0
- package/dist/oas/utils/naming.d.ts +16 -0
- package/dist/oas/utils/naming.js +143 -0
- package/dist/oas/utils/naming.js.map +1 -0
- package/dist/oas/utils/typeUtils.d.ts +6 -0
- package/dist/oas/utils/typeUtils.js +25 -0
- package/dist/oas/utils/typeUtils.js.map +1 -0
- package/package.json +77 -0
- package/readme.md +383 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/cli/json.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { JsonGen } from '../json/index.js';
|
|
3
|
+
// // mute console.log
|
|
4
|
+
// console.log = () => {};
|
|
5
|
+
// function walkSourceFile(source: string): void {
|
|
6
|
+
// const fileContent = fs.readFileSync(source, 'utf-8');
|
|
7
|
+
// const walker = JsonGen.fromReader(fileContent);
|
|
8
|
+
// console.info(walker.generateSchema());
|
|
9
|
+
// }
|
|
10
|
+
// async function main() {
|
|
11
|
+
// walkSourceFile(
|
|
12
|
+
// '/Users/fernando/Development/Apollo/connectors/projects/JsonToConnector/src/test/resources/preferences/user/50.json',
|
|
13
|
+
// );
|
|
14
|
+
// }
|
|
15
|
+
// main().then(() => console.log('done'));
|
|
16
|
+
import { Command } from 'commander';
|
|
17
|
+
// const originalConsole = {
|
|
18
|
+
// log: console.log,
|
|
19
|
+
// };
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- for options
|
|
21
|
+
async function main(fileOrFolder, opts) {
|
|
22
|
+
console.log = () => { };
|
|
23
|
+
if (!fs.existsSync(fileOrFolder)) {
|
|
24
|
+
console.error(`File or folder not found: ${fileOrFolder}`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// generator
|
|
28
|
+
let gen;
|
|
29
|
+
// if it is a file
|
|
30
|
+
if (fs.lstatSync(fileOrFolder).isFile()) {
|
|
31
|
+
// read contents
|
|
32
|
+
const contents = fs.readFileSync(fileOrFolder, 'utf-8');
|
|
33
|
+
gen = JsonGen.fromReader(contents);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// iterate through the files found in the target folder and load all the contents
|
|
37
|
+
gen = JsonGen.new();
|
|
38
|
+
fs.readdirSync(fileOrFolder).forEach((file) => {
|
|
39
|
+
const contents = fs.readFileSync(fileOrFolder + '/' + file, 'utf-8');
|
|
40
|
+
gen.walkJson(contents);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
let generated;
|
|
44
|
+
if (opts.schemaTypes) {
|
|
45
|
+
generated = gen.writeTypes();
|
|
46
|
+
}
|
|
47
|
+
else if (opts.selectionSet) {
|
|
48
|
+
generated = gen.writeSelection();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
generated = gen.generateSchema();
|
|
52
|
+
}
|
|
53
|
+
if (opts.outputFile !== 'stdout') {
|
|
54
|
+
fs.writeFileSync(opts.outputFile, generated);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.info(generated);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const program = new Command();
|
|
61
|
+
program
|
|
62
|
+
.version('0.0.1')
|
|
63
|
+
.argument('<file|folder>', 'A single JSON file or a folder with a collection of JSON files')
|
|
64
|
+
.option('-s --schema-types', 'Output the GraphQL schema types', false)
|
|
65
|
+
.option('-e --selection-set', 'Output the Apollo Connector selection set', false)
|
|
66
|
+
.option('-o --output-file <file>', 'Where to write the output', 'stdout')
|
|
67
|
+
.parse(process.argv);
|
|
68
|
+
const source = program.args[0];
|
|
69
|
+
main(source, program.opts()).then(() => console.log('done'));
|
|
70
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/cli/json.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport { JsonGen } from '../json/index.js';\n\n// // mute console.log\n// console.log = () => {};\n\n// function walkSourceFile(source: string): void {\n// const fileContent = fs.readFileSync(source, 'utf-8');\n\n// const walker = JsonGen.fromReader(fileContent);\n// console.info(walker.generateSchema());\n// }\n\n// async function main() {\n// walkSourceFile(\n// '/Users/fernando/Development/Apollo/connectors/projects/JsonToConnector/src/test/resources/preferences/user/50.json',\n// );\n// }\n\n// main().then(() => console.log('done'));\n\nimport { Command } from 'commander';\n\n// const originalConsole = {\n// log: console.log,\n// };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- for options\nasync function main(fileOrFolder: string, opts: any): Promise<void> {\n console.log = () => {};\n\n if (!fs.existsSync(fileOrFolder)) {\n console.error(`File or folder not found: ${fileOrFolder}`);\n return;\n }\n\n // generator\n let gen: JsonGen;\n\n // if it is a file\n if (fs.lstatSync(fileOrFolder).isFile()) {\n // read contents\n const contents = fs.readFileSync(fileOrFolder, 'utf-8');\n gen = JsonGen.fromReader(contents);\n } else {\n // iterate through the files found in the target folder and load all the contents\n gen = JsonGen.new();\n fs.readdirSync(fileOrFolder).forEach((file) => {\n const contents = fs.readFileSync(fileOrFolder + '/' + file, 'utf-8');\n gen.walkJson(contents);\n });\n }\n\n let generated;\n if (opts.schemaTypes) {\n generated = gen.writeTypes();\n } else if (opts.selectionSet) {\n generated = gen.writeSelection();\n } else {\n generated = gen.generateSchema();\n }\n\n if (opts.outputFile !== 'stdout') {\n fs.writeFileSync(opts.outputFile, generated);\n } else {\n console.info(generated);\n }\n}\n\nconst program = new Command();\nprogram\n .version('0.0.1')\n .argument('<file|folder>', 'A single JSON file or a folder with a collection of JSON files')\n .option('-s --schema-types', 'Output the GraphQL schema types', false)\n .option('-e --selection-set', 'Output the Apollo Connector selection set', false)\n .option('-o --output-file <file>', 'Where to write the output', 'stdout')\n .parse(process.argv);\n\nconst source = program.args[0];\nmain(source, program.opts()).then(() => console.log('done'));\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { IType } from '../../oas/nodes/type.js';
|
|
2
|
+
import { OasGen } from '../../oas/oasGen.js';
|
|
3
|
+
export declare function generateFromSelection(opts: any, gen: OasGen): void;
|
|
4
|
+
export declare function promptForSelection(gen: OasGen, opts: any, types: IType[]): Promise<string[] | []>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/// internal functions
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { Composed } from '../../oas/nodes/comp.js';
|
|
4
|
+
import { Ref } from '../../oas/nodes/ref.js';
|
|
5
|
+
import { Union } from '../../oas/nodes/union.js';
|
|
6
|
+
import { typesPrompt } from '../../oas/prompts/prompt.js';
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
export function generateFromSelection(opts, gen) {
|
|
9
|
+
const selections = JSON.parse(fs.readFileSync(opts.loadSelections, { encoding: 'utf-8' }));
|
|
10
|
+
if (!Array.isArray(selections)) {
|
|
11
|
+
console.error('Invalid selections file');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
console.info('--------------- Apollo Connector schema -----------------');
|
|
15
|
+
console.info(gen.generateSchema(selections));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
export async function promptForSelection(gen, opts, types) {
|
|
20
|
+
function expandType(type) {
|
|
21
|
+
if (!type) {
|
|
22
|
+
return types;
|
|
23
|
+
}
|
|
24
|
+
let result;
|
|
25
|
+
if (type instanceof Composed || type instanceof Union) {
|
|
26
|
+
// make sure we gather all the props
|
|
27
|
+
type.consolidate([]);
|
|
28
|
+
result = Array.from(type.props.values());
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// top level paths
|
|
32
|
+
result = gen.expand(type);
|
|
33
|
+
if (result.length === 1) {
|
|
34
|
+
// we are checking for a ref so we can go straight to where its pointing
|
|
35
|
+
const child = result[0];
|
|
36
|
+
if (!child.visited) {
|
|
37
|
+
child.visit(gen.context);
|
|
38
|
+
}
|
|
39
|
+
if (child instanceof Ref) {
|
|
40
|
+
result = [child.refType];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
return typesPrompt({
|
|
47
|
+
context: gen.context,
|
|
48
|
+
expandFn: expandType,
|
|
49
|
+
message: 'Navigate spec and select the fields to use in the connector',
|
|
50
|
+
pageSize: parseInt(opts.pageSize, 10),
|
|
51
|
+
types: types,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/oas-helpers/index.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,8DAA8D;AAC9D,MAAM,UAAU,qBAAqB,CAAC,IAAS,EAAE,GAAW;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7C,OAAO;AACT,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAW,EAAE,IAAS,EAAE,KAAc;IAC7E,SAAS,UAAU,CAAC,IAAY;QAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,MAAe,CAAC;QAEpB,IAAI,IAAI,YAAY,QAAQ,IAAI,IAAI,YAAY,KAAK,EAAE,CAAC;YACtD,oCAAoC;YACnC,IAAyB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YAE3C,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,kBAAkB;YAClB,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAE1B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,wEAAwE;gBACxE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBAExB,IAAI,CAAE,KAAc,CAAC,OAAO,EAAE,CAAC;oBAC7B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAQ,CAAC,CAAC;gBAC5B,CAAC;gBAED,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;oBACzB,MAAM,GAAG,CAAC,KAAK,CAAC,OAAQ,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,WAAW,CAAC;QACjB,OAAO,EAAE,GAAG,CAAC,OAAQ;QACrB,QAAQ,EAAE,UAAU;QACpB,OAAO,EAAE,6DAA6D;QACtE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;QACrC,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;AACL,CAAC","sourcesContent":["/// internal functions\nimport fs from 'fs';\nimport { Composed } from '../../oas/nodes/comp.js';\nimport { Ref } from '../../oas/nodes/ref.js';\nimport { IType, Type } from '../../oas/nodes/type.js';\nimport { Union } from '../../oas/nodes/union.js';\nimport { OasGen } from '../../oas/oasGen.js';\nimport { typesPrompt } from '../../oas/prompts/prompt.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function generateFromSelection(opts: any, gen: OasGen) {\n const selections = JSON.parse(fs.readFileSync(opts.loadSelections, { encoding: 'utf-8' }));\n if (!Array.isArray(selections)) {\n console.error('Invalid selections file');\n return;\n }\n\n console.info('--------------- Apollo Connector schema -----------------');\n console.info(gen.generateSchema(selections));\n return;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function promptForSelection(gen: OasGen, opts: any, types: IType[]) {\n function expandType(type?: IType) {\n if (!type) {\n return types;\n }\n\n let result: IType[];\n\n if (type instanceof Composed || type instanceof Union) {\n // make sure we gather all the props\n (type as Composed | Union).consolidate([]);\n\n result = Array.from(type.props.values());\n } else {\n // top level paths\n result = gen.expand(type);\n\n if (result.length === 1) {\n // we are checking for a ref so we can go straight to where its pointing\n const child = result[0];\n\n if (!(child as Type).visited) {\n child.visit(gen.context!);\n }\n\n if (child instanceof Ref) {\n result = [child.refType!];\n }\n }\n }\n\n return result;\n }\n\n return typesPrompt({\n context: gen.context!,\n expandFn: expandType,\n message: 'Navigate spec and select the fields to use in the connector',\n pageSize: parseInt(opts.pageSize, 10),\n types: types,\n });\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/cli/oas.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { generateFromSelection, promptForSelection } from './oas-helpers/index.js';
|
|
3
|
+
import { OasGen } from '../oas/oasGen.js';
|
|
4
|
+
const originalConsole = {
|
|
5
|
+
log: console.log,
|
|
6
|
+
};
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- for options
|
|
8
|
+
async function main(sourceFile, opts) {
|
|
9
|
+
console.log = () => { };
|
|
10
|
+
const gen = await OasGen.fromFile(sourceFile, opts);
|
|
11
|
+
await gen.visit();
|
|
12
|
+
let pathSet = Array.from(gen.paths.values());
|
|
13
|
+
if (opts.loadSelections) {
|
|
14
|
+
generateFromSelection(opts, gen);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (opts.grep !== '*') {
|
|
18
|
+
const regex = new RegExp(opts.grep, 'ig');
|
|
19
|
+
pathSet = pathSet.filter((p) => regex.test(p.path()));
|
|
20
|
+
}
|
|
21
|
+
if (opts.listPaths) {
|
|
22
|
+
pathSet.forEach((path) => console.info(path.path()));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
let paths;
|
|
26
|
+
if (opts.skipSelection) {
|
|
27
|
+
paths = pathSet.map((p) => p.path() + '>**');
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
paths = await promptForSelection(gen, opts, pathSet);
|
|
31
|
+
}
|
|
32
|
+
console.info('selected :=', JSON.stringify(paths, null, 2));
|
|
33
|
+
console.info('--------------- Apollo Connector schema -----------------');
|
|
34
|
+
console.info(gen.generateSchema(paths));
|
|
35
|
+
}
|
|
36
|
+
const program = new Command();
|
|
37
|
+
program
|
|
38
|
+
.version('0.0.1')
|
|
39
|
+
.argument('<source>', 'source spec (yaml or json)')
|
|
40
|
+
.option('-i --skip-validation', 'Skip validation step', false)
|
|
41
|
+
.option('-n --skip-selection', 'Generate all [filtered] paths without prompting for a selection', false)
|
|
42
|
+
.option('-l --list-paths', 'Only list the paths that can be generated', false)
|
|
43
|
+
.option('-g --grep <regex>', 'Filter the list of paths with the passed expression', '*')
|
|
44
|
+
.option('-p --page-size <num>', 'Number of rows to display in selection mode', '10')
|
|
45
|
+
.option('-s --load-selections <file>', 'Load a JSON file with field selections (other options are ignored)')
|
|
46
|
+
.parse(process.argv);
|
|
47
|
+
const source = program.args[0];
|
|
48
|
+
main(source, program.opts()).then(() => console.log('done'));
|
|
49
|
+
//# sourceMappingURL=oas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oas.js","sourceRoot":"","sources":["../../src/cli/oas.ts"],"names":[],"mappings":"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","sourcesContent":["import { Command } from 'commander';\nimport { generateFromSelection, promptForSelection } from './oas-helpers/index.js';\nimport { OasGen } from '../oas/oasGen.js';\n\nconst originalConsole = {\n log: console.log,\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- for options\nasync function main(sourceFile: string, opts: any): Promise<void> {\n console.log = () => {};\n\n const gen = await OasGen.fromFile(sourceFile, opts);\n await gen.visit();\n\n let pathSet = Array.from(gen.paths.values());\n if (opts.loadSelections) {\n generateFromSelection(opts, gen);\n return;\n }\n\n if (opts.grep !== '*') {\n const regex = new RegExp(opts.grep, 'ig');\n pathSet = pathSet.filter((p) => regex.test(p.path()));\n }\n\n if (opts.listPaths) {\n pathSet.forEach((path) => console.info(path.path()));\n return;\n }\n\n let paths: string[];\n if (opts.skipSelection) {\n paths = pathSet.map((p) => p.path() + '>**');\n } else {\n paths = await promptForSelection(gen, opts, pathSet);\n }\n\n console.info('selected :=', JSON.stringify(paths, null, 2));\n console.info('--------------- Apollo Connector schema -----------------');\n console.info(gen.generateSchema(paths));\n}\n\nconst program = new Command();\nprogram\n .version('0.0.1')\n .argument('<source>', 'source spec (yaml or json)')\n .option('-i --skip-validation', 'Skip validation step', false)\n .option('-n --skip-selection', 'Generate all [filtered] paths without prompting for a selection', false)\n .option('-l --list-paths', 'Only list the paths that can be generated', false)\n .option('-g --grep <regex>', 'Filter the list of paths with the passed expression', '*')\n .option('-p --page-size <num>', 'Number of rows to display in selection mode', '10')\n .option('-s --load-selections <file>', 'Load a JSON file with field selections (other options are ignored)')\n .parse(process.argv);\n\nconst source = program.args[0];\nmain(source, program.opts()).then(() => console.log('done'));\n"]}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["// export * from './oas';\nexport { JsonGen } from './json/index.js';\nexport { OasGen } from './oas/oasGen.js';\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { StringWriter, ConnectorWriter } from './io/index.js';
|
|
2
|
+
export { JsonContext } from './walker/jsonContext.js';
|
|
3
|
+
export { JsonGen } from './walker/jsonGen.js';
|
|
4
|
+
export { JsonObj, JsonScalar, JsonType, JsonArray } from './walker/types/index.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/json/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC","sourcesContent":["export { StringWriter, ConnectorWriter } from './io/index.js';\nexport { JsonContext } from './walker/jsonContext.js';\nexport { JsonGen } from './walker/jsonGen.js';\nexport { JsonObj, JsonScalar, JsonType, JsonArray } from './walker/types/index.js';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StringWriter, ConnectorWriter, type IWriter } from './writer.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/json/io/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAgB,MAAM,aAAa,CAAC","sourcesContent":["export { StringWriter, ConnectorWriter, type IWriter } from './writer.js';\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { JsonGen } from '../walker/jsonGen.js';
|
|
2
|
+
export interface IWriter {
|
|
3
|
+
write(text: string): void;
|
|
4
|
+
}
|
|
5
|
+
export declare class StringWriter implements IWriter {
|
|
6
|
+
builder: string[];
|
|
7
|
+
write(text: string): void;
|
|
8
|
+
flush(): string;
|
|
9
|
+
clear(): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class ConnectorWriter {
|
|
12
|
+
static write(walker: JsonGen, writer: IWriter): void;
|
|
13
|
+
private static writeConnector;
|
|
14
|
+
private static writeQuery;
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export class StringWriter {
|
|
2
|
+
builder = [];
|
|
3
|
+
write(text) {
|
|
4
|
+
this.builder.push(text);
|
|
5
|
+
}
|
|
6
|
+
flush() {
|
|
7
|
+
return this.builder.join('');
|
|
8
|
+
}
|
|
9
|
+
clear() {
|
|
10
|
+
this.builder = [];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class ConnectorWriter {
|
|
14
|
+
static write(walker, writer) {
|
|
15
|
+
this.writeConnector(writer);
|
|
16
|
+
writer.write(walker.writeTypes());
|
|
17
|
+
this.writeQuery(walker, writer);
|
|
18
|
+
}
|
|
19
|
+
static writeConnector(writer) {
|
|
20
|
+
writer.write(`extend schema
|
|
21
|
+
@link(url: "https://specs.apollo.dev/federation/v2.10", import: ["@key"])
|
|
22
|
+
@link(
|
|
23
|
+
url: "https://specs.apollo.dev/connect/v0.1"
|
|
24
|
+
import: ["@connect", "@source"]
|
|
25
|
+
)
|
|
26
|
+
@source(name: "api", http: { baseURL: "http://localhost:4010" })
|
|
27
|
+
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
static writeQuery(walker, writer) {
|
|
31
|
+
writer.write('\n' +
|
|
32
|
+
`type Query {
|
|
33
|
+
root: Root
|
|
34
|
+
@connect(
|
|
35
|
+
source: "api"
|
|
36
|
+
http: { GET: "/test" }
|
|
37
|
+
selection: """` +
|
|
38
|
+
'\n');
|
|
39
|
+
writer.write(walker.writeSelection());
|
|
40
|
+
writer.write(`"""
|
|
41
|
+
)}
|
|
42
|
+
`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/json/io/writer.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,YAAY;IACvB,OAAO,GAAa,EAAE,CAAC;IAEvB,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;CACF;AAED,MAAM,OAAO,eAAe;IACnB,MAAM,CAAC,KAAK,CAAC,MAAe,EAAE,MAAe;QAClD,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAEO,MAAM,CAAC,cAAc,CAAC,MAAe;QAC3C,MAAM,CAAC,KAAK,CAAC;;;;;;;;CAQhB,CAAC,CAAC;IACD,CAAC;IAEO,MAAM,CAAC,UAAU,CAAC,MAAe,EAAE,MAAe;QACxD,MAAM,CAAC,KAAK,CACV,IAAI;YACF;;;;;qBAKa;YACb,IAAI,CACP,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC;;CAEhB,CAAC,CAAC;IACD,CAAC;CACF","sourcesContent":["import { JsonGen } from '../walker/jsonGen.js';\n\nexport interface IWriter {\n write(text: string): void;\n}\n\nexport class StringWriter implements IWriter {\n builder: string[] = [];\n\n write(text: string): void {\n this.builder.push(text);\n }\n\n flush(): string {\n return this.builder.join('');\n }\n\n clear(): void {\n this.builder = [];\n }\n}\n\nexport class ConnectorWriter {\n public static write(walker: JsonGen, writer: IWriter): void {\n this.writeConnector(writer);\n writer.write(walker.writeTypes());\n this.writeQuery(walker, writer);\n }\n\n private static writeConnector(writer: IWriter): void {\n writer.write(`extend schema\n @link(url: \"https://specs.apollo.dev/federation/v2.10\", import: [\"@key\"])\n @link(\n url: \"https://specs.apollo.dev/connect/v0.1\"\n import: [\"@connect\", \"@source\"]\n )\n @source(name: \"api\", http: { baseURL: \"http://localhost:4010\" })\n \n`);\n }\n\n private static writeQuery(walker: JsonGen, writer: IWriter): void {\n writer.write(\n '\\n' +\n `type Query {\n root: Root\n @connect(\n source: \"api\"\n http: { GET: \"/test\" }\n selection: \"\"\"` +\n '\\n',\n );\n\n writer.write(walker.writeSelection());\n writer.write(`\"\"\"\n)}\n`);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/json/walker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { JsonContext } from './jsonContext.js';\nexport { JsonGen } from './jsonGen.js';\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { JsonType } from '../walker/types/jsonType.js';
|
|
2
|
+
export declare class JsonContext {
|
|
3
|
+
private stack;
|
|
4
|
+
private types;
|
|
5
|
+
constructor();
|
|
6
|
+
getStack(): JsonType[];
|
|
7
|
+
enter(element: JsonType): void;
|
|
8
|
+
leave(_element: JsonType): void;
|
|
9
|
+
store(type: JsonType): void;
|
|
10
|
+
private merge;
|
|
11
|
+
getTypes(): JsonType[];
|
|
12
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { JsonObj } from '../walker/types/jsonObj.js';
|
|
2
|
+
export class JsonContext {
|
|
3
|
+
stack;
|
|
4
|
+
types;
|
|
5
|
+
constructor() {
|
|
6
|
+
this.stack = [];
|
|
7
|
+
this.types = new Map();
|
|
8
|
+
}
|
|
9
|
+
getStack() {
|
|
10
|
+
return this.stack;
|
|
11
|
+
}
|
|
12
|
+
enter(element) {
|
|
13
|
+
// trace(this, "[context]", "-> enter: (" + this.stack.length + ") " + element.getName());
|
|
14
|
+
this.stack.push(element);
|
|
15
|
+
}
|
|
16
|
+
leave(_element) {
|
|
17
|
+
// trace(this, "[context]", "<- leave: (" + this.stack.length + ") " + element.getName());
|
|
18
|
+
this.stack.pop();
|
|
19
|
+
}
|
|
20
|
+
store(type) {
|
|
21
|
+
if (this.types.has(type.id())) {
|
|
22
|
+
this.merge(type);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
this.types.set(type.id(), type);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
merge(type) {
|
|
29
|
+
const source = this.types.get(type.id());
|
|
30
|
+
// Only merge if both are Obj instances
|
|
31
|
+
if (source instanceof JsonObj && type instanceof JsonObj) {
|
|
32
|
+
type.getFields().forEach((value, key) => {
|
|
33
|
+
source.getFields().set(key, value);
|
|
34
|
+
});
|
|
35
|
+
this.types.set(source.id(), source);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
getTypes() {
|
|
39
|
+
return Array.from(this.types.values());
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=jsonContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonContext.js","sourceRoot":"","sources":["../../../src/json/walker/jsonContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAGrD,MAAM,OAAO,WAAW;IACd,KAAK,CAAa;IAClB,KAAK,CAAwB;IAErC;QACE,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC3C,CAAC;IAEM,QAAQ;QACb,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAEM,KAAK,CAAC,OAAiB;QAC5B,0FAA0F;QAC1F,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,QAAkB;QAC7B,0FAA0F;QAC1F,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,IAAc;QACzB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAc;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,uCAAuC;QACvC,IAAI,MAAM,YAAY,OAAO,IAAI,IAAI,YAAY,OAAO,EAAE,CAAC;YACzD,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,KAAe,EAAE,GAAW,EAAE,EAAE;gBACxD,MAAM,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;CACF","sourcesContent":["import { JsonObj } from '../walker/types/jsonObj.js';\nimport { JsonType } from '../walker/types/jsonType.js';\n\nexport class JsonContext {\n private stack: JsonType[];\n private types: Map<string, JsonType>;\n\n constructor() {\n this.stack = [];\n this.types = new Map<string, JsonType>();\n }\n\n public getStack(): JsonType[] {\n return this.stack;\n }\n\n public enter(element: JsonType): void {\n // trace(this, \"[context]\", \"-> enter: (\" + this.stack.length + \") \" + element.getName());\n this.stack.push(element);\n }\n\n public leave(_element: JsonType): void {\n // trace(this, \"[context]\", \"<- leave: (\" + this.stack.length + \") \" + element.getName());\n this.stack.pop();\n }\n\n public store(type: JsonType): void {\n if (this.types.has(type.id())) {\n this.merge(type);\n } else {\n this.types.set(type.id(), type);\n }\n }\n\n private merge(type: JsonType): void {\n const source = this.types.get(type.id());\n // Only merge if both are Obj instances\n if (source instanceof JsonObj && type instanceof JsonObj) {\n type.getFields().forEach((value: JsonType, key: string) => {\n source.getFields().set(key, value);\n });\n this.types.set(source.id(), source);\n }\n }\n\n public getTypes(): JsonType[] {\n return Array.from(this.types.values());\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { JsonContext } from '../index.js';
|
|
2
|
+
export declare class JsonGen {
|
|
3
|
+
private readonly context;
|
|
4
|
+
private constructor();
|
|
5
|
+
getContext(): JsonContext;
|
|
6
|
+
static new(): JsonGen;
|
|
7
|
+
static fromReader(json: string): JsonGen;
|
|
8
|
+
static fromJsons(jsons: string[]): JsonGen;
|
|
9
|
+
generateSchema(): string;
|
|
10
|
+
writeSelection(): string;
|
|
11
|
+
writeTypes(): string;
|
|
12
|
+
private writeType;
|
|
13
|
+
walkJson(json: string): void;
|
|
14
|
+
private walkElement;
|
|
15
|
+
private walkObject;
|
|
16
|
+
private walkArray;
|
|
17
|
+
private walkPrimitive;
|
|
18
|
+
private static generateNewObjType;
|
|
19
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { ConnectorWriter, JsonArray, JsonContext, JsonObj, JsonScalar, StringWriter } from '../index.js';
|
|
4
|
+
import { trace, warn } from './log/trace.js';
|
|
5
|
+
import { sanitiseField } from './naming.js';
|
|
6
|
+
export class JsonGen {
|
|
7
|
+
context;
|
|
8
|
+
// Private constructor
|
|
9
|
+
constructor() {
|
|
10
|
+
this.context = new JsonContext();
|
|
11
|
+
}
|
|
12
|
+
getContext() {
|
|
13
|
+
return this.context;
|
|
14
|
+
}
|
|
15
|
+
// // Walks the provided file or folder (synchronously)
|
|
16
|
+
// public walk(fileOrFolder: string): void {
|
|
17
|
+
// const stats = fs.statSync(fileOrFolder);
|
|
18
|
+
// if (stats.isDirectory()) {
|
|
19
|
+
// const sources = fs
|
|
20
|
+
// .readdirSync(fileOrFolder)
|
|
21
|
+
// .filter((name) => name.toLowerCase().endsWith('.json'));
|
|
22
|
+
// for (const source of sources) {
|
|
23
|
+
// const fullPath = path.join(fileOrFolder, source);
|
|
24
|
+
// this.walkSourceFile(fullPath);
|
|
25
|
+
// }
|
|
26
|
+
// } else {
|
|
27
|
+
// this.walkSourceFile(fileOrFolder);
|
|
28
|
+
// }
|
|
29
|
+
// }
|
|
30
|
+
// Factory method from file or folder
|
|
31
|
+
// public static fromFileOrFolder(fileOrFolder: string): Walker {
|
|
32
|
+
// if (!fs.existsSync(fileOrFolder)) {
|
|
33
|
+
// throw new Error('Argument does not exist');
|
|
34
|
+
// }
|
|
35
|
+
// const walker = new Walker();
|
|
36
|
+
// walker.walk(fileOrFolder);
|
|
37
|
+
// return walker;
|
|
38
|
+
// }
|
|
39
|
+
static new() {
|
|
40
|
+
return new JsonGen();
|
|
41
|
+
}
|
|
42
|
+
// Factory method from a JSON string
|
|
43
|
+
static fromReader(json) {
|
|
44
|
+
const walker = new JsonGen();
|
|
45
|
+
walker.walkJson(json);
|
|
46
|
+
return walker;
|
|
47
|
+
}
|
|
48
|
+
static fromJsons(jsons) {
|
|
49
|
+
const walker = new JsonGen();
|
|
50
|
+
for (const json of jsons) {
|
|
51
|
+
walker.walkJson(json);
|
|
52
|
+
}
|
|
53
|
+
return walker;
|
|
54
|
+
}
|
|
55
|
+
generateSchema() {
|
|
56
|
+
const writer = new StringWriter();
|
|
57
|
+
ConnectorWriter.write(this, writer);
|
|
58
|
+
return writer.flush();
|
|
59
|
+
}
|
|
60
|
+
// Writes selection using a given Writer
|
|
61
|
+
writeSelection() {
|
|
62
|
+
const writer = new StringWriter();
|
|
63
|
+
const types = this.context.getTypes();
|
|
64
|
+
const root = types.find((t) => t.getParent() === null);
|
|
65
|
+
if (root) {
|
|
66
|
+
root.select(this.context, writer);
|
|
67
|
+
}
|
|
68
|
+
return writer.flush();
|
|
69
|
+
}
|
|
70
|
+
// Writes all types in order using the provided Writer
|
|
71
|
+
writeTypes() {
|
|
72
|
+
const writer = new StringWriter();
|
|
73
|
+
const types = this.context.getTypes();
|
|
74
|
+
const root = types.find((t) => t.getParent() === null);
|
|
75
|
+
if (root) {
|
|
76
|
+
const orderedSet = new Set();
|
|
77
|
+
this.writeType(root, orderedSet);
|
|
78
|
+
const generatedSet = new Map();
|
|
79
|
+
orderedSet.forEach((t) => {
|
|
80
|
+
// Assumes t is an Obj
|
|
81
|
+
const obj = t;
|
|
82
|
+
let typeName = obj.getType();
|
|
83
|
+
if (generatedSet.has(typeName)) {
|
|
84
|
+
// If same type, skip generation
|
|
85
|
+
if (_.isEqual(obj, generatedSet.get(typeName))) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
obj.setType(JsonGen.generateNewObjType(generatedSet, t, typeName));
|
|
89
|
+
typeName = obj.getType();
|
|
90
|
+
}
|
|
91
|
+
t.write(this.context, writer);
|
|
92
|
+
generatedSet.set(typeName, t);
|
|
93
|
+
});
|
|
94
|
+
console.log('orderedSet =', Array.from(orderedSet));
|
|
95
|
+
}
|
|
96
|
+
return writer.flush();
|
|
97
|
+
}
|
|
98
|
+
// Recursive helper to order types
|
|
99
|
+
writeType(type, orderedSet) {
|
|
100
|
+
if (type instanceof JsonObj) {
|
|
101
|
+
// Traverse children first
|
|
102
|
+
for (const child of Array.from(type.getFields().values())) {
|
|
103
|
+
this.writeType(child, orderedSet);
|
|
104
|
+
}
|
|
105
|
+
orderedSet.add(type);
|
|
106
|
+
}
|
|
107
|
+
else if (type instanceof JsonArray) {
|
|
108
|
+
const arrayType = type.getArrayType();
|
|
109
|
+
if (arrayType) {
|
|
110
|
+
this.writeType(arrayType, orderedSet);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// // Walk a source file (given by path)
|
|
115
|
+
// private walkSourceFile(source: string): void {
|
|
116
|
+
// trace(this.context, '-> [walkSource]', 'in: ' + path.basename(source));
|
|
117
|
+
// const fileContent = fs.readFileSync(source, 'utf-8');
|
|
118
|
+
// this.walkReader(fileContent);
|
|
119
|
+
// trace(this.context, '<- [walkSource]', 'out: ' + path.basename(source));
|
|
120
|
+
// }
|
|
121
|
+
// Walk the JSON provided as a string
|
|
122
|
+
walkJson(json) {
|
|
123
|
+
const rootElement = JSON.parse(json);
|
|
124
|
+
this.walkElement(this.context, null, 'root', rootElement);
|
|
125
|
+
trace(this.context, ' [walkSource]', 'types found: ' + this.context.getTypes().length);
|
|
126
|
+
}
|
|
127
|
+
// Walk an element in the JSON tree
|
|
128
|
+
walkElement(context, parent, name, element) {
|
|
129
|
+
trace(context, '-> [walkElement]', 'in: ' + name);
|
|
130
|
+
let result;
|
|
131
|
+
if (typeof element === 'object' && !Array.isArray(element) && element !== null) {
|
|
132
|
+
// JSON object
|
|
133
|
+
result = this.walkObject(context, parent, name, element);
|
|
134
|
+
context.store(result);
|
|
135
|
+
}
|
|
136
|
+
else if (Array.isArray(element)) {
|
|
137
|
+
result = this.walkArray(context, parent, name, element);
|
|
138
|
+
}
|
|
139
|
+
else if (typeof element === 'string' || typeof element === 'number' || typeof element === 'boolean') {
|
|
140
|
+
result = this.walkPrimitive(context, parent, name, element);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
throw new Error("Cannot yet handle '" + name + "' of type " + typeof element);
|
|
144
|
+
}
|
|
145
|
+
trace(context, '<- [walkElement]', 'out: ' + name);
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
// Walk a JSON object
|
|
149
|
+
walkObject(context, parent, name, object) {
|
|
150
|
+
trace(context, '-> [walkObject]', 'in: ' + name);
|
|
151
|
+
const result = new JsonObj(name, parent);
|
|
152
|
+
const fieldSet = Object.keys(object);
|
|
153
|
+
trace(context, ' [walkObject]', 'fieldSet: ' + fieldSet);
|
|
154
|
+
for (const field of fieldSet) {
|
|
155
|
+
trace(context, ' [walkObject]', 'field: ' + field);
|
|
156
|
+
const childElement = object[field];
|
|
157
|
+
const type = this.walkElement(context, result, field, childElement);
|
|
158
|
+
result.add(field, type);
|
|
159
|
+
}
|
|
160
|
+
trace(context, '<- [walkObject]', 'out: ' + name);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
// Walk a JSON array
|
|
164
|
+
walkArray(context, parent, name, array) {
|
|
165
|
+
trace(context, '-> [walkArray]', 'in: ' + name);
|
|
166
|
+
const result = new JsonArray(name, parent);
|
|
167
|
+
if (array.length > 0) {
|
|
168
|
+
const firstElement = array[0];
|
|
169
|
+
const arrayType = this.walkElement(context, parent, name, firstElement);
|
|
170
|
+
result.setArrayType(arrayType);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
warn(context, ' [walkArray]', "Array is empty -- cannot derive type for field '" + name + "'");
|
|
174
|
+
}
|
|
175
|
+
trace(context, '-> [walkArray]', 'in: ' + name);
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
// Walk a primitive JSON value
|
|
179
|
+
walkPrimitive(_context, parent, name, primitive) {
|
|
180
|
+
let result;
|
|
181
|
+
if (typeof primitive === 'string') {
|
|
182
|
+
result = new JsonScalar(name, parent, 'String');
|
|
183
|
+
}
|
|
184
|
+
else if (typeof primitive === 'boolean') {
|
|
185
|
+
result = new JsonScalar(name, parent, 'Boolean');
|
|
186
|
+
}
|
|
187
|
+
else if (typeof primitive === 'number') {
|
|
188
|
+
result = new JsonScalar(name, parent, 'Int');
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
throw new Error('Cannot yet handle primitive: ' + primitive);
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
// Utility method for naming conflict resolution
|
|
196
|
+
static generateNewObjType(generatedSet, t, typeName) {
|
|
197
|
+
let newName;
|
|
198
|
+
let type = t;
|
|
199
|
+
do {
|
|
200
|
+
const parent = type.getParent();
|
|
201
|
+
const parentName = parent === null ? '' : sanitiseField(parent.getName()).replace(/^\w/, (c) => c.toUpperCase());
|
|
202
|
+
const thisName = sanitiseField(typeName).replace(/^\w/, (c) => c.toUpperCase());
|
|
203
|
+
newName = parentName + thisName;
|
|
204
|
+
type = parent;
|
|
205
|
+
} while (type !== null && generatedSet.has(newName));
|
|
206
|
+
return newName;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=jsonGen.js.map
|