[
  {
    "path": ".editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\r\n# coding styles between different editors and IDEs\r\n# http://editorconfig.org\r\n\r\nroot = true\r\n\r\n[*]\r\nindent_style = space\r\nindent_size = 2\r\nend_of_line = lf\r\ncharset = utf-8\r\ntrim_trailing_whitespace = true\r\ninsert_final_newline = true\r\n"
  },
  {
    "path": ".eslintignore",
    "content": "/client/*\r\n/coverage/**\r\n/out/**"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n    \"root\": true,\n    \"env\": {\n        \"amd\": true,\n        \"browser\": true,\n        \"mocha\": true,\n        \"es6\": true,\n        \"jasmine\": true,\n        \"node\": true\n    },\n    \"globals\": {\n        \"assert\": true,\n        \"browser\": true,\n        \"expect\": true,\n        \"by\": true,\n        \"protractor\": true,\n        \"sinon\": true,\n        \"xdescribe\": true,\n        \"xit\": true\n    },\n    \"plugins\": [\n        \"nodeca\"\n    ],\n    \"rules\": {\n        \"comma-dangle\": [1, \"ignore\"],\n        \"camelcase\": 0,\n        \"complexity\": [0, 11],\n        \"consistent-return\": 2,\n        \"consistent-this\": [1, \"self\"],\n        \"curly\": [2, \"all\"],\n        \"dot-notation\": 2,\n        \"eol-last\": 0,\n        \"eqeqeq\": [2, \"smart\"],\n        \"indent\": [0, 1, {\n            \"SwitchCase\": 1\n        }],\n        \"keyword-spacing\": [2, {\n            \"before\": true,\n            \"after\": true,\n            \"overrides\": {}\n        }],\n        \"nodeca/indent\": [2, \"spaces\", 4],\n        \"max-depth\": [0, 4],\n        \"max-len\": [0, 80, 4],\n        \"max-nested-callbacks\": [0, 2],\n        \"max-params\": [0, 15],\n        \"max-statements\": [0, 10],\n        \"new-cap\": [0],\n        \"new-parens\": 2,\n        \"no-alert\": 2,\n        \"no-array-constructor\": 2,\n        \"no-caller\": 2,\n        \"no-catch-shadow\": 2,\n        \"no-cond-assign\": 2,\n        \"no-console\": 1,\n        \"no-constant-condition\": 2,\n        \"no-control-regex\": 2,\n        \"no-debugger\": 2,\n        \"no-delete-var\": 2,\n        \"no-dupe-keys\": 2,\n        \"no-empty\": 0,\n        \"no-empty-character-class\": 2,\n        \"no-labels\": 2,\n        \"no-ex-assign\": 2,\n        \"no-extend-native\": 2,\n        \"no-extra-boolean-cast\": 2,\n        \"no-extra-parens\": 1,\n        \"no-extra-semi\": 2,\n        \"no-fallthrough\": 2,\n        \"no-func-assign\": 2,\n        \"no-implied-eval\": 2,\n        \"no-invalid-regexp\": 2,\n        \"no-iterator\": 2,\n        \"no-label-var\": 2,\n        \"no-lone-blocks\": 2,\n        \"no-lonely-if\": 0,\n        \"no-loop-func\": 2,\n        \"no-mixed-spaces-and-tabs\": [2, true],\n        \"no-multi-str\": 2,\n        \"no-multiple-empty-lines\": [2, {\n            \"max\": 1\n        }],\n        \"no-native-reassign\": 2,\n        \"no-negated-in-lhs\": 2,\n        \"no-nested-ternary\": 0,\n        \"no-new\": 2,\n        \"no-new-func\": 2,\n        \"no-new-object\": 2,\n        \"no-new-require\": 0,\n        \"no-new-wrappers\": 2,\n        \"no-obj-calls\": 2,\n        \"no-octal\": 2,\n        \"no-octal-escape\": 2,\n        \"no-path-concat\": 2,\n        \"no-process-exit\": 1,\n        \"no-proto\": 2,\n        \"no-redeclare\": 2,\n        \"no-regex-spaces\": 2,\n        \"no-return-assign\": 2,\n        \"no-script-url\": 2,\n        \"no-sequences\": 2,\n        \"no-shadow\": 0,\n        \"no-shadow-restricted-names\": 2,\n        \"no-spaced-func\": 2,\n        \"no-sparse-arrays\": 2,\n        \"no-sync\": 0,\n        \"no-ternary\": 0,\n        \"no-trailing-spaces\": 2,\n        \"no-undef\": 2,\n        \"no-undef-init\": 2,\n        \"no-underscore-dangle\": 0,\n        \"no-unreachable\": 2,\n        \"no-unused-vars\": [2, {\n            \"args\": \"none\",\n            \"vars\": \"local\"\n        }],\n        \"no-use-before-define\": 2,\n        \"no-warning-comments\": [1, {\n            \"terms\": [\"todo\", \"fixme\", \"xxx\"],\n            \"location\": \"start\"\n        }],\n        \"no-with\": 2,\n        \"quotes\": [2, \"single\"],\n        \"semi\": 2,\n        \"semi-spacing\": 2,\n        \"space-infix-ops\": [2, {\n            \"int32Hint\": false\n        }],\n        \"strict\": [2, \"global\"],\n        \"use-isnan\": 2,\n        \"valid-jsdoc\": [2, {\n            \"prefer\": {\n                \"return\": \"returns\"\n            },\n            \"requireReturn\": false,\n            \"requireParamDescription\": true\n        }],\n        \"valid-typeof\": 2,\n        \"wrap-iife\": [2, \"any\"],\n        \"yoda\": [2, \"never\", {\n            \"exceptRange\": true\n        }]\n    }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Dependencies\nnode_modules/\n\n# Coverage\ncoverage\n\n# Transpiled files\nbuild/\n\n# VS Code\n#.vscode\n#!.vscode/tasks.js\n\n# JetBrains IDEs\n.idea/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Misc\n.DS_Store\ndata\n\npackage-lock.json\n"
  },
  {
    "path": ".jsbeautifyrc",
    "content": "{\n  \"html\": {\n    \"allowed_file_extensions\": [\"htm\", \"html\", \"xhtml\", \"shtml\", \"xml\", \"svg\"],\n    \"brace_style\": \"collapse\",\n    \"indent_char\": \" \",\n    \"indent_handlebars\": false,\n    \"indent_inner_html\": false,\n    \"indent_scripts\": \"keep\",\n    \"indent_size\": 4,\n    \"max_preserve_newlines\": 1,\n    \"preserve_newlines\": true,\n    \"unformatted\": [\"a\", \"sub\", \"sup\", \"b\", \"i\", \"u\", \"pre\"],\n    \"wrap_line_length\": 0\n  },\n  \"css\": {\n    \"allowed_file_extensions\": [\"css\", \"scss\", \"sass\", \"less\"],\n    \"end_with_newline\": false,\n    \"indent_char\": \" \",\n    \"indent_size\": 4,\n    \"selector_separator\": \" \",\n    \"selector_separator_newline\": false\n  },\n  \"js\": {\n    \"allowed_file_extensions\": [\"js\", \"json\", \"jshintrc\", \"jsbeautifyrc\"],\n    \"brace_style\": \"collapse\",\n    \"break_chained_methods\": false,\n    \"e4x\": true,\n    \"eval_code\": false,\n    \"indent_char\": \" \",\n    \"indent_level\": 0,\n    \"indent_size\": 4,\n    \"indent_with_tabs\": false,\n    \"jslint_happy\": false,\n    \"keep_array_indentation\": false,\n    \"keep_function_indentation\": false,\n    \"max_preserve_newlines\": 2,\n    \"preserve_newlines\": true,\n    \"space_before_conditional\": true,\n    \"space_in_paren\": false,\n    \"unescape_strings\": false,\n    \"wrap_line_length\": 0\n  }\n}\n"
  },
  {
    "path": ".npmignore",
    "content": "server\nclient\ntest\ncoverage\nresources\ncommon\ndata.json\n.vscode\n.github\n./data.json\nbuild\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"6\"\n  - \"7\"\n\ncache:\n  directories:\n    - ${HOME}/.npm\n\nbefore_install:\n  - npm config set spin=false\n  - npm install -g npm@4\n  - npm install -g coveralls\n\ninstall:\n  - npm install\n\nscript:\n  - npm test\n  - npm run coverage\n\nafter_script:\n  - coveralls < ./coverage/lcov.info || true # if coveralls doesn't have it covered\n\nbranches:\n    only:\n      - master\n\n# Allow Travis tests to run in containers.\nsudo: false\n\ndeploy:\n  provider: npm\n  email: tally.barak@gmail.com\n  api_key: $NPM_API_KEY\n  on:\n    tags: true\n    all_branches: true\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n\n        {\n            \"name\": \"Tests\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"program\": \"${workspaceRoot}/node_modules/jest-cli/bin/jest.js\",\n            \"stopOnEntry\": false,\n            \"args\": [\"--runInBand\"],\n            \"cwd\": \"${workspaceRoot}\",\n            \"runtimeExecutable\": null,\n            \"runtimeArgs\": [\n                \"--nolazy\"\n            ],\n            \"env\": {\n                \"NODE_ENV\": \"development\"\n            },\n            \"console\": \"internalConsole\",\n            \"sourceMaps\": true\n        },\n        {\n            \"name\": \"Launch\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"program\": \"${workspaceRoot}/server/server.js\",\n            \"stopOnEntry\": false,\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"preLaunchTask\": null,\n            \"outFiles\": [\"build\"],\n            \"runtimeExecutable\": null,\n            \"runtimeArgs\": [\n                \"--nolazy\"\n            ],\n            \"env\": {\n                \"NODE_ENV\": \"development\"\n            },\n            \"console\": \"internalConsole\",\n            \"sourceMaps\": true\n        },\n        {\n            \"name\": \"Attach\",\n            \"type\": \"node\",\n            \"request\": \"attach\",\n            \"port\": 5858,\n            \"address\": \"localhost\",\n            \"restart\": false,\n            \"sourceMaps\": false,\n            \"outFiles\": [\"dist\"],\n            \"localRoot\": \"${workspaceRoot}\",\n            \"remoteRoot\": null\n        },\n        {\n            \"name\": \"Attach to Process\",\n            \"type\": \"node\",\n            \"request\": \"attach\",\n            \"processId\": \"${command:PickProcess}\",\n            \"port\": 5858,\n            \"sourceMaps\": false,\n            \"outFiles\": [\"dist\"]\n        }\n    ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "// Place your settings in this file to overwrite default and user settings.\n{\n    \"search.exclude\": {\n        \"out\": true,\n        \"lib\": true\n    },\n    \"vsicons.presets.angular\": false\n}\n"
  },
  {
    "path": ".vscode/tasks.json",
    "content": ""
  },
  {
    "path": ".yo-rc.json",
    "content": "{\r\n  \"generator-loopback\": {}\r\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n\n<a name=\"0.13.0\"></a>\n# [0.13.0](https://github.com/tallyb/loopback-graphql/compare/v0.12.1...v0.13.0) (2017-05-19)\n\n\n### Bug Fixes\n\n* **app:** Packages upgrades ([c7cf2de](https://github.com/tallyb/loopback-graphql/commit/c7cf2de))\n* **resolvers:** Remove workaround. Closes [#44](https://github.com/tallyb/loopback-graphql/issues/44) ([758ebbf](https://github.com/tallyb/loopback-graphql/commit/758ebbf))\n\n\n\n<a name=\"0.12.1\"></a>\n## [0.12.1](https://github.com/tallyb/loopback-graphql/compare/v0.12.0...v0.12.1) (2017-04-30)\n\n\n### Bug Fixes\n\n* **github:** Remove github template ([353aadf](https://github.com/tallyb/loopback-graphql/commit/353aadf))\n* **package:** update graphql-server-express to version 0.7.0 ([#49](https://github.com/tallyb/loopback-graphql/issues/49)) ([36cf7b4](https://github.com/tallyb/loopback-graphql/commit/36cf7b4))\n\n\n\n<a name=\"0.12.0\"></a>\n# [0.12.0](https://github.com/tallyb/loopback-graphql/compare/v0.11.0...v0.12.0) (2017-04-01)\n\n\n### Features\n\n* **app:** Remove scalar types and use libs ([749b5ee](https://github.com/tallyb/loopback-graphql/commit/749b5ee))\n\n\n\n<a name=\"0.11.0\"></a>\n# [0.11.0](https://github.com/tallyb/loopback-graphql/compare/v0.10.0...v0.11.0) (2017-03-31)\n\n\n### Bug Fixes\n\n* **package:** update graphql-server-express to version 0.5.0 ([#24](https://github.com/tallyb/loopback-graphql/issues/24)) ([8f84b54](https://github.com/tallyb/loopback-graphql/commit/8f84b54))\n* **package:** update graphql-tools to version 0.10.0 ([#31](https://github.com/tallyb/loopback-graphql/issues/31)) ([398386e](https://github.com/tallyb/loopback-graphql/commit/398386e))\n* **package:** update graphql-tools to version 0.11.0 ([#46](https://github.com/tallyb/loopback-graphql/issues/46)) ([4991faa](https://github.com/tallyb/loopback-graphql/commit/4991faa))\n* **tests:** Fix partial tests ([e5eb2cd](https://github.com/tallyb/loopback-graphql/commit/e5eb2cd))\n\n\n### Features\n\n* **app:** Upgrade to loopback 3.0 ([5dfe8fb](https://github.com/tallyb/loopback-graphql/commit/5dfe8fb))\n\n\n\n<a name=\"0.10.0\"></a>\n# [0.10.0](https://github.com/tallyb/loopback-graphql/compare/v0.9.0...v0.10.0) (2017-01-06)\n\n\n### Bug Fixes\n\n* **app:** Fix models names ([c21f454](https://github.com/tallyb/loopback-graphql/commit/c21f454))\n* **app:** Fix wrong mixins ([93e8da7](https://github.com/tallyb/loopback-graphql/commit/93e8da7))\n* **package:** update graphql-tools to version 0.9.0 ([#21](https://github.com/tallyb/loopback-graphql/issues/21)) ([1f0f309](https://github.com/tallyb/loopback-graphql/commit/1f0f309))\n\n\n### Features\n\n* **app:** Adding request to context ([0a3163d](https://github.com/tallyb/loopback-graphql/commit/0a3163d))\n\n\n\n<a name=\"0.9.0\"></a>\n# [0.9.0](https://github.com/tallyb/loopback-graphql/compare/v0.8.0...v0.9.0) (2016-11-20)\n\n\n### Features\n\n* **app:** Support complex models ([82e479c](https://github.com/tallyb/loopback-graphql/commit/82e479c)), closes [#7](https://github.com/tallyb/loopback-graphql/issues/7)\n\n\n\n<a name=\"0.8.0\"></a>\n# [0.8.0](https://github.com/tallyb/loopback-graphql/compare/v0.7.0...v0.8.0) (2016-11-15)\n\n\n### Features\n\n* **app:** Resolvers with edges ([883e79d](https://github.com/tallyb/loopback-graphql/commit/883e79d))\n* **app:** Support paginations ([5ca2257](https://github.com/tallyb/loopback-graphql/commit/5ca2257))\n\n\n\n<a name=\"0.7.0\"></a>\n# [0.7.0](https://github.com/tallyb/loopback-graphql/compare/v0.6.0...v0.7.0) (2016-11-03)\n\n\n### Bug Fixes\n\n* **typedefs:** Include generated properties ([a10c444](https://github.com/tallyb/loopback-graphql/commit/a10c444))\n\n\n### Features\n\n* **app:** Fix hidden attributes ([8d5c8a0](https://github.com/tallyb/loopback-graphql/commit/8d5c8a0))\n\n\n\n<a name=\"0.6.0\"></a>\n# [0.6.0](https://github.com/tallyb/loopback-graphql/compare/v0.5.3...v0.6.0) (2016-10-18)\n\n\n### Features\n\n* **App:** Support aggregated types ([b057b3b](https://github.com/tallyb/loopback-graphql/commit/b057b3b)), closes [#1](https://github.com/tallyb/loopback-graphql/issues/1)\n\n\n\n<a name=\"0.5.3\"></a>\n## [0.5.3](https://github.com/tallyb/loopback-graphql/compare/v0.5.2...v0.5.3) (2016-10-16)\n\n\n### Bug Fixes\n\n* **App:** Error on ReferencesMany relationship ([81f0821](https://github.com/tallyb/loopback-graphql/commit/81f0821))\n\n\n\n<a name=\"0.5.1\"></a>\n## [0.5.1](https://github.com/tallyb/loopback-graphql/compare/v0.5.0...0.5.1) (2016-10-15)\n\n\n### Bug Fixes\n\n* **resolvers:** Fix resolving nested models ([c80b02d](https://github.com/tallyb/loopback-graphql/commit/c80b02d))\n\n\n\n<a name=\"0.5.0\"></a>\n# [0.5.0](https://github.com/tallyb/loopback-graphql/compare/v0.3.0...v0.5.0) (2016-10-14)\n\n\n### Features\n\n* **Query:** ID parameter to single object query ([83ab4c4](https://github.com/tallyb/loopback-graphql/commit/83ab4c4))\n\n\n\n<a name=\"0.3.0\"></a>\n# [0.3.0](https://github.com/tallyb/loopback-graphql/compare/v0.2.1...v0.3.0) (2016-10-12)\n\n\n### Bug Fixes\n\n* **app:** Fix relationships errors ([29716d1](https://github.com/tallyb/loopback-graphql/commit/29716d1))\n\n\n### Features\n\n* **app:** Add Delete Mutations ([e57dd20](https://github.com/tallyb/loopback-graphql/commit/e57dd20))\n* **app:** Publish scripts ([caa66bf](https://github.com/tallyb/loopback-graphql/commit/caa66bf))\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Guidelines for contributors\n\nIf you're unsure whether your pull request or feature is something that has a chance of being merged, just open an issue and ask away!\n\n\n## New contributors\n\nAre Welcome (no guidelines yet...)"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2017 Tally Barak\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "\n# Deprecation Warning: \nI have been very bad at maintaining this repo, and do not see how I come back to it in the near future.\nI have seen that this repo is a fork that moved forward: https://github.com/yahoohung/loopback-graphql-server/. \nIf anyone is willing to take maintaining this repo on themselves - you are welcome. \nThanks for all the feedback... \n\n### Status\n[![Build Status](https://travis-ci.org/Tallyb/loopback-graphql.svg?branch=master)](https://travis-ci.org/Tallyb/loopback-graphql)\n\n# GraphQL Server for Loopback (Apollo Server)\n\nCombine the powers of [ApolloStack](http://www.apollostack.com/) GraphQL with the backend of Loopback.\n<br>\nAll of Loopback models are exposed as GraphQL Queries.\n<br>\nDefine models in Loopback to be exposed as REST APIs and GraphQL queries and mutations *.\n<br>\nUse the Apollo [clients](http://dev.apollodata.com/) to access your data. \n\n![Loopback Graphql](./resources/loopback-graphql.png?raw=true \"LoopBack Apollo Architecture\") \n\n## Getting started\n\n```sh\nnpm install loopback-graphql\n```\nAdd the loopback-graphql component to the `server/component-config.json`: \n\n```\n\"loopback-graphql\": {\n    \"path\": \"/graphql\",\n    \"graphiqlPath\":\"/graphiql\"\n  }\n```\n\nRequests will be posted to `path` path. (Default: `/graphql`);\n\nGraphiql is available on `graphiqlPath` path. (Default: `/graphiql`);\n\n## Usage\n\nAccess the Graphiql interface to view your GraphQL model on the Docs section. \nBuild the GraphQL queries and use them in your application.\n\ngeoPoint objects are supported as follow: \n```\n{\"newNote\": \n  {\n    \"location\": {\"lat\":40.77492964101182, \"lng\":-73.90950187151662}\n  }\n}\n```\n\n## Roadmap\n[See here the Github project](https://github.com/Tallyb/loopback-graphql/projects/1)\n"
  },
  {
    "path": "__test__/data.json",
    "content": "{\n    \"ids\": {\n        \"User\": 3,\n        \"AccessToken\": 1,\n        \"ACL\": 1,\n        \"RoleMapping\": 1,\n        \"Role\": 1,\n        \"Note\": 7,\n        \"Author\": 6,\n        \"Reader\": 2,\n        \"Book\": 2,\n        \"Customer\": 8,\n        \"Address\": 1,\n        \"EmailAddress\": 1,\n        \"Account\": 3,\n        \"Order\": 6\n    },\n    \"models\": {\n        \"User\": {\n            \"1\": \"{\\\"username\\\":\\\"tally\\\",\\\"password\\\":\\\"$2a$10$b/Ok3FC3HYCbF2LlLXpk4OSsrz5EixJfkfJittHp8eEtPQvUJZiEa\\\",\\\"email\\\":\\\"tally@a.com\\\",\\\"id\\\":1}\",\n        },\n        \"AccessToken\": {},\n        \"ACL\": {},\n        \"RoleMapping\": {},\n        \"Role\": {},\n        \"Note\": {\n            \"1\": \"{\\\"title\\\":\\\"1st note\\\",\\\"id\\\":1}\",\n            \"2\": \"{\\\"title\\\":\\\"Who is Afraid\\\",\\\"Genre\\\":\\\"HUMOR\\\",\\\"authorId\\\":3,\\\"id\\\":2}\",\n            \"3\": \"{\\\"title\\\":\\\"A room with a View\\\",\\\"authorId\\\":3,\\\"id\\\":3}\",\n            \"4\": \"{\\\"title\\\":\\\"The Bluest Eye\\\",\\\"authorId\\\":5,\\\"id\\\":4}\",\n            \"5\": \"{\\\"title\\\":\\\"Of Mice and Men\\\",\\\"Genre\\\":\\\"HUMOR\\\",\\\"authorId\\\":4,\\\"id\\\":5}\",\n            \"6\": \"{\\\"title\\\":\\\"Love and Prejudice\\\",\\\"authorId\\\":8,\\\"Genre\\\":\\\"ROMANCE\\\",\\\"id\\\":6}\"\n        },\n        \"Author\": {\n            \"1\": \"{\\\"first_name\\\":\\\"Jane\\\",\\\"last_name\\\":\\\"Austin\\\",\\\"birth_date\\\":\\\"1883-10-15T00:00:00.000Z\\\",\\\"id\\\":8,\\\"friendIds\\\":[5,7]}\",\n            \"3\": \"{\\\"first_name\\\":\\\"Virginia\\\",\\\"last_name\\\":\\\"Wolf\\\",\\\"birth_date\\\":\\\"2017-06-30T07:36:32.666Z\\\",\\\"friendIds\\\":[],\\\"id\\\":3}\",\n        },\n        \"Reader\": {\n            \"1\": \"{\\\"name\\\":\\\"Reader 1\\\",\\\"id\\\":1}\"\n        },\n        \"Book\": {\n            \"1\": \"{\\\"name\\\":\\\"Book 1\\\",\\\"links\\\":[{\\\"id\\\":1,\\\"name\\\":\\\"Author 1\\\",\\\"notes\\\":\\\"Note 1\\\",\\\"linkedId\\\":1,\\\"linkedType\\\":\\\"Author\\\"},{\\\"id\\\":2,\\\"name\\\":\\\"Reader 1\\\",\\\"notes\\\":\\\"Note 2\\\",\\\"linkedId\\\":1,\\\"linkedType\\\":\\\"Reader\\\"}],\\\"id\\\":1}\"\n        },\n        \"Order\": {\n            \"1\": \"{\\\"date\\\":\\\"2014-12-31T18:30:00.000Z\\\",\\\"description\\\":\\\"First order by Customer A\\\",\\\"customerId\\\":1,\\\"id\\\":1}\",\n            \"2\": \"{\\\"date\\\":\\\"2015-01-31T18:30:00.000Z\\\",\\\"description\\\":\\\"Second order by Customer A\\\",\\\"customerId\\\":1,\\\"id\\\":2}\",\n            \"3\": \"{\\\"date\\\":\\\"2015-02-28T18:30:00.000Z\\\",\\\"description\\\":\\\"Order by Customer B\\\",\\\"customerId\\\":2,\\\"id\\\":3}\",\n            \"4\": \"{\\\"date\\\":\\\"2015-03-31T18:30:00.000Z\\\",\\\"description\\\":\\\"Order by Customer C\\\",\\\"customerId\\\":3,\\\"id\\\":4}\",\n            \"5\": \"{\\\"date\\\":\\\"2015-04-30T18:30:00.000Z\\\",\\\"description\\\":\\\"Order by Anonymous\\\",\\\"id\\\":5}\"\n        },\n        \"Customer\": {\n            \"1\": \"{\\\"name\\\":\\\"Customer A\\\",\\\"age\\\":21,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":1}\",\n            \"2\": \"{\\\"name\\\":\\\"Customer B\\\",\\\"age\\\":22,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":2}\",\n            \"3\": \"{\\\"name\\\":\\\"Customer C\\\",\\\"age\\\":23,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":3}\",\n            \"4\": \"{\\\"name\\\":\\\"Customer D\\\",\\\"age\\\":24,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":4}\",\n            \"5\": \"{\\\"name\\\":\\\"Mary Smith\\\",\\\"emailList\\\":[],\\\"accountIds\\\":[1,2],\\\"id\\\":5}\",\n            \"6\": \"{\\\"name\\\":\\\"John Smith\\\",\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":6,\\\"billingAddress\\\":{\\\"street\\\":\\\"123 A St\\\",\\\"city\\\":\\\"San Jose\\\",\\\"state\\\":\\\"CA\\\",\\\"zipCode\\\":\\\"95131\\\"}}\",\n            \"7\": \"{\\\"name\\\":\\\"Larry Smith\\\",\\\"emailList\\\":[{\\\"label\\\":\\\"home\\\",\\\"address\\\":\\\"larry@yahoo.com\\\",\\\"id\\\":2,\\\"name\\\":\\\"home\\\"}],\\\"accountIds\\\":[],\\\"id\\\":7}\"\n        },\n        \"Address\": {},\n        \"EmailAddress\": {},\n        \"Account\": {\n            \"1\": \"{\\\"name\\\":\\\"Checking\\\",\\\"balance\\\":5000,\\\"id\\\":1}\",\n            \"2\": \"{\\\"name\\\":\\\"Saving\\\",\\\"balance\\\":2000,\\\"id\\\":2}\"\n        }\n    }\n}\n"
  },
  {
    "path": "__test__/mutation.spec.ts",
    "content": "'use strict';\nimport { gqlRequest } from './testHelper';\nimport gql from 'graphql-tag';\n// var _ = require('lodash');\n\ndescribe('mutation', () => {\n\n  it('should add and Delete single entity', () => {\n    let id;\n    const createAuthor = gql`\n            mutation save ($obj: AuthorInput!) {\n                saveAuthor (obj: $obj) {\n                    first_name\n                    last_name\n                    birth_date\n                    id\n                }\n           }\n        `;\n    const authorInput = {\n      first_name: 'Virginia',\n      last_name: 'Wolf',\n      birth_date: new Date(),\n    };\n    const deleteAuthor = gql`\n            mutation delete ($id: ID!) {\n                deleteAuthor (id: $id) {\n                    text\n                }\n           }\n        `;\n\n    return gqlRequest(createAuthor, 200, {\n      obj: authorInput,\n    })\n      .then(res => {\n        id = res.body.data.saveAuthor.id;\n        return gqlRequest(deleteAuthor, 200, {\n          id: id,\n        });\n      });\n  });\n\n  it('should add a single entity with sub type', () => {\n    const body = 'Heckelbery Finn';\n    const query = gql`\n            mutation save ($obj: NoteInput!) {\n                saveNote (obj: $obj) {\n                    id\n                    title\n                    author {\n                        first_name\n                        last_name\n                    }\n\n                }\n           }\n        `;\n    const variables = {\n      obj: {\n        title: 'Heckelbery Finn',\n        content: {\n          body: body,\n          footer: 'The end',\n        },\n      },\n    };\n\n    return gqlRequest(query, 200, variables)\n      .then(res => {\n        expect(res.body.data.saveNote.title).toEqual(body);\n      });\n  });\n\n  describe('remote methods', () => {\n\n    const userInput = {\n      email: 'John@a.com',\n      password: '123456',\n      username: 'John@a.com',\n    };\n    const createUser = `\n          mutation userCreate ($obj: UserInput!) {\n            saveUser ( obj: $obj ) {\n              id\n            }\n          }\n        `;\n    const deleteUser = gql`\n            mutation delete ($id: ID!) {\n                deleteAuthor (id: $id) {\n                    text\n                }\n           }\n        `;\n    let userId;\n\n    beforeEach(() => {\n      return gqlRequest(createUser, 200, {\n        obj: userInput,\n      })\n        .then(res => {\n          userId = res.body.data.saveUser.id;\n        });\n    });\n\n    afterEach(() => {\n      return gqlRequest(deleteUser, 200, {\n        id: userId,\n      });\n    });\n    it.skip('should login and return an accessToken', () => {\n      const query = gql`\n          mutation login{\n            UserLogin(credentials:{username:\"John@a.com\", password:\"123456\"})\n          }\n        `;\n      return gqlRequest(query, 200)\n        .then(res => {\n          expect(res.body.data.UserLogin).toHaveProperty('id');\n        });\n    });\n\n  });\n\n});\n"
  },
  {
    "path": "__test__/pagination.spec.ts",
    "content": "'use strict';\nimport { gqlRequest } from './testHelper';\nimport gql from 'graphql-tag';\n// var _ = require('lodash');\n\ndescribe('Pagination', () => {\n\n\n  it('should query first 2 entities', () => {\n    const query = gql`{\n                    allNotes(first: 2) {\n                        totalCount\n                        pageInfo {\n                            hasNextPage\n                            hasPreviousPage\n                            startCursor\n                            endCursor\n                        }\n                        edges {\n                        node {\n                            title\n                            id\n                        }\n                        cursor\n                        }\n                    }\n                    }\n\n        `;\n    return gqlRequest(query, 200)\n      .then(res => {\n        let data: any = res.body.data;\n        expect(data.allNotes.edges.length).toBeGreaterThan(0);\n      });\n  });\n\n  it('should query entity after cursor', () => {\n    const query = gql`{\n            allNotes (after: \"Y29ubmVjdGlvbi40\", first: 3) {\n                pageInfo  {\n                    hasNextPage\n                    hasPreviousPage\n                    startCursor\n                    endCursor\n                }\n                edges {\n                node {\n                    id\n                    title\n                }\n                cursor\n                }\n            }\n        }`;\n    return gqlRequest(query, 200)\n      .then(res => {\n        let data: any = res.body.data;\n        expect(data.allNotes.edges.length).toBeGreaterThan(0);\n        expect(data.allNotes.edges[0].node.id).toBeGreaterThan(4);\n        expect(data.allNotes.pageInfo.hasPreviousPage).toEqual(true);\n      });\n  });\n\n  it('should query related entity on edge', () => {\n    const query = gql`{\n                allAuthors {\n                    pageInfo {\n                        hasNextPage\n                        hasPreviousPage\n                        startCursor\n                        endCursor\n                    }\n                    edges {\n                    node {\n                        id\n                        last_name\n                        notes {\n                        totalCount\n                        Notes {\n                            title\n                        }\n                        }\n                    }\n                    cursor\n                    }\n                }\n                }\n            `;\n    return gqlRequest(query, 200)\n      .then(res => {\n        let data: any = res.body.data;\n        expect(data.allAuthors.edges[0].node.notes.Notes.length).toBeGreaterThan(0);\n        expect(data.allAuthors.edges[0].node.notes.totalCount).toBeGreaterThan(0);\n        //data.allAuthors.edges[0].cursor.should.not.to.be.empty();\n      });\n  });\n\n});\n"
  },
  {
    "path": "__test__/query.spec.ts",
    "content": "'use strict';\nimport { gqlRequest } from './testHelper';\nimport gql from 'graphql-tag';\n\ndescribe('query', () => {\n\n  describe('Single entity', () => {\n    it('should execute a single query with relation', () => {\n      const query = gql`\n            query {\n              allOrders(first:1){\n                edges{\n                  node{\n                    date\n                    description\n                    customer{\n                      edges{\n                        node{\n                          name\n                          age\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }`;\n      return gqlRequest(query, 200, {})\n        .then(res => {\n          console.log('RES', res.body.data);\n          let data = res.body.data;\n          expect(data.allOrders.edges.length).toEqual(1);\n        });\n    });\n  });\n\n  describe('Multiple entities', () => {\n    it('should return response with where on id', () => {\n      const query = gql`\n                query users ($where:JSON){\n                  allUsers(where: $where) {\n                    totalCount\n                    edges {\n                      node {\n                        id\n                        email\n                      }\n                    }\n\n                  }\n      }`;\n      const variables = {\n        where: {\n          id: {\n            inq: [1, 2],\n          },\n        },\n      };\n      return gqlRequest(query, 200, variables)\n        .then(res => {\n          expect(res.body.data.allUsers.totalCount).toEqual(2);\n        });\n\n    });\n  });\n\n  describe('relationships', () => {\n    it('should query related entity with nested relational data', () => {\n      const query = gql`\n                query {\n                 allCustomers(first:2){\n                   edges{\n                     node{\n                       name\n                       age\n                       orders{\n                         edges{\n                           node{\n                             date\n                             description\n                             customer{\n                               edges{\n                                 node{\n                                   name\n                                   age\n                                 }\n                               }\n                             }\n                           }\n                         }\n                       }\n                     }\n                   }\n                 }\n               }\n            `;\n      return gqlRequest(query, 200, {})\n        .then(res => {\n          expect(res.body.data.allCustomers.edges.length).toEqual(2);\n        });\n    });\n  });\n\n});\n"
  },
  {
    "path": "__test__/testHelper.ts",
    "content": "'use strict';\n\nimport request from 'supertest';\nimport app from '../server/server.js';\n\nexport function gqlRequest(query: any, status: number, variables?: object) {\n\n  return request(app)\n    .post('/graphql')\n    .send({\n      query,\n      variables,\n    })\n    .expect(status);\n}\n"
  },
  {
    "path": "client/README.md",
    "content": "## Client\n\nThis is the place for your application front-end files.\n"
  },
  {
    "path": "common/models/account.js",
    "content": "// Copyright IBM Corp. 2015. All Rights Reserved.\n// Node module: loopback-example-relations\n// This file is licensed under the MIT License.\n// License text available at https://opensource.org/licenses/MIT\n'use strict';\n\nmodule.exports = function(Account) {\n\n};\n"
  },
  {
    "path": "common/models/account.json",
    "content": "{\n  \"name\": \"Account\",\n  \"base\": \"PersistedModel\",\n  \"idInjection\": true,\n  \"properties\": {\n    \"name\": {\n      \"type\": \"string\"\n    },\n    \"balance\": {\n      \"type\": \"number\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {},\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/address.js",
    "content": "// Copyright IBM Corp. 2015. All Rights Reserved.\n// Node module: loopback-example-relations\n// This file is licensed under the MIT License.\n// License text available at https://opensource.org/licenses/MIT\n'use strict';\n\nmodule.exports = function(Address) {\n\n};\n"
  },
  {
    "path": "common/models/address.json",
    "content": "{\n  \"name\": \"Address\",\n  \"base\": \"Model\",\n  \"idInjection\": true,\n  \"properties\": {\n    \"street\": {\n      \"type\": \"string\"\n    },\n    \"city\": {\n      \"type\": \"string\"\n    },\n    \"state\": {\n      \"type\": \"string\"\n    },\n    \"zipCode\": {\n      \"type\": \"string\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {},\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/author.js",
    "content": "'use strict';\n\nmodule.exports = function(Author) {\n\n    Author.remoteMethod(\n        'addFriend', {\n            'http': {\n                'path': '/addFriend',\n                'verb': 'post'\n            },\n\n            'accepts': [{\n                'arg': 'author',\n                'type': 'number'\n            }, {\n                'arg': 'friend',\n                'type': ['number']\n            }],\n\n            'returns': {\n                'arg': 'result',\n                'type': 'object'\n            }\n        }\n    );\n\n    Author.addFriend = function(author, friend) {\n\n        return Author.findById(author)\n            .then(res => {\n                let updated = res;\n                updated.friendIds.push(friend);\n                return updated.save();\n            }).then(res => {});\n    };\n};"
  },
  {
    "path": "common/models/author.json",
    "content": "{\n    \"name\": \"Author\",\n    \"plural\": \"Authors\",\n    \"base\": \"PersistedModel\",\n    \"idInjection\": true,\n    \"options\": {\n        \"validateUpsert\": true\n    },\n    \"properties\": {\n        \"first_name\": {\n            \"type\": \"string\",\n            \"required\": true\n        },\n        \"last_name\": {\n            \"type\": \"string\",\n            \"required\": true\n        },\n\n        \"birth_date\": {\n            \"type\": \"date\",\n            \"required\": true\n        },\n        \"user\": {\n            \"type\": \"User\",\n            \"required\": false\n        },\n        \"dream\": \"Object\"\n    },\n    \"validations\": [],\n    \"relations\": {\n        \"notes\": {\n            \"type\": \"hasMany\",\n            \"model\": \"Note\",\n            \"foreignKey\": \"\"\n        },\n        \"friends\": {\n            \"type\": \"referencesMany\",\n            \"model\": \"Author\",\n            \"foreignKey\": \"friendIds\"\n        },\n        \"others\": {\n            \"type\": \"hasMany\",\n            \"model\": \"Author\"\n        }\n    },\n    \"acls\": [],\n    \"methods\": {}\n}"
  },
  {
    "path": "common/models/book.json",
    "content": "{\n  \"name\": \"Book\",\n  \"base\": \"PersistedModel\",\n  \"idInjection\": true,\n  \"properties\": {\n    \"name\": {\n      \"type\": \"string\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {\n    \"people\": {\n      \"type\": \"embedsMany\",\n      \"model\": \"Link\",\n      \"scope\": {\n        \"include\": \"linked\"\n      }\n    }\n  },\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/catalogs.js",
    "content": "'use strict';\n\nmodule.exports = function(Catalogs) {\n\n};"
  },
  {
    "path": "common/models/catalogs.json",
    "content": "{\n    \"name\": \"catalogs\",\n    \"base\": \"PersistedModel\",\n    \"idInjection\": true,\n    \"options\": {\n        \"validateUpsert\": true\n    },\n    \"properties\": {\n        \"_id\": {\n            \"type\": \"string\",\n            \"generated\": true,\n            \"id\": true\n        }\n    },\n    \"validations\": [],\n    \"relations\": {\n        \"products\": {\n            \"type\": \"hasMany\",\n            \"model\": \"products\",\n            \"foreignKey\": \"catalogRef\"\n        }\n    },\n    \"acls\": [{\n        \"accessType\": \"*\",\n        \"principalType\": \"ROLE\",\n        \"principalId\": \"$everyone\",\n        \"permission\": \"DENY\"\n    }, {\n        \"accessType\": \"*\",\n        \"principalType\": \"ROLE\",\n        \"principalId\": \"$authenticated\",\n        \"permission\": \"ALLOW\"\n    }],\n    \"indexes\": {\n        \"catalogRef_1\": {\n            \"catalogRef\": 1\n        }\n    },\n    \"methods\": [],\n    \"permissions\": \"private\",\n    \"mixins\": {}\n}"
  },
  {
    "path": "common/models/customer.js",
    "content": "// Copyright IBM Corp. 2015. All Rights Reserved.\n// Node module: loopback-example-relations\n// This file is licensed under the MIT License.\n// License text available at https://opensource.org/licenses/MIT\n'use strict';\n\nmodule.exports = function(Customer) {\n\n};\n"
  },
  {
    "path": "common/models/customer.json",
    "content": "{\n  \"name\": \"Customer\",\n  \"base\": \"PersistedModel\",\n  \"idInjection\": true,\n  \"properties\": {\n    \"name\": {\n      \"type\": \"string\"\n    },\n    \"age\": {\n      \"type\": \"number\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {\n    \"address\": {\n      \"type\": \"embedsOne\",\n      \"model\": \"Address\",\n      \"property\": \"billingAddress\",\n      \"options\": {\n        \"validate\": true,\n        \"forceId\": false\n      }\n    },\n    \"emails\": {\n      \"type\": \"embedsMany\",\n      \"model\": \"EmailAddress\",\n      \"property\": \"emailList\",\n      \"options\": {\n        \"validate\": true,\n        \"forceId\": false\n      }\n    },\n    \"accounts\": {\n      \"type\": \"referencesMany\",\n      \"model\": \"Account\",\n      \"foreignKey\": \"accountIds\",\n      \"options\": {\n        \"validate\": true,\n        \"forceId\": false\n      }\n    },\n    \"orders\": {\n      \"type\": \"hasMany\",\n      \"model\": \"Order\",\n      \"foreignKey\": \"id\"\n    }\n  },\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/email-address.js",
    "content": "// Copyright IBM Corp. 2015. All Rights Reserved.\n// Node module: loopback-example-relations\n// This file is licensed under the MIT License.\n// License text available at https://opensource.org/licenses/MIT\n'use strict';\n\nmodule.exports = function(EmailAddress) {\n\n};\n"
  },
  {
    "path": "common/models/email-address.json",
    "content": "{\n  \"name\": \"EmailAddress\",\n  \"base\": \"Model\",\n  \"idInjection\": true,\n  \"properties\": {\n    \"label\": {\n      \"type\": \"string\"\n    },\n    \"address\": {\n      \"type\": \"string\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {},\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/googlemaps.js",
    "content": "'use strict';\n\nmodule.exports = function(Googlemaps) {};"
  },
  {
    "path": "common/models/googlemaps.json",
    "content": "{\n    \"name\": \"Googlemaps\",\n    \"plural\": \"Googlemaps\",\n    \"base\": \"PersistedModel\",\n    \"idInjection\": false,\n    \"options\": {\n        \"validateUpsert\": true\n    },\n    \"properties\": {\n        \"id\": {\n            \"type\": \"string\",\n            \"description\": \"contains a unique stable identifier denoting this place. This identifier may not be used to retrieve information about this place, but is guaranteed to be valid across sessions. It can be used to consolidate data about this place, and to verify the identity of a place across separate searches. **Note**: The `id` is now deprecated in favor of `place_id`.\"\n        },\n        \"geometry\": {\n            \"type\": {\n                \"location\": {\n                    \"lat\": \"number\",\n                    \"lng\": \"number\"\n                },\n                \"viewport\": {\n                    \"northeast\": {\n                        \"lat\": \"number\",\n                        \"lng\": \"number\"\n                    },\n                    \"southwest\": {\n                        \"lat\": \"number\",\n                        \"lng\": \"number\"\n                    }\n                }\n            },\n            \"description\": \"contains geometry information about the result, generally including the `location` (geocode) of the place and (optionally) the `viewport` identifying its general area of coverage.\"\n        },\n        \"photos\": {\n            \"description\": \"an array of `photo` objects, each containing a reference to an image. A Place Search will return at most one `photo` object. Performing a Place Details request on the place may return up to ten photos. More information about Place Photos and how you can use the images in your application can be found in the [Place Photos](https://developers.google.com/places/web-service/photos) documentation.\",\n            \"type\": [{\n                \"photo_reference\": {\n                    \"type\": \"string\",\n                    \"description\": \" a string used to identify the photo when you perform a Photo request.\"\n                },\n                \"height\": {\n                    \"type\": \"number\",\n                    \"description\": \" the maximum height of the image.\"\n                },\n                \"width\": {\n                    \"type\": \"number\",\n                    \"description\": \" the maximum width of the image.\"\n                },\n                \"html_attributions\": {\n                    \"type\": [\"string\"],\n                    \"description\": \"contains any required attributions. This field will always be present, but may be empty.\"\n                }\n            }]\n        },\n        \"scope\": {\n            \"type\": \"string\",\n            \"description\": [\n                \"Indicates the scope of the `place_id`. The possible values are:\", \" * `APP`: The place ID is recognised by your application only. This is because your application added the place, and the place has not yet passed the moderation process.\", \" * `GOOGLE`: The place ID is available to other applications and on Google Maps.\", \"**Note**: The `scope` field is included only in Nearby Search results and Place Details results. You can only retrieve app-scoped places via the Nearby Search and the Place Details requests. If the `scope` field is not present in a response, it is safe to assume the scope is `GOOGLE`.\"\n            ]\n        },\n        \"alt_ids\": {\n            \"type\": {\n                \"place_id\": {\n                    \"type\": \"string\",\n                    \"description\": \"The most likely reason for a place to have an alternative place ID is if your application adds a place and receives an application-scoped place ID, then later receives a Google-scoped place ID after passing the moderation process.\"\n                },\n                \"scope\": {\n                    \"type\": \"string\",\n                    \"description\": \"The scope of an alternative place ID will always be APP, indicating that the alternative place ID is recognised by your application only.\"\n                }\n            },\n            \"description\": [\"An array of zero, one or more alternative place IDs for the place, with a scope related to each alternative ID. Note: This array may be empty or not present.\", \"For example, let's assume your application adds a place and receives a `place_id` of `AAA` for the new place. Later, the place passes the moderation process and receives a Google-scoped `place_id` of `BBB`. From this point on, the information for this place will contain:\", \"```\", \"\\\"results\\\" : [\", \"      {\", \"        \\\"place_id\\\" : \\\"BBB\\\",\", \"        \\\"scope\\\" : \\\"GOOGLE\\\",\", \"        \\\"alt_ids\\\" : [\", \"          {\", \"            \\\"place_id\\\" : \\\"AAA\\\",\", \"            \\\"scope\\\" : \\\"APP\\\",\", \"          }\", \"        ],\", \"      }\", \"    ]\", \"```\"]\n        }\n    },\n    \"validations\": [],\n    \"relations\": {},\n    \"acls\": [],\n    \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/link.json",
    "content": "{\n  \"name\": \"Link\",\n  \"base\": \"Model\",\n  \"idInjection\": true,\n  \"properties\": {\n    \"id\": {\n      \"type\": \"number\",\n      \"id\": true\n    },\n    \"name\": {\n      \"type\": \"string\"\n    },\n    \"notes\": {\n      \"type\": \"string\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {\n    \"linked\": {\n      \"type\": \"belongsTo\",\n      \"polymorphic\": {\n        \"idType\": \"number\"\n      },\n      \"properties\": {\n        \"name\": \"name\"\n      },\n      \"options\": {\n        \"invertProperties\": true\n      }\n    }\n  },\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/note.js",
    "content": "'use strict';\n\nmodule.exports = function(Note) {\n\n    Note.clear = () => {\n        return {\n            note: {\n                Content: ''\n            },\n            previousClear: new Date()\n        };\n    };\n\n    Note.remoteMethod(\n        'clear', {\n            'http': {\n                'path': '/clear',\n                'verb': 'post'\n            },\n            'returns': [{\n                'arg': 'note',\n                'type': 'object'\n            }, {\n                'arg': 'previousClear',\n                'type': 'Date'\n            }]\n        });\n};"
  },
  {
    "path": "common/models/note.json",
    "content": "{\n    \"name\": \"Note\",\n    \"properties\": {\n        \"title\": {\n            \"type\": \"string\",\n            \"required\": true\n        },\n        \"content\": {\n            \"type\": \"Content\"\n        },\n        \"Genre\": {\n            \"type\": \"string\",\n            \"required\": false,\n            \"enum\": [\n                \"HUMOR\",\n                \"SCI_FI\",\n                \"HORROR\",\n                \"ROMANCE\",\n                \"NON_FICTION\"\n            ]\n        },\n        \"location\": {\n            \"type\": \"GeoPoint\"\n        }\n    },\n    \"validations\": [],\n    \"relations\": {\n        \"author\": {\n            \"type\": \"belongsTo\",\n            \"model\": \"Author\",\n            \"foreignKey\": \"\"\n        }\n    },\n    \"acls\": [],\n    \"methods\": {\n        \"prototype.vote\": {\n            \"accepts\": [{\n                \"arg\": \"rank\",\n                \"type\": \"number\",\n                \"required\": true,\n                \"description\": \"\"\n            }],\n            \"returns\": [],\n            \"description\": \" vote  a note\",\n            \"http\": [{\n                \"path\": \"vote\",\n                \"verb\": \"post\"\n            }]\n        }\n    }\n}\n"
  },
  {
    "path": "common/models/order.js",
    "content": "// Copyright IBM Corp. 2015. All Rights Reserved.\n// Node module: loopback-example-relations\n// This file is licensed under the MIT License.\n// License text available at https://opensource.org/licenses/MIT\n'use strict';\n\nmodule.exports = function(Order) {\n\n};\n"
  },
  {
    "path": "common/models/order.json",
    "content": "{\n  \"name\": \"Order\",\n  \"base\": \"PersistedModel\",\n  \"idInjection\": true,\n  \"options\": {\n    \"validateUpsert\": true\n  },\n  \"properties\": {\n    \"date\": {\n      \"type\": \"date\"\n    },\n    \"description\": {\n      \"type\": \"string\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {\n    \"customer\": {\n      \"type\": \"hasOne\",\n      \"model\": \"Customer\",\n      \"foreignKey\": \"id\"\n    }\n  },\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/models/products.js",
    "content": "'use strict';\n\nmodule.exports = function(Products) {\n\n};"
  },
  {
    "path": "common/models/products.json",
    "content": "{\n    \"name\": \"products\",\n    \"base\": \"PersistedModel\",\n    \"idInjection\": true,\n    \"options\": {\n        \"validateUpsert\": true\n    },\n    \"properties\": {\n        \"_id\": {\n            \"type\": \"string\",\n            \"generated\": true,\n            \"id\": true\n        }\n    },\n    \"validations\": [],\n    \"relations\": {\n        \"catalog\": {\n            \"type\": \"belongsTo\",\n            \"model\": \"catalogs\",\n            \"foreignKey\": \"catalogRef\"\n        }\n    },\n    \"acls\": [{\n        \"accessType\": \"*\",\n        \"principalType\": \"ROLE\",\n        \"principalId\": \"$everyone\",\n        \"permission\": \"DENY\"\n    }, {\n        \"accessType\": \"*\",\n        \"principalType\": \"ROLE\",\n        \"principalId\": \"$authenticated\",\n        \"permission\": \"ALLOW\"\n    }],\n    \"indexes\": {\n        \"catalogRef_1\": {\n            \"catalogRef\": 1\n        }\n    },\n    \"methods\": [],\n    \"permissions\": \"private\",\n    \"mixins\": {}\n}"
  },
  {
    "path": "common/models/reader.json",
    "content": "{\n  \"name\": \"Reader\",\n  \"base\": \"PersistedModel\",\n  \"idInjection\": true,\n  \"properties\": {\n    \"name\": {\n      \"type\": \"string\"\n    }\n  },\n  \"validations\": [],\n  \"relations\": {},\n  \"acls\": [],\n  \"methods\": {}\n}\n"
  },
  {
    "path": "common/types/content.json",
    "content": "{\n    \"name\": \"Content\",\n    \"plural\": \"Content\",\n    \"base\": \"Model\",\n    \"idInjection\": false,\n    \"options\": {\n        \"validateUpsert\": true\n    },\n    \"properties\": {\n        \"title\": {\n            \"type\": \"string\"\n        },\n        \"body\": {\n            \"type\": \"string\"\n        },\n        \"footer\": {\n            \"type\": \"string\"\n        }\n    },\n    \"validations\": [],\n    \"relations\": {},\n    \"acls\": [],\n    \"methods\": {}\n\n}"
  },
  {
    "path": "data.json",
    "content": "{\n  \"ids\": {\n    \"User\": 1,\n    \"AccessToken\": 1,\n    \"ACL\": 1,\n    \"RoleMapping\": 1,\n    \"Role\": 1,\n    \"Customer\": 1,\n    \"Account\": 1,\n    \"Author\": 6,\n    \"Reader\": 1,\n    \"Book\": 1,\n    \"Order\": 1,\n    \"Note\": 1,\n    \"Googlemaps\": 1,\n    \"products\": 1,\n    \"catalogs\": 1\n  },\n  \"models\": {\n    \"User\": {},\n    \"AccessToken\": {},\n    \"ACL\": {},\n    \"RoleMapping\": {},\n    \"Role\": {},\n    \"Customer\": {},\n    \"Account\": {},\n    \"Author\": {\n      \"1\": \"{\\\"first_name\\\":\\\"Virginia\\\",\\\"last_name\\\":\\\"Wolf\\\",\\\"birth_date\\\":\\\"2017-06-30T07:47:24.747Z\\\",\\\"friendIds\\\":[],\\\"id\\\":1}\",\n      \"2\": \"{\\\"first_name\\\":\\\"Virginia\\\",\\\"last_name\\\":\\\"Wolf\\\",\\\"birth_date\\\":\\\"2017-06-30T07:49:23.893Z\\\",\\\"friendIds\\\":[],\\\"id\\\":2}\",\n      \"3\": \"{\\\"first_name\\\":\\\"Virginia\\\",\\\"last_name\\\":\\\"Wolf\\\",\\\"birth_date\\\":\\\"2017-06-30T09:43:37.721Z\\\",\\\"friendIds\\\":[],\\\"id\\\":3}\",\n      \"4\": \"{\\\"first_name\\\":\\\"Virginia\\\",\\\"last_name\\\":\\\"Wolf\\\",\\\"birth_date\\\":\\\"2017-07-08T05:38:45.056Z\\\",\\\"friendIds\\\":[],\\\"id\\\":4}\",\n      \"5\": \"{\\\"first_name\\\":\\\"Virginia\\\",\\\"last_name\\\":\\\"Wolf\\\",\\\"birth_date\\\":\\\"2017-09-23T04:09:57.126Z\\\",\\\"friendIds\\\":[],\\\"id\\\":5}\"\n    },\n    \"Reader\": {},\n    \"Book\": {},\n    \"Order\": {},\n    \"Note\": {},\n    \"Googlemaps\": {},\n    \"products\": {},\n    \"catalogs\": {}\n  }\n}"
  },
  {
    "path": "jsconfig.json",
    "content": "{\r\n\t// See https://go.microsoft.com/fwlink/?LinkId=759670\r\n\t// for the documentation about the jsconfig.json format\r\n\t\"compilerOptions\": {\r\n\t\t\"target\": \"es6\",\r\n\t\t\"module\": \"commonjs\",\r\n\t\t\"allowSyntheticDefaultImports\": true\r\n\t},\r\n\t\"exclude\": [\r\n\t\t\"node_modules\",\r\n\t\t\"bower_components\",\r\n\t\t\"jspm_packages\",\r\n\t\t\"tmp\",\r\n\t\t\"temp\"\r\n\t],\r\n\t\"env\": {\r\n        \"node\": true\r\n    }\r\n}\r\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"loopback-graphql\",\n    \"version\": \"0.13.0\",\n    \"description\": \"Add Apollo Server or GraphQL queries on your Loopback server\",\n    \"main\": \"build/src/index.js\",\n    \"directories\": {\n        \"test\": \"test\"\n    },\n    \"types\": \"build/index\",\n    \"scripts\": {\n        \"clean\": \"rimraf coverage build tmp\",\n        \"build\": \"tsc -p tsconfig.release.json\",\n        \"lint\": \"tslint -t stylish '{src,__tests__}/**/*.{ts,tsx}'\",\n        \"pretest\": \"npm run lint  && npm run copydata\",\n        \"test\": \"npm run test:only\",\n        \"test:only\": \"jest --coverage\",\n        \"test:watch\": \"jest --watch\",\n        \"copydata\": \"cpx ./__test__/data.json ./server/\",\n        \"test:notify\": \"npm run test:watch -- --notify\",\n        \"test:co\": \"npm run test -- --runInBand\",\n        \"coverage\": \"npm test -- --coverage\",\n        \"coverage:notify\": \"npm run coverage -- --watch --notify\",\n        \"start\": \"npm run build && node server/server.js\",\n        \"start:watch\": \"concurrently \\\"npm run build:watch\\\" \\\"node-dev server/server.js\\\"\",\n        \"prerelease\": \"npm test\",\n        \"release\": \"standard-version\"\n    },\n    \"repository\": {\n        \"url\": \"git+https://github.com/tallyb/loopback-graphql.git\",\n        \"type\": \"git\"\n    },\n    \"keywords\": [\n        \"Loopback\",\n        \"GraphQL\",\n        \"Apollo\",\n        \"Express\",\n        \"Javascript\",\n        \"REST\",\n        \"APIs\"\n    ],\n    \"author\": \"Tally Barak <tally.barak@gmail.com>\",\n    \"license\": \"MIT\",\n    \"bugs\": {\n        \"url\": \"https://github.com/tallyb/loopback-graphql/issues\"\n    },\n    \"homepage\": \"https://github.com/tallyb/loopback-graphql#readme\",\n    \"dependencies\": {\n        \"body-parser\": \"^1.17.2\",\n        \"graphql\": \"^0.12.0\",\n        \"graphql-date\": \"^1.0.3\",\n        \"graphql-geojson\": \"^1.0.0\",\n        \"graphql-server-express\": \"^1.0.0\",\n        \"graphql-tools\": \"^3.0.0\",\n        \"graphql-type-json\": \"^0.2.0\",\n        \"lodash\": \"^4.17.4\"\n    },\n    \"devDependencies\": {\n        \"@types/jest\": \"22.0.0\",\n        \"@types/graphql\": \"^0.13.4\",\n        \"@types/jest\": \"^21.1.0\",\n        \"@types/lodash\": \"^4.14.66\",\n        \"@types/request\": \"2.0.7\",\n        \"@types/node\": \"^10.5.5\",\n        \"@types/request-promise\": \"^4.1.33\",\n        \"@types/supertest\": \"^2.0.1\",\n        \"@types/uuid\": \"^3.0.0\",\n        \"awesome-typescript-loader\": \"^5.0.0\",\n        \"compression\": \"^1.6.2\",\n        \"concurrently\": \"^3.4.0\",\n        \"cors\": \"^2.8.3\",\n        \"cpx\": \"^1.5.0\",\n        \"eslint\": \"^5.0.0\",\n        \"express\": \"^4.15.3\",\n        \"ghooks\": \"^2.0.0\",\n        \"graphql-tag\": \"^2.3.0\",\n        \"helmet\": \"^3.6.1\",\n        \"jest-cli\": \"^22.0.0\",\n        \"jest\": \"^22.0.0\",\n        \"loopback\": \"^3.8.0\",\n        \"loopback-boot\": \"^2.24.1\",\n        \"loopback-component-explorer\": \"^6.0.0\",\n        \"loopback-datasource-juggler\": \"^3.9.1\",\n        \"node-dev\": \"^3.1.3\",\n        \"nsp\": \"^3.0.0\",\n        \"request\": \"^2.81.0\",\n        \"rimraf\": \"^2.6.1\",\n        \"serve-favicon\": \"^2.4.3\",\n        \"standard-version\": \"^4.2.0\",\n        \"strong-error-handler\": \"^3.0.0\",\n        \"supertest\": \"^3.0.0\",\n        \"ts-jest\": \"^23.1.0\",\n        \"tslint\": \"^5.4.3\",\n        \"typescript\": \"^2.4.0\"\n    },\n    \"jest\": {\n        \"transform\": {\n            \".(ts|tsx)\": \"<rootDir>/node_modules/ts-jest/preprocessor.js\"\n        },\n        \"mapCoverage\": true,\n        \"testEnvironment\": \"node\",\n        \"testRegex\": \".*\\\\.spec\\\\.ts$\",\n        \"moduleFileExtensions\": [\n            \"ts\",\n            \"js\",\n            \"json\"\n        ],\n        \"globals\": {\n            \"__DEV__\": true,\n            \"ts-jest\": {\n                \"tsConfigFile\": \"tsconfig.test.json\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "server/boot/authentication.js",
    "content": "// Copyright IBM Corp. 2015. All Rights Reserved.\n// Node module: loopback-example-relations\n// This file is licensed under the MIT License.\n// License text available at https://opensource.org/licenses/MIT\n'use strict';\n\nmodule.exports = function enableAuthentication(server) {\n  // enable authentication\n};\n"
  },
  {
    "path": "server/boot/root.js",
    "content": "// Copyright IBM Corp. 2015. All Rights Reserved.\n// Node module: loopback-example-relations\n// This file is licensed under the MIT License.\n// License text available at https://opensource.org/licenses/MIT\n'use strict';\n\nmodule.exports = function(app) {\n\n};\n"
  },
  {
    "path": "server/component-config.json",
    "content": "{\n    \"loopback-component-explorer\": {\n        \"mountPath\": \"/explorer\"\n    },\n    \"../build/index.js\": {}\n}\n"
  },
  {
    "path": "server/config.json",
    "content": "{\n  \"restApiRoot\": \"/api\",\n  \"host\": \"0.0.0.0\",\n  \"port\": 3000,\n  \"remoting\": {\n    \"context\": false,\n    \"rest\": {\n      \"normalizeHttpPath\": false,\n      \"xml\": false\n    },\n    \"json\": {\n      \"strict\": false,\n      \"limit\": \"100kb\"\n    },\n    \"urlencoded\": {\n      \"extended\": true,\n      \"limit\": \"100kb\"\n    },\n    \"cors\": false,\n    \"handleErrors\": false\n  },\n  \"legacyExplorer\": false\n}\n"
  },
  {
    "path": "server/data.json",
    "content": "{\n    \"ids\": {\n        \"User\": 3,\n        \"AccessToken\": 1,\n        \"ACL\": 1,\n        \"RoleMapping\": 1,\n        \"Role\": 1,\n        \"Note\": 7,\n        \"Author\": 6,\n        \"Reader\": 2,\n        \"Book\": 2,\n        \"Customer\": 8,\n        \"Address\": 1,\n        \"EmailAddress\": 1,\n        \"Account\": 3,\n        \"Order\": 6\n    },\n    \"models\": {\n        \"User\": {\n            \"1\": \"{\\\"username\\\":\\\"tally\\\",\\\"password\\\":\\\"$2a$10$b/Ok3FC3HYCbF2LlLXpk4OSsrz5EixJfkfJittHp8eEtPQvUJZiEa\\\",\\\"email\\\":\\\"tally@a.com\\\",\\\"id\\\":1}\",\n        },\n        \"AccessToken\": {},\n        \"ACL\": {},\n        \"RoleMapping\": {},\n        \"Role\": {},\n        \"Note\": {\n            \"1\": \"{\\\"title\\\":\\\"1st note\\\",\\\"id\\\":1}\",\n            \"2\": \"{\\\"title\\\":\\\"Who is Afraid\\\",\\\"Genre\\\":\\\"HUMOR\\\",\\\"authorId\\\":3,\\\"id\\\":2}\",\n            \"3\": \"{\\\"title\\\":\\\"A room with a View\\\",\\\"authorId\\\":3,\\\"id\\\":3}\",\n            \"4\": \"{\\\"title\\\":\\\"The Bluest Eye\\\",\\\"authorId\\\":5,\\\"id\\\":4}\",\n            \"5\": \"{\\\"title\\\":\\\"Of Mice and Men\\\",\\\"Genre\\\":\\\"HUMOR\\\",\\\"authorId\\\":4,\\\"id\\\":5}\",\n            \"6\": \"{\\\"title\\\":\\\"Love and Prejudice\\\",\\\"authorId\\\":8,\\\"Genre\\\":\\\"ROMANCE\\\",\\\"id\\\":6}\"\n        },\n        \"Author\": {\n            \"1\": \"{\\\"first_name\\\":\\\"Jane\\\",\\\"last_name\\\":\\\"Austin\\\",\\\"birth_date\\\":\\\"1883-10-15T00:00:00.000Z\\\",\\\"id\\\":8,\\\"friendIds\\\":[5,7]}\",\n            \"3\": \"{\\\"first_name\\\":\\\"Virginia\\\",\\\"last_name\\\":\\\"Wolf\\\",\\\"birth_date\\\":\\\"2017-06-30T07:36:32.666Z\\\",\\\"friendIds\\\":[],\\\"id\\\":3}\",\n        },\n        \"Reader\": {\n            \"1\": \"{\\\"name\\\":\\\"Reader 1\\\",\\\"id\\\":1}\"\n        },\n        \"Book\": {\n            \"1\": \"{\\\"name\\\":\\\"Book 1\\\",\\\"links\\\":[{\\\"id\\\":1,\\\"name\\\":\\\"Author 1\\\",\\\"notes\\\":\\\"Note 1\\\",\\\"linkedId\\\":1,\\\"linkedType\\\":\\\"Author\\\"},{\\\"id\\\":2,\\\"name\\\":\\\"Reader 1\\\",\\\"notes\\\":\\\"Note 2\\\",\\\"linkedId\\\":1,\\\"linkedType\\\":\\\"Reader\\\"}],\\\"id\\\":1}\"\n        },\n        \"Order\": {\n            \"1\": \"{\\\"date\\\":\\\"2014-12-31T18:30:00.000Z\\\",\\\"description\\\":\\\"First order by Customer A\\\",\\\"customerId\\\":1,\\\"id\\\":1}\",\n            \"2\": \"{\\\"date\\\":\\\"2015-01-31T18:30:00.000Z\\\",\\\"description\\\":\\\"Second order by Customer A\\\",\\\"customerId\\\":1,\\\"id\\\":2}\",\n            \"3\": \"{\\\"date\\\":\\\"2015-02-28T18:30:00.000Z\\\",\\\"description\\\":\\\"Order by Customer B\\\",\\\"customerId\\\":2,\\\"id\\\":3}\",\n            \"4\": \"{\\\"date\\\":\\\"2015-03-31T18:30:00.000Z\\\",\\\"description\\\":\\\"Order by Customer C\\\",\\\"customerId\\\":3,\\\"id\\\":4}\",\n            \"5\": \"{\\\"date\\\":\\\"2015-04-30T18:30:00.000Z\\\",\\\"description\\\":\\\"Order by Anonymous\\\",\\\"id\\\":5}\"\n        },\n        \"Customer\": {\n            \"1\": \"{\\\"name\\\":\\\"Customer A\\\",\\\"age\\\":21,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":1}\",\n            \"2\": \"{\\\"name\\\":\\\"Customer B\\\",\\\"age\\\":22,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":2}\",\n            \"3\": \"{\\\"name\\\":\\\"Customer C\\\",\\\"age\\\":23,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":3}\",\n            \"4\": \"{\\\"name\\\":\\\"Customer D\\\",\\\"age\\\":24,\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":4}\",\n            \"5\": \"{\\\"name\\\":\\\"Mary Smith\\\",\\\"emailList\\\":[],\\\"accountIds\\\":[1,2],\\\"id\\\":5}\",\n            \"6\": \"{\\\"name\\\":\\\"John Smith\\\",\\\"emailList\\\":[],\\\"accountIds\\\":[],\\\"id\\\":6,\\\"billingAddress\\\":{\\\"street\\\":\\\"123 A St\\\",\\\"city\\\":\\\"San Jose\\\",\\\"state\\\":\\\"CA\\\",\\\"zipCode\\\":\\\"95131\\\"}}\",\n            \"7\": \"{\\\"name\\\":\\\"Larry Smith\\\",\\\"emailList\\\":[{\\\"label\\\":\\\"home\\\",\\\"address\\\":\\\"larry@yahoo.com\\\",\\\"id\\\":2,\\\"name\\\":\\\"home\\\"}],\\\"accountIds\\\":[],\\\"id\\\":7}\"\n        },\n        \"Address\": {},\n        \"EmailAddress\": {},\n        \"Account\": {\n            \"1\": \"{\\\"name\\\":\\\"Checking\\\",\\\"balance\\\":5000,\\\"id\\\":1}\",\n            \"2\": \"{\\\"name\\\":\\\"Saving\\\",\\\"balance\\\":2000,\\\"id\\\":2}\"\n        }\n    }\n}\n"
  },
  {
    "path": "server/datasources.json",
    "content": "{\n    \"db\": {\n        \"name\": \"db\",\n        \"connector\": \"memory\",\n        \"file\": \"./data.json\"\n    },\n    \"transient\": {\n        \"name\": \"transient\",\n        \"connector\": \"memory\"\n    }\n}\n"
  },
  {
    "path": "server/middleware.development.json",
    "content": "{\n  \"final:after\": {\n    \"strong-error-handler\": {\n      \"params\": {\n        \"debug\": true,\n        \"log\": true\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "server/middleware.json",
    "content": "{\n  \"initial:before\": {\n    \"loopback#favicon\": {}\n  },\n  \"initial\": {\n    \"compression\": {},\n    \"cors\": {\n      \"params\": {\n        \"origin\": true,\n        \"credentials\": true,\n        \"maxAge\": 86400\n      }\n    }\n  },\n  \"session\": {\n  },\n  \"auth\": {\n  },\n  \"parse\": {\n  },\n  \"routes:before\": {\n    \"loopback#rest\": {\n      \"paths\": [\"${restApiRoot}\"]\n    }\n  },\n  \"files\": {\n    \"serve-static\": {\n      \"params\": \"$!../client\"\n    }\n  },\n  \"final\": {\n    \"loopback#urlNotFound\": {}\n  },\n  \"final:after\": {\n    \"strong-error-handler\": {}\n  }\n}\n"
  },
  {
    "path": "server/model-config.json",
    "content": "{\n    \"_meta\": {\n        \"sources\": [\n            \"loopback/common/models\",\n            \"loopback/server/models\",\n            \"../common/models\",\n            \"../common/types\",\n            \"./models\"\n        ]\n    },\n    \"User\": {\n        \"dataSource\": \"db\"\n    },\n    \"AccessToken\": {\n        \"dataSource\": \"db\",\n        \"public\": false\n    },\n    \"ACL\": {\n        \"dataSource\": \"db\",\n        \"public\": false\n    },\n    \"RoleMapping\": {\n        \"dataSource\": \"db\",\n        \"public\": false\n    },\n    \"Role\": {\n        \"dataSource\": \"db\",\n        \"public\": false\n    },\n    \"Customer\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    },\n    \"Address\": {\n        \"dataSource\": \"transient\",\n        \"public\": false\n    },\n    \"EmailAddress\": {\n        \"dataSource\": \"transient\",\n        \"public\": false\n    },\n    \"Account\": {\n        \"dataSource\": \"db\",\n        \"public\": false\n    },\n    \"Author\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    },\n    \"Reader\": {\n        \"dataSource\": \"db\",\n        \"public\": false\n    },\n    \"Book\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    },\n    \"Link\": {\n        \"dataSource\": \"transient\",\n        \"public\": false\n    },\n    \"Order\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    },\n    \"Note\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    },\n    \"Content\": {\n        \"dataSource\": null,\n        \"public\": false\n    },\n    \"Googlemaps\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    },\n    \"products\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    },\n    \"catalogs\": {\n        \"dataSource\": \"db\",\n        \"public\": true\n    }\n}"
  },
  {
    "path": "server/server.js",
    "content": "'use strict';\n\nvar loopback = require('loopback');\nvar boot = require('loopback-boot');\n\nvar app = module.exports = loopback();\n\napp.start = function() {\n    // start the web server\n    return app.listen(function() {\n        app.emit('started');\n        var baseUrl = app.get('url').replace(/\\/$/, '');\n        console.log('Web server listening at: %s', baseUrl);\n        if (app.get('loopback-component-explorer')) {\n            var explorerPath = app.get('loopback-component-explorer').mountPath;\n            console.log('Browse your REST API at %s%s', baseUrl, explorerPath);\n        }\n    });\n};\n\n// Bootstrap the application, configure models, datasources and middleware.\n// Sub-apps like REST API are mounted via boot scripts.\nboot(app, __dirname, function(err) {\n    if (err) {\n        throw err;\n    }\n\n    // start the server if `$ node server.js`\n    if (require.main === module) {\n        app.start();\n    }\n});\n"
  },
  {
    "path": "src/ast.ts",
    "content": "import * as _ from 'lodash';\nimport {\n  connectionTypeName,\n  singularModelName,\n  pluralModelName,\n  methodName,\n  edgeTypeName,\n  sharedRelations,\n  idToCursor,\n} from './utils';\nimport { findRelated, findAll, findOne, resolveConnection } from './execution';\nimport { ITypesHash } from './interfaces';\n\n/*** Loopback Types - GraphQL types\n        any - JSON\n        Array - [JSON]\n        Boolean = boolean\n        Buffer - not supported\n        Date - Date (custom scalar)\n        GeoPoint - not supported\n        null - not supported\n        Number = float\n        Object = JSON (custom scalar)\n        String - string\n    ***/\n\nlet types: ITypesHash = {};\n\nconst exchangeTypes = {\n  'any': 'JSON',\n  'Any': 'JSON',\n  'Number': 'Int',\n  'number': 'Int',\n  'Object': 'JSON',\n  'object': 'JSON',\n};\n\nconst SCALARS = {\n  any: 'JSON',\n  number: 'Float',\n  string: 'String',\n  boolean: 'Boolean',\n  objectid: 'ID',\n  date: 'Date',\n  object: 'JSON',\n  now: 'Date',\n  guid: 'ID',\n  uuid: 'ID',\n  uuidv4: 'ID',\n  geopoint: 'GeoPoint',\n};\n\nconst PAGINATION = 'where: JSON, after: String, first: Int, before: String, last: Int';\nconst IDPARAMS = 'id: ID!';\n\nfunction getScalar(type: string) {\n  return SCALARS[type.toLowerCase().trim()];\n}\n\nfunction toTypes(union: string[]) {\n  return _.map(union, type => {\n    return getScalar(type) ? getScalar(type) : type;\n  });\n}\n\nfunction mapProperty(model: any, property: any, modelName: string, propertyName: string) {\n  if (property.deprecated) {\n    return;\n  }\n  types[modelName].fields[propertyName] = {\n    required: property.required,\n    hidden: model.definition.settings.hidden && model.definition.settings.hidden.indexOf(propertyName) !== -1,\n  };\n  let currentProperty = types[modelName].fields[propertyName];\n\n  let typeName = `${modelName}_${propertyName}`;\n  let propertyType = property.type;\n\n  if (propertyType.name === 'Array') { // JSON Array\n    currentProperty.list = true;\n    currentProperty.gqlType = 'JSON';\n    currentProperty.scalar = true;\n    return;\n  }\n\n  if (_.isArray(property.type)) {\n    currentProperty.list = true;\n    propertyType = property.type[0];\n  }\n\n  let scalar = getScalar(propertyType.name);\n  if (property.defaultFn) {\n    scalar = getScalar(property.defaultFn);\n  }\n  if (scalar) {\n    currentProperty.scalar = true;\n    currentProperty.gqlType = scalar;\n    if (property.enum) { // enum has a dedicated type but no input type is required\n      types[typeName] = {\n        values: property.enum,\n        category: 'ENUM',\n      };\n      currentProperty.gqlType = typeName;\n    }\n  }\n\n  if (propertyType.name === 'ModelConstructor' && property.defaultFn !== 'now') {\n    currentProperty.gqlType = propertyType.modelName;\n    let union = propertyType.modelName.split('|');\n    //type is a union\n    if (union.length > 1) { // union type\n      types[typeName] = { // creating a new union type\n        category: 'UNION',\n        values: toTypes(union),\n      };\n    } else if (propertyType.settings && propertyType.settings.anonymous && propertyType.definition) {\n      currentProperty.gqlType = typeName;\n      types[typeName] = {\n        category: 'TYPE',\n        input: true,\n        fields: {},\n      }; // creating a new type\n      _.forEach(propertyType.definition.properties, (p, key) => {\n        mapProperty(propertyType, p, typeName, key);\n      });\n    }\n  }\n}\n\nfunction mapRelation(rel: any, modelName: string, relName: string) {\n  types[modelName].fields[relName] = {\n    relation: true,\n    embed: rel.embed,\n    gqlType: connectionTypeName(rel.modelTo),\n    args: PAGINATION,\n    resolver: (obj, args) => {\n      return findRelated(rel, obj, args);\n    },\n  };\n}\n\n/*\nfunction generateReturns(name, props) {\n    if (_.isObject(props)) {\n        props = [props];\n    }\n    let args;\n    args = _.map(props, prop => {\n        if (_.isArray(prop.type)) {\n            return `${prop.arg}: [${toType(prop.type[0])}]${prop.required ? '!' : ''}`;\n        } else if (toType(prop.type)) {\n            return `${prop.arg}: ${toType(prop.type)}${prop.required ? '!' : ''}`;\n        }\n        return '';\n    }).join(' \\n ');\n    return args ? `{${args}}` : '';\n}\n\nfunction generateAccepts(name, props) {\n    let ret = _.map(props, prop => {\n        let propType = prop.type;\n        if (_.isArray(prop.type)) {\n            propType = prop.type[0];\n        }\n        return propType ? `${prop.arg}: [${toType(prop.type[0])}]${prop.required ? '!' : ''}` : '';\n    }).join(' \\n ');\n    return ret ? `(${ret})` : '';\n\n}\n*/\n\nfunction addRemoteHooks(model: any) {\n\n  _.map(model.sharedClass._methods, (method: any) => {\n    if (method.accessType !== 'READ' && method.http.path) {\n      let acceptingParams = '',\n        returnType = 'JSON';\n      method.accepts.map(function (param) {\n        let paramType = '';\n        if (typeof param.type === 'object') {\n          paramType = 'JSON';\n        } else {\n          if (!SCALARS[param.type.toLowerCase()]) {\n            paramType = `${param.type}Input`;\n          } else {\n            paramType = _.upperFirst(param.type);\n          }\n        }\n        if (param.arg) {\n          acceptingParams += `${param.arg}: ${exchangeTypes[paramType] || paramType} `;\n        }\n      });\n      if (method.returns && method.returns[0]) {\n        if (!SCALARS[method.returns[0].type] && typeof method.returns[0].type !== 'object') {\n          returnType = `${method.returns[0].type}`;\n        } else {\n          returnType = `${_.upperFirst(method.returns[0].type)}`;\n          if (typeof method.returns[0].type === 'object') {\n            returnType = 'JSON';\n          }\n        }\n      }\n      types.Mutation.fields[`${methodName(method, model)}`] = {\n        relation: true,\n        args: acceptingParams,\n        gqlType: `${exchangeTypes[returnType] || returnType}`,\n      };\n    }\n  });\n}\n\nfunction mapRoot(model) {\n  types.Query.fields[singularModelName(model)] = {\n    relation: true,\n    args: IDPARAMS,\n    root: true,\n    gqlType: singularModelName(model),\n    resolver: (obj, args /*, context*/) => {\n      findOne(model, obj, args);\n    },\n  };\n\n  types.Query.fields[pluralModelName(model)] = {\n    relation: true,\n    root: true,\n    args: PAGINATION,\n    gqlType: connectionTypeName(model),\n    resolver: (obj, args) => {\n      findAll(model, obj, args);\n    },\n  };\n\n  types.Mutation.fields[`save${singularModelName(model)}`] = {\n    relation: true,\n    args: `obj: ${singularModelName(model)}Input!`,\n    gqlType: singularModelName(model),\n    resolver: (context, args) => model.upsert(args.obj, context),\n  };\n\n  types.Mutation.fields[`delete${singularModelName(model)}`] = {\n    relation: true,\n    args: IDPARAMS,\n    gqlType: ` ${singularModelName(model)}`,\n    resolver: (context, args) => {\n      return model.findById(args.id, context)\n        .then(instance => instance.destroy());\n    },\n  };\n  // _.each(model.sharedClass.methods, method => {\n  //     if (method.accessType !== 'READ' && method.http.path) {\n  //         let methodName = methodName(method, model);\n  //         types.Mutation.fields[methodName] = {\n  //             gqlType: `${generateReturns(method.name, method.returns)}`,\n  //             args: `${generateAccepts(method.name, method.accepts)}`\n  //         }\n\n  //         return `${methodName(method)}\n  //                     ${generateAccepts(method.name, method.accepts)}\n\n  //                 : JSON`;\n  //     } else {\n  //         return undefined;\n  //     }\n  // });\n  addRemoteHooks(model);\n}\n\nfunction mapConnection(model) {\n  types[connectionTypeName(model)] = {\n    connection: true,\n    category: 'TYPE',\n    fields: {\n      pageInfo: {\n        required: true,\n        gqlType: 'pageInfo',\n      },\n      edges: {\n        list: true,\n        gqlType: edgeTypeName(model),\n        resolver: (obj /*, args, context*/) => {\n          return _.map(obj.list, node => {\n            return {\n              cursor: idToCursor(node[model.getIdName()]),\n              node: node,\n            };\n          });\n        },\n      },\n      totalCount: {\n        gqlType: 'Int',\n        scalar: true,\n        resolver: (obj /*, args, context*/) => {\n          return obj.count;\n        },\n      },\n      [model.pluralModelName]: {\n        gqlType: singularModelName(model),\n        list: true,\n        resolver: (obj /*, args, context*/) => {\n          return obj.list;\n        },\n      },\n    },\n    resolver: (/*obj, args, context*/) => {\n      return resolveConnection(model);\n    },\n  };\n  types[edgeTypeName(model)] = {\n    category: 'TYPE',\n    fields: {\n      node: {\n        gqlType: singularModelName(model),\n        required: true,\n      },\n      cursor: {\n        gqlType: 'String',\n        required: true,\n      },\n    },\n  };\n\n}\nexport function abstractTypes(models: any[]): ITypesHash {\n  //building all models types & relationships\n  types.pageInfo = {\n    category: 'TYPE',\n    fields: {\n      hasNextPage: {\n        gqlType: 'Boolean',\n        required: true,\n      },\n      hasPreviousPage: {\n        gqlType: 'Boolean',\n        required: true,\n      },\n      startCursor: {\n        gqlType: 'String',\n      },\n      endCursor: {\n        gqlType: 'String',\n      },\n    },\n  };\n  types.Query = {\n    category: 'TYPE',\n    fields: {},\n  };\n  types.Mutation = {\n    category: 'TYPE',\n    fields: {},\n  };\n\n  _.forEach(models, model => {\n    if (model.shared) {\n      mapRoot(model);\n    }\n    types[singularModelName(model)] = {\n      category: 'TYPE',\n      input: true,\n      fields: {},\n    };\n    _.forEach(model.definition.properties, (property, key) => {\n      mapProperty(model, property, singularModelName(model), key);\n    });\n\n    mapConnection(model);\n    _.forEach(sharedRelations(model), rel => {\n      mapRelation(rel, singularModelName(model), rel.name);\n      mapConnection(rel.modelTo);\n    });\n  });\n  return types;\n}\n"
  },
  {
    "path": "src/boot.ts",
    "content": "import { graphqlExpress, graphiqlExpress } from 'graphql-server-express';\nimport { makeExecutableSchema } from 'graphql-tools';\nimport * as bodyParser from 'body-parser';\n\nimport { abstractTypes } from './ast';\nimport { resolvers } from './resolvers';\nimport { generateTypeDefs } from './typedefs';\n\nexport function boot(app, options) {\n  const models = app.models();\n  let types = abstractTypes(models);\n  let schema = makeExecutableSchema({\n    typeDefs: generateTypeDefs(types),\n    resolvers: resolvers(models),\n    resolverValidationOptions: {\n      requireResolversForAllFields: false,\n    },\n  });\n\n  let graphiqlPath = options.graphiqlPath || '/graphiql';\n  let path = options.path || '/graphql';\n\n  app.use(path, bodyParser.json(), graphqlExpress(req => {\n    return {\n      schema,\n      context: req,\n    };\n  }));\n  app.use(graphiqlPath, graphiqlExpress({\n    endpointURL: path,\n  }));\n}\n"
  },
  {
    "path": "src/execution.ts",
    "content": "import * as _ from 'lodash';\n\nimport {\n  getId,\n  connectionTypeName,\n  idToCursor,\n} from './utils';\n\nfunction buildSelector(model, args) {\n  let selector = {\n    where: args.where || {},\n    skip: undefined,\n    limit: undefined,\n    order: undefined,\n  };\n  const begin = getId(args.after);\n  const end = getId(args.before);\n\n  selector.skip = args.first - args.last || 0;\n  selector.limit = args.last || args.first;\n  selector.order = model.getIdName() + (end ? ' DESC' : ' ASC');\n  if (begin) {\n    selector.where[model.getIdName()] = selector[model.getIdName()] || {};\n    selector.where[model.getIdName()].gt = begin;\n  }\n  if (end) {\n    selector.where[model.getIdName()] = selector[model.getIdName()] || {};\n    selector.where[model.getIdName()].lt = end;\n  }\n  return selector;\n}\n\nfunction findOne(model, obj, args /*, context*/) {\n  let id = obj ? obj[model.getIdName()] : args.id;\n  return model.findById(id);\n}\n\nfunction getCount(model, obj, args, context) {\n  return model.count(args.where, obj, context);\n}\n\nfunction getFirst(model, obj, args) {\n  return model.findOne({\n    order: model.getIdName() + (args.before ? ' DESC' : ' ASC'),\n    where: args.where,\n  }, obj)\n    .then(res => {\n      return res ? res.__data : {};\n    });\n}\n\nfunction getList(model, args) {\n  return model.find(buildSelector(model, args));\n}\n\nfunction findAll(model: any, obj: any, args: any) {\n  const response = {\n    args: args,\n    count: undefined,\n    first: undefined,\n    list: undefined,\n  };\n  return getCount(model, obj, args, undefined)\n    .then(count => {\n      response.count = count;\n      return getFirst(model, obj, args);\n    })\n    .then(first => {\n      response.first = first;\n      return getList(model, args);\n    })\n    .then(list => {\n      response.list = list;\n      return response;\n    });\n}\n\nfunction findRelated(rel, obj, args) {\n  if (_.isArray(obj[rel.keyFrom])) {\n    return [];\n  }\n  args.where = {\n    [rel.keyTo]: obj[rel.keyFrom],\n  };\n  return findAll(rel.modelTo, obj, args);\n\n}\n\nfunction resolveConnection(model) {\n  return {\n    [connectionTypeName(model)]: {\n      totalCount: (obj) => {\n        return obj.count;\n      },\n\n      edges: (obj) => {\n        return _.map(obj.list, node => {\n          return {\n            cursor: idToCursor(node[model.getIdName()]),\n            node: node,\n          };\n        });\n      },\n\n      [model.pluralModelName]: (obj) => {\n        return obj.list;\n      },\n\n      pageInfo: (obj) => {\n        let pageInfo = {\n          startCursor: null,\n          endCursor: null,\n          hasPreviousPage: false,\n          hasNextPage: false,\n        };\n        if (obj.count > 0) {\n          pageInfo.startCursor = idToCursor(obj.list[0][model.getIdName()]);\n          pageInfo.endCursor = idToCursor(obj.list[obj.list.length - 1][model.getIdName()]);\n          pageInfo.hasNextPage = obj.list.length === obj.args.limit;\n          pageInfo.hasPreviousPage = obj.list[0][model.getIdName()] !== obj.first[model.getIdName()].toString();\n        }\n        return pageInfo;\n      },\n    },\n  };\n}\n\nexport {\n  findAll,\n  findOne,\n  findRelated,\n  resolveConnection,\n};\n"
  },
  {
    "path": "src/index.ts",
    "content": "import { boot } from './boot';\nmodule.exports = boot;\n"
  },
  {
    "path": "src/interfaces.ts",
    "content": "//export declare function Model(arg?: { hooks?: {}, remotes?: {} }): any;\n\nexport interface IProperty {\n  type: any;\n  deprecated?: Boolean;\n  required?: Boolean;\n  defaultFn?: any;\n  enum?: any;\n}\n\nexport interface IField {\n  list?: Boolean;\n  scalar?: Boolean;\n  required?: Boolean;\n  gqlType: string;\n  relation?: any;\n  args?: any;\n}\n\nexport interface ITypesHash {\n  [id: string]: any;\n}\n\nexport interface ISchemaType {\n  category: string;\n  fields: IField[];\n  input: any;\n  values: any;\n}\n"
  },
  {
    "path": "src/methods.ts",
    "content": "// import * as _ from 'lodash';\n// import {toType} from './ast';\n// import {} from './utils';\n// import {Property} from './interfaces';\n\n\n// function generateAccepts(name: string, props: Property[]) {\n//   let ret = _.map(props, prop => {\n//     let propType = prop.type;\n//     if (_.isArray(prop.type)) {\n//       propType = prop.type[0];\n//     }\n//     return propType ? `${prop.arg}: [${toType(prop.type[0])}]${prop.required ? '!' : ''}` : '';\n//   }).join(' \\n ');\n//   return ret ? `(${ret})` : '';\n\n// }\n\n// function generateReturns(name, props) {\n//   if (_.isObject(props)) {\n//     props = [props];\n//   }\n//   let args;\n//   args = _.map(props, prop => {\n//     if (_.isArray(prop.type)) {\n//       return `${prop.arg}: [${toType(prop.type[0])}]${prop.required ? '!' : ''}`;\n//     } else if (toType(prop.type)) {\n//       return `${prop.arg}: ${toType(prop.type)}${prop.required ? '!' : ''}`;\n//     }\n//     return '';\n//   }).join(' \\n ');\n//   return args ? `{${args}}` : '';\n// }\n\n// export default function generateMethods(model) {\n//   return _.chain(model.sharedClass.methods())\n//     .map(method => {\n//       if (method.accessType === 'WRITE' && method.http.path) {\n//         return `${utils.methodName(method)}\n//                         ${generateAccepts(method.name, method.accepts)}\n//                         ${generateReturns(method.name, method.returns)}\n//                     : JSON`;\n//       } else {\n//         return undefined;\n//       }\n//     })\n//     .compact()\n//     .value()\n//     .join(' \\n ');\n// }\n"
  },
  {
    "path": "src/resolvers.ts",
    "content": "import * as _ from 'lodash';\nimport * as utils from './utils';\n\nimport * as execution from './execution';\nimport * as GraphQLJSON from 'graphql-type-json';\nimport * as GraphQLDate from 'graphql-date';\nimport {\n  CoordinatesScalar,\n} from 'graphql-geojson';\n\nconst scalarResolvers = {\n  JSON: GraphQLJSON,\n  Date: GraphQLDate,\n  GeoPoint: CoordinatesScalar,\n};\n\nfunction RelationResolver(model) {\n  let resolver = {};\n  _.forEach(utils.sharedRelations(model), rel => {\n    resolver[rel.name] = (obj, args) => {\n      return execution.findRelated(rel, obj, args);\n    };\n  });\n\n  return {\n    [utils.singularModelName(model)]: resolver,\n  };\n}\n\nfunction rootResolver(model) {\n  return {\n    Query: {\n      [`${utils.pluralModelName(model)}`]: (root, args) => {\n        return execution.findAll(model, root, args);\n      },\n      [`${utils.singularModelName(model)}`]: (obj, args) => {\n        return execution.findOne(model, obj, args);\n      },\n    },\n    Mutation: {\n      [`save${utils.singularModelName(model)}`]: (_root, args) => {\n        return model.upsert(args.obj);\n      },\n      [`delete${utils.singularModelName(model)}`]: (_root, args) => {\n        return model.findById(args.id)\n          .then(instance => {\n            return instance ? instance.destroy() : null;\n          });\n      },\n    },\n  };\n}\n\nfunction connectionResolver(model: any) {\n  return {\n    [utils.connectionTypeName(model)]: {\n      totalCount: (obj) => {\n        return obj.count;\n      },\n\n      edges: (obj) => {\n        return _.map(obj.list, node => {\n          return {\n            cursor: utils.idToCursor(node[model.getIdName()]),\n            node: node,\n          };\n        });\n      },\n\n      [model.pluralModelName]: (obj) => {\n        return obj.list;\n      },\n\n      pageInfo: (obj) => {\n        let pageInfo = {\n          startCursor: null,\n          endCursor: null,\n          hasPreviousPage: false,\n          hasNextPage: false,\n        };\n        if (obj.count > 0) {\n          pageInfo.startCursor = utils.idToCursor(obj.list[0][model.getIdName()]);\n          pageInfo.endCursor = utils.idToCursor(obj.list[obj.list.length - 1][model.getIdName()]);\n          pageInfo.hasNextPage = obj.list.length === obj.args.limit;\n          pageInfo.hasPreviousPage = obj.list[0][model.getIdName()] !== obj.first[model.getIdName()].toString();\n        }\n        return pageInfo;\n      },\n    },\n  };\n}\n\nfunction remoteResolver(model) {\n  let mutation = {};\n  //model.sharedClass.methods\n  if (model.sharedClass && model.sharedClass.methods) {\n    model.sharedClass._methods.map(function (method) {\n      if (method.accessType !== 'READ' && method.http.path) {\n        let acceptingParams = [];\n        method.accepts.map(function (param) {\n          if (param.arg) {\n            acceptingParams.push(param.arg);\n          }\n        });\n        mutation[`${utils.methodName(method, model)}`] = (args) => {\n          let params = [];\n          _.each(method.accepts, (el, i) => {\n            params[i] = args[el.arg];\n          });\n          return model[method.name].apply(model, params);\n        };\n      }\n    });\n  }\n  return {\n    Mutation: mutation,\n  };\n}\n\n/**\n * Generate resolvers for all models\n *\n * @param {Object} models: All loopback Models\n * @returns {Object} resolvers functions for all models - queries and mutations\n */\nexport function resolvers(models: any[]) {\n  return _.reduce(models, (obj: any, model: any) => {\n    if (model.shared) {\n      return _.merge(\n        obj,\n        rootResolver(model),\n        connectionResolver(model),\n        RelationResolver(model),\n        remoteResolver(model),\n      );\n    }\n    return obj;\n  }, scalarResolvers);\n}\n"
  },
  {
    "path": "src/typedefs.ts",
    "content": "import * as _ from 'lodash';\nimport { ISchemaType, IField, ITypesHash } from './interfaces';\n\nconst scalarTypes = `\n        scalar Date\n        scalar JSON\n        scalar GeoPoint\n        `;\n\nfunction args(params: string): string {\n  return params ? `(${args})` : '';\n}\n\nfunction generateInputField(field: IField, name: string): string {\n  return `\n        ${name} : ${field.list ? '[' : ''}\n        ${field.gqlType}${field.scalar ? '' : 'Input'}${field.required ? '!' : ''} ${field.list ? ']' : ''}`;\n}\n\nfunction generateOutputField(field: IField, name: string): string {\n  return `${name} ${args(field.args)} : ${field.list ? '[' : ''}${field.gqlType}${field.required ? '!' : ''} ${field.list ? ']' : ''}`;\n}\n\nexport function generateTypeDefs(types: ITypesHash) {\n  const categories = {\n    TYPE: (type: ISchemaType, name: string) => {\n      let output = _.reduce(type.fields, (res: string, field: IField, fieldName: string): string => {\n        return res + generateOutputField(field, fieldName) + ' \\n ';\n      }, '');\n\n      let result = `\n                type ${name} {\n                    ${output}\n                }`;\n      if (type.input) {\n        let input = _.reduce(type.fields, (accumulator: string, field: IField, fieldName: string) => {\n          return !field.relation ? accumulator + generateInputField(field, fieldName) + ' \\n ' : accumulator;\n        }, '');\n        result += `input ${name}Input {\n                    ${input}\n                }`;\n      }\n      return result;\n    },\n    UNION: (type: ISchemaType, name: string) => {\n      return `union ${name} = ${type.values.join(' | ')}`;\n    },\n    ENUM: (type: ISchemaType, name: string) => {\n      return `enum ${name} {${type.values.join(' ')}}`;\n    },\n  };\n\n  return _.reduce(types, (result: string, type: ISchemaType, name: string) => {\n    return result + categories[type.category](type, name);\n  }, scalarTypes);\n}\n"
  },
  {
    "path": "src/utils.ts",
    "content": "import * as _ from 'lodash';\n\nconst PAGINATION = '(where: JSON, after: String, first: Int, before: String, last: Int)';\n\nfunction base64(i) {\n  return (new Buffer(i, 'ascii')).toString('base64');\n}\n\nfunction unbase64(i) {\n  return (new Buffer(i, 'base64')).toString('ascii');\n}\n\nconst PREFIX = 'connection.';\n\n/**\n * Creates the cursor string from an offset.\n * @param {String} id the id to convert\n * @returns {String}   an opaque cursor\n */\nfunction idToCursor(id) {\n  return base64(PREFIX + id);\n}\n\n/**\n * Rederives the offset from the cursor string.\n * @param {String} cursor   the cursor for conversion\n * @returns {String} id   converted id\n */\nfunction cursorToId(cursor) {\n  return unbase64(cursor).substring(PREFIX.length);\n}\n\nfunction getId(cursor) {\n  if (cursor === undefined || cursor === null) {\n    return null;\n  }\n  return cursorToId(cursor);\n}\n\nfunction connectionTypeName(model) {\n  return `${model.modelName}Connection`;\n}\n\nfunction edgeTypeName(model: any) {\n  return `${model.modelName}Edge`; // e.g. UserEdge\n}\n\nfunction singularModelName(model) {\n  return model.modelName;\n}\n\nfunction pluralModelName(model: any) {\n  return 'all' + _.upperFirst(model.pluralModelName);\n}\n\nfunction sharedRelations(model: any) {\n  return _.pickBy(model.relations, rel => rel.modelTo && rel.modelTo.shared);\n}\n\nfunction sharedModels(models: any[]) {\n  return _.filter(models, model => {\n    return model.shared;\n  });\n}\n\nfunction methodName(method, model) {\n  return model.modelName + _.upperFirst(method.name);\n}\nexport {\n  PAGINATION,\n  getId,\n  idToCursor,\n  cursorToId,\n  connectionTypeName,\n  edgeTypeName,\n  singularModelName,\n  methodName,\n  pluralModelName,\n  sharedRelations,\n  sharedModels,\n};\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"target\": \"es6\",\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"noImplicitAny\": false,\n        \"allowSyntheticDefaultImports\": true,\n        \"allowJs\": true,\n        \"importHelpers\": true,\n        \"noUnusedLocals\": true,\n        \"noUnusedParameters\": true,\n        \"noImplicitThis\": true,\n        \"alwaysStrict\": true,\n        \"experimentalDecorators\": true,\n        \"emitDecoratorMetadata\": true,\n        \"declaration\": false,\n        \"outDir\": \"build\",\n        \"sourceMap\": true,\n        \"watch\": true\n    },\n    \"include\": [\n        \"src/**/*\",\n        \"__tests__/**/*\"\n    ],\n    \"typeRoots\": [\n        \"node_modules/@types\"\n    ]\n}\n"
  },
  {
    "path": "tsconfig.release.json",
    "content": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"sourceMap\": false,\n        \"declaration\": false,\n        \"outDir\": \"build\",\n        \"removeComments\": true,\n        \"watch\": false\n    },\n    \"include\": [\n        \"src/**/*\"\n    ]\n}\n"
  },
  {
    "path": "tsconfig.test.json",
    "content": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"allowSyntheticDefaultImports\": true,\n        \"moduleResolution\": \"node\",\n        \"inlineSourceMap\": true\n    }\n}\n"
  },
  {
    "path": "tslint.json",
    "content": "{\n    \"rules\": {\n        \"align\": [\n            false,\n            \"parameters\",\n            \"arguments\",\n            \"statements\"\n        ],\n        \"ban\": false,\n        \"class-name\": true,\n        \"curly\": true,\n        \"eofline\": true,\n        \"forin\": true,\n        \"indent\": [\n            true,\n            \"spaces\"\n        ],\n        \"interface-name\": [],\n        \"jsdoc-format\": true,\n        \"label-position\": true,\n        \"max-line-length\": [\n            true,\n            140\n        ],\n        \"member-access\": true,\n        \"member-ordering\": [\n            true,\n            \"public-before-private\",\n            \"static-before-instance\",\n            \"variables-before-functions\"\n        ],\n        \"no-any\": false,\n        \"no-arg\": true,\n        \"no-bitwise\": true,\n        \"no-conditional-assignment\": true,\n        \"no-consecutive-blank-lines\": false,\n        \"no-console\": [\n            true,\n            \"log\",\n            \"debug\",\n            \"info\",\n            \"time\",\n            \"timeEnd\",\n            \"trace\"\n        ],\n        \"no-construct\": true,\n        \"no-debugger\": true,\n        \"no-duplicate-variable\": true,\n        \"no-empty\": true,\n        \"no-eval\": true,\n        \"no-inferrable-types\": [],\n        \"no-internal-module\": true,\n        \"no-null-keyword\": false,\n        \"no-require-imports\": false,\n        \"no-shadowed-variable\": true,\n        \"no-switch-case-fall-through\": true,\n        \"no-trailing-whitespace\": true,\n        \"no-unused-expression\": true,\n        \"no-var-keyword\": true,\n        \"no-var-requires\": true,\n        \"object-literal-sort-keys\": false,\n        \"one-line\": [\n            true,\n            \"check-open-brace\",\n            \"check-catch\",\n            \"check-else\",\n            \"check-finally\",\n            \"check-whitespace\"\n        ],\n        \"quotemark\": [\n            true,\n            \"single\",\n            \"avoid-escape\"\n        ],\n        \"radix\": true,\n        \"semicolon\": [\n            true,\n            \"always\"\n        ],\n        \"switch-default\": true,\n        \"trailing-comma\": [\n            true,\n            {\n                \"multiline\": \"always\",\n                \"singleline\": \"never\"\n            }\n        ],\n        \"triple-equals\": [\n            true,\n            \"allow-null-check\"\n        ],\n        \"typedef\": [\n            false,\n            \"call-signature\",\n            \"parameter\",\n            \"arrow-parameter\",\n            \"property-declaration\",\n            \"variable-declaration\",\n            \"member-variable-declaration\"\n        ],\n        \"typedef-whitespace\": [\n            true,\n            {\n                \"call-signature\": \"nospace\",\n                \"index-signature\": \"nospace\",\n                \"parameter\": \"nospace\",\n                \"property-declaration\": \"nospace\",\n                \"variable-declaration\": \"nospace\"\n            },\n            {\n                \"call-signature\": \"space\",\n                \"index-signature\": \"space\",\n                \"parameter\": \"space\",\n                \"property-declaration\": \"space\",\n                \"variable-declaration\": \"space\"\n            }\n        ],\n        \"variable-name\": [\n            true,\n            \"check-format\",\n            \"allow-leading-underscore\",\n            \"ban-keywords\"\n        ],\n        \"whitespace\": [\n            true,\n            \"check-branch\",\n            \"check-decl\",\n            \"check-operator\",\n            \"check-separator\",\n            \"check-type\"\n        ]\n    }\n}\n"
  }
]