Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
maxnachlinger committed Feb 2, 2019
0 parents commit 8ad7e00
Show file tree
Hide file tree
Showing 27 changed files with 8,726 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
@@ -0,0 +1,2 @@
node_modules/
coverage/
22 changes: 22 additions & 0 deletions .eslintrc.yml
@@ -0,0 +1,22 @@
###########################################################################
# Copyright (c) [2018]-present, Walmart Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License."
###########################################################################

---
extends: "walmart/configurations/es6-node"
env:
node: true
es6: true
jest: true
5 changes: 5 additions & 0 deletions .gitignore
@@ -0,0 +1,5 @@
node_modules
coverage
.nyc_output
.idea

13 changes: 13 additions & 0 deletions .looper.yml
@@ -0,0 +1,13 @@
inherit: 'job://looper-base'
envs:
global:
variables:
SONAR_SCANNER: '${WORKSPACE}/sonar-scanner'
tools:
nodejs: 10.14.2
npm: 6.5.0
flows:
default:
- call: master-job
pr:
- call: pr-job
12 changes: 12 additions & 0 deletions .npmignore
@@ -0,0 +1,12 @@
.nyc_output
coverage
test
.eslintignore
.eslintrc.yml
.gitignore
.looper.yml
.npmrc
.prettierignore
.prettierrc
.looper.yml
sonar-project.properties
1 change: 1 addition & 0 deletions .npmrc
@@ -0,0 +1 @@
registry=https://registry.npmjs.com/
4 changes: 4 additions & 0 deletions .prettierignore
@@ -0,0 +1,4 @@
node_modules
coverage
test/fixtures
.DS_Store
7 changes: 7 additions & 0 deletions .prettierrc
@@ -0,0 +1,7 @@

{
"useTabs": false,
"printWidth": 100,
"tabWidth": 2,
"jsxBracketSameLine": true
}
13 changes: 13 additions & 0 deletions LICENSE
@@ -0,0 +1,13 @@
Copyright (c) [2018]-present, Walmart Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
5 changes: 5 additions & 0 deletions LICENSE-DOCS
@@ -0,0 +1,5 @@
Documentation in this project is licensed under

Creative Commons Attribution 4.0 International License.

Full details available at https://creativecommons.org/licenses/by/4.0/
141 changes: 141 additions & 0 deletions README.md
@@ -0,0 +1,141 @@
## json-to-simple-graphql-schema

Transforms streamed JSON input into a GraphQL schema.

### Why would I use this?

Let's say you want to use an existing REST API in a GraphQL service and expose the data that API provides. You'll need to expose that data in a GraphQL schema. Without this tool, you'll have to slog through the JSON response and manually extract and convert the relevant types to GraphQL schema types. This tool attempts to provide an automated reasonable first-pass at that effort.

### Installation:

No need to install this, use `npx` :) If you'd really like to install, you can do:
```bash
npm i -g @walmartlabs/json-to-simple-graphql-schema
```

### Usage:

Pipe in some JSON. Here's a cURL JSON response piped in to this app:
```bash
curl https://demo.ckan.org/api/3/action/package_show?id=adur_district_spending \
| npx json-to-simple-graphql-schema
```
> You'll still need to rename the resulting main Type in the schema, unless you like `AutogeneratedMainType` :)
```
Or pipe in some JSON from a JSON file.
```bash
curl https://demo.ckan.org/api/3/action/package_show?id=adur_district_spending > input.json
cat input.json | npx json-to-simple-graphql-schema > output.graphql
```

### Example output:

Given this JSON:
```json
{
"id": "some-id-0",
"name": "A fun object",
"subType": {
"id": "some-id-1",
"name": "A fun sub-type"
}
}
```
This app will send this to stdout:
```
type SubType {
id: String
name: String,
}
type AutogeneratedMainType {
id: String
name: String
subType: SubType
}
```

### Fun features: duplicate removal

Consider this JSON with 2 `color` types:
```json
{
"id": "some-id-0",
"name": "A fun object",
"color": {
"id": "color-id-1",
"name": "Test color"
},
"subType": {
"id": "some-id-1",
"name": "A fun sub-type",
"color": {
"id": "color-id-1",
"name": "Test color",
"hex": "#ff0000"
}
}
}
```
When piped to this app, the following schema is produced:
```
type Color {
id: String
name: String
hex: String,
}
type SubType {
id: String
name: String
color: Color,
}
type AutogeneratedMainType {
id: String
name: String
subType: SubType
color: Color
}
```
It kept the `Color` type with more fields.

### Fun features: calls out possible duplicates

Consider this JSON with two types containing identical fields:
```json
{
"id": "some-id-0",
"name": "A fun object",
"color": {
"id": "color-id-1",
"name": "Test color"
},
"favoriteColor": {
"id": "color-id-1",
"name": "Test color"
}
}
```
When piped to this app, the following schema is produced:
```
type FavoriteColor {
id: String
name: String
}
type Color {
id: String
name: String
}
type AutogeneratedMainType {
id: String
name: String
favoriteColor: FavoriteColor
color: Color
}
# Types with identical fields:
# FavoriteColor Color
```
It called out the two types with identical fields.
41 changes: 41 additions & 0 deletions app.js
@@ -0,0 +1,41 @@
#! /usr/bin/env node
/**
* Copyright (c) [2018]-present, Walmart Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License."
*/

"use strict";

const getStdin = require("get-stdin");
const { jsonToSchema } = require("./lib");

const main = async () => {
const jsonInput = await getStdin();

const { error, value } = jsonToSchema({ jsonInput });
if (error) {
// eslint-disable-next-line no-console
console.error(error);
throw error;
}

// eslint-disable-next-line no-console
console.log(value);
};

if (!module.parent) {
main();
}

module.exports = { jsonToSchema };
57 changes: 57 additions & 0 deletions lib/index.js
@@ -0,0 +1,57 @@
/**
* Copyright (c) [2018]-present, Walmart Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License."
*/

"use strict";

const { toSchema } = require("./to-schema");
const { stringifySchema } = require("./stringify-schema");

const safeFnExecute = fn => {
try {
return { value: fn() };
} catch (error) {
return { error };
}
};

const validateJson = jsonInput => {
const { error: jsonError, value } = safeFnExecute(() => JSON.parse(jsonInput));

if (jsonError) {
jsonError.message = `Invalid JSON received: ${jsonInput}, error: ${jsonError.message}`;
return { error: jsonError };
}

if (!value) {
return { error: new Error(`Invalid JSON received: ${jsonInput}`) };
}

return { value };
};

const jsonToSchema = ({ baseType = "AutogeneratedMainType", jsonInput }) => {
const { error, value } = validateJson(jsonInput);
if (error) {
return { error };
}

return safeFnExecute(() => stringifySchema(baseType, toSchema(value)));
};

module.exports = {
jsonToSchema,
validateJson
};

0 comments on commit 8ad7e00

Please sign in to comment.