├── .eslintrc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── DEV_README.md ├── LICENSE ├── README.md ├── functions └── apollo-graphql │ ├── apollo-graphql.js │ ├── package-lock.json │ └── package.json ├── gatsby-browser.js ├── gatsby-config.js ├── gatsby-node.js ├── gatsby-ssr.js ├── index.js ├── netlify.toml ├── package.json ├── src ├── client.js ├── components │ ├── Application │ │ ├── Application.js │ │ └── index.js │ ├── Drawer │ │ ├── Drawer.js │ │ └── index.js │ ├── Dropdown │ │ ├── Dropdown.js │ │ └── index.js │ ├── Editor │ │ ├── Editor.js │ │ └── index.js │ ├── EditorToolbar │ │ ├── EditorToolbar.js │ │ └── index.js │ ├── Footer │ │ ├── Footer.js │ │ └── index.js │ ├── Header │ │ ├── Header.js │ │ └── index.js │ ├── IconButton │ │ ├── IconButton.js │ │ └── index.js │ ├── Identity │ │ ├── Identity.js │ │ └── index.js │ ├── Lightbox │ │ ├── Lightbox.js │ │ └── index.js │ ├── Logo │ │ ├── Logo.js │ │ └── index.js │ ├── Preview │ │ ├── Preivew.js │ │ └── index.js │ ├── PreviewToolbar │ │ ├── PreviewToolbar.js │ │ └── index.js │ ├── Seo │ │ ├── Seo.js │ │ └── index.js │ ├── Settings │ │ ├── Settings.js │ │ └── index.js │ ├── Sidebar │ │ ├── Sidebar.js │ │ └── index.js │ ├── Sidenav │ │ ├── Sidenav.js │ │ └── index.js │ ├── Source │ │ ├── Source.js │ │ └── index.js │ ├── SvgIcon │ │ ├── SvgIcon.js │ │ └── index.js │ ├── ThemeThumbnail │ │ ├── ThemeThumbnail.js │ │ └── index.js │ ├── ThemeWrapper │ │ ├── ThemeWrapper.js │ │ └── index.js │ ├── Toolbar │ │ ├── Toolbar.js │ │ └── index.js │ └── TopNav │ │ ├── TopNav.js │ │ └── index.js ├── context │ └── index.js ├── data │ └── useSiteMetadata.js ├── layouts │ └── EditorLayout.js ├── pages │ ├── 404.js │ ├── editor.mdx │ ├── index.js │ ├── showcase.js │ └── your-themes.js ├── theme │ └── index.js └── utils │ ├── checkAndAddQuotes.js │ ├── checkAndParse.js │ ├── checkAndReplaceQuotes.js │ ├── const.js │ ├── defaultThemeObject.js │ ├── graphql.js │ └── iconPaths.js ├── static ├── images │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── skin-ui-background-image.jpg │ ├── skin-ui-editor-image.jpg │ ├── skin-ui-open-graph-image.jpg │ ├── skin-ui-save-image.jpg │ └── skin-ui-source-image.jpg └── skin-ui-source.zip └── yarn.lock /.eslintrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulieScanlon/skin-ui/4c86c5783e392f6b1a8f7fdb6698d0d7bf63de5e/.eslintrc -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variable files 55 | .env* 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /DEV_README.md: -------------------------------------------------------------------------------- 1 | Skin UI uses Netlify functions and apollo graphql which can be found at `/functions/apollo-graphql` 2 | 3 | In order to spin up the front-end and the back-end run the following 4 | 5 | ``` 6 | netlify dev 7 | ``` 8 | 9 | The front-end is now running on `http://localhost:8888/` 10 | 11 | and 12 | 13 | The back-end is now running on `http://localhost:8888/.netlify/functions/apollo-graphql` 14 | 15 | Admin User / Skin UI theme_author 16 | 17 | Allows you to amend the Default Skin UI theme 18 | 19 | email: fatbannerpaul@googlemail.com 20 | pass: Sc8nn3r1 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | skin-ui main image 3 | 4 | 5 | # Skin UI 6 | 7 | A Theme UI Live Preview and Code Editor. 8 | 9 | [https://www.skin-ui.com/](https://www.skin-ui.com/) 10 | 11 | If you have any feedback i'd love to hear from you: [@pauliescanlon](https://twitter.com/PaulieScanlon) 12 | 13 | Oh, and feel free to star the repo 🙏 14 | 15 | [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/P5P31B7G8) 16 | -------------------------------------------------------------------------------- /functions/apollo-graphql/apollo-graphql.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config() 2 | const faunadb = require("faunadb") 3 | const { ApolloServer, gql } = require("apollo-server-lambda") 4 | 5 | const q = faunadb.query 6 | 7 | const client = new faunadb.Client({ secret: process.env.FAUNA }) 8 | 9 | const typeDefs = gql` 10 | type Query { 11 | getAllThemes(theme_is_private: Boolean!): [ThemeObject] 12 | getThemesByUser(user_id: String!): [ThemeObject] 13 | getThemeById(theme_id: String!): ThemeObject 14 | } 15 | 16 | type Mutation { 17 | forkThemeWithId( 18 | user_id: String! 19 | theme_author: String! 20 | theme_name: String! 21 | theme_description: String! 22 | theme_style: String! 23 | theme_object: String! 24 | ): ThemeObject 25 | 26 | updateThemeById( 27 | theme_id: String! 28 | theme_name: String! 29 | theme_description: String! 30 | theme_style: String! 31 | theme_object: String! 32 | ): ThemeObject 33 | 34 | deleteThemeById(theme_id: String!): EmptyObject 35 | } 36 | 37 | type EmptyObject { 38 | ref: String 39 | } 40 | 41 | type ThemeObject { 42 | ref: String 43 | user_id: String! 44 | theme_author: String! 45 | theme_name: String! 46 | theme_description: String! 47 | theme_style: String! 48 | theme_is_private: Boolean! 49 | theme_object: String 50 | } 51 | ` 52 | 53 | const resolvers = { 54 | Query: { 55 | getAllThemes: async (root, args, context) => { 56 | const results = await client.query( 57 | q.Paginate(q.Match(q.Index("get-all-themes"), args.theme_is_private)) 58 | ) 59 | return results.data.map( 60 | ([ 61 | ref, 62 | user_id, 63 | theme_author, 64 | theme_name, 65 | theme_description, 66 | theme_style, 67 | theme_is_private, 68 | theme_object, 69 | ]) => ({ 70 | ref: ref.id, 71 | user_id, 72 | theme_author, 73 | theme_name, 74 | theme_description, 75 | theme_style, 76 | theme_is_private, 77 | theme_object, 78 | }) 79 | ) 80 | }, 81 | 82 | getThemesByUser: async (root, args, context) => { 83 | if (!args.user_id) { 84 | return [] 85 | } else { 86 | const results = await client.query( 87 | q.Paginate(q.Match(q.Index("get-themes-by-user"), args.user_id)) 88 | ) 89 | 90 | return results.data.map( 91 | ([ 92 | ref, 93 | user_id, 94 | theme_author, 95 | theme_name, 96 | theme_description, 97 | theme_style, 98 | theme_is_private, 99 | theme_object, 100 | ]) => ({ 101 | ref: ref.id, 102 | user_id, 103 | theme_author, 104 | theme_name, 105 | theme_description, 106 | theme_style, 107 | theme_is_private, 108 | theme_object, 109 | }) 110 | ) 111 | } 112 | }, 113 | 114 | getThemeById: async (root, args, context) => { 115 | if (!args.theme_id) { 116 | return [] 117 | } else { 118 | const results = await client.query( 119 | q.Get(q.Ref(q.Collection("skin-ui-themes"), args.theme_id)) 120 | ) 121 | 122 | const { theme_object } = results.data 123 | 124 | return { 125 | ref: results.ref.id, 126 | ...results.data, 127 | theme_object: theme_object, 128 | } 129 | } 130 | }, 131 | }, 132 | 133 | Mutation: { 134 | updateThemeById: async (root, args, context) => { 135 | const results = await client.query( 136 | q.Update(q.Ref(q.Collection("skin-ui-themes"), args.theme_id), { 137 | data: { 138 | user_id: args.user_id, 139 | theme_author: args.theme_author, 140 | theme_name: args.theme_name, 141 | theme_description: args.theme_description, 142 | theme_style: args.theme_style, 143 | theme_is_private: false, 144 | theme_object: args.theme_object, 145 | }, 146 | }) 147 | ) 148 | const { theme_object } = results.data 149 | 150 | return { 151 | ref: results.ref.id, 152 | ...results.data, 153 | theme_object: theme_object, 154 | } 155 | }, 156 | 157 | forkThemeWithId: async (root, args, context) => { 158 | const results = await client.query( 159 | q.Create(q.Collection("skin-ui-themes"), { 160 | data: { 161 | user_id: args.user_id, 162 | theme_author: args.theme_author, 163 | theme_name: args.theme_name, 164 | theme_description: args.theme_description, 165 | theme_style: args.theme_style, 166 | theme_is_private: false, 167 | theme_object: args.theme_object, 168 | }, 169 | }) 170 | ) 171 | const { theme_object } = results.data 172 | 173 | return { 174 | ref: results.ref.id, 175 | ...results.data, 176 | theme_object: theme_object, 177 | } 178 | }, 179 | 180 | deleteThemeById: async (root, args, context) => { 181 | const results = await client.query( 182 | q.Delete(q.Ref(q.Collection("skin-ui-themes"), args.theme_id)) 183 | ) 184 | 185 | return { 186 | ref: results.ref.id, 187 | } 188 | }, 189 | }, 190 | } 191 | 192 | const server = new ApolloServer({ 193 | typeDefs, 194 | resolvers, 195 | playground: true, 196 | introspection: true, 197 | }) 198 | 199 | exports.handler = server.createHandler({ 200 | cors: { 201 | origin: "*", 202 | credentials: true, 203 | }, 204 | }) 205 | -------------------------------------------------------------------------------- /functions/apollo-graphql/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apollo-graphql", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@apollo/protobufjs": { 8 | "version": "1.0.3", 9 | "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.3.tgz", 10 | "integrity": "sha512-gqeT810Ect9WIqsrgfUvr+ljSB5m1PyBae9HGdrRyQ3HjHjTcjVvxpsMYXlUk4rUHnrfUqyoGvLSy2yLlRGEOw==", 11 | "requires": { 12 | "@protobufjs/aspromise": "^1.1.2", 13 | "@protobufjs/base64": "^1.1.2", 14 | "@protobufjs/codegen": "^2.0.4", 15 | "@protobufjs/eventemitter": "^1.1.0", 16 | "@protobufjs/fetch": "^1.1.0", 17 | "@protobufjs/float": "^1.0.2", 18 | "@protobufjs/inquire": "^1.1.0", 19 | "@protobufjs/path": "^1.1.2", 20 | "@protobufjs/pool": "^1.1.0", 21 | "@protobufjs/utf8": "^1.1.0", 22 | "@types/long": "^4.0.0", 23 | "@types/node": "^10.1.0", 24 | "long": "^4.0.0" 25 | }, 26 | "dependencies": { 27 | "@types/node": { 28 | "version": "10.17.17", 29 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", 30 | "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==" 31 | } 32 | } 33 | }, 34 | "@apollographql/apollo-tools": { 35 | "version": "0.4.4", 36 | "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.4.4.tgz", 37 | "integrity": "sha512-kldvB9c+vzimel4yEktlkB08gaJ5DQn9ZuIfFf1kpAw+++5hFwYRWTyKgOhF9LbOWNWGropesYC7WwLja2erhQ==", 38 | "requires": { 39 | "apollo-env": "^0.6.2" 40 | } 41 | }, 42 | "@apollographql/graphql-playground-html": { 43 | "version": "1.6.24", 44 | "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz", 45 | "integrity": "sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ==" 46 | }, 47 | "@protobufjs/aspromise": { 48 | "version": "1.1.2", 49 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 50 | "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" 51 | }, 52 | "@protobufjs/base64": { 53 | "version": "1.1.2", 54 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 55 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 56 | }, 57 | "@protobufjs/codegen": { 58 | "version": "2.0.4", 59 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 60 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 61 | }, 62 | "@protobufjs/eventemitter": { 63 | "version": "1.1.0", 64 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 65 | "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" 66 | }, 67 | "@protobufjs/fetch": { 68 | "version": "1.1.0", 69 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 70 | "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", 71 | "requires": { 72 | "@protobufjs/aspromise": "^1.1.1", 73 | "@protobufjs/inquire": "^1.1.0" 74 | } 75 | }, 76 | "@protobufjs/float": { 77 | "version": "1.0.2", 78 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 79 | "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" 80 | }, 81 | "@protobufjs/inquire": { 82 | "version": "1.1.0", 83 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 84 | "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" 85 | }, 86 | "@protobufjs/path": { 87 | "version": "1.1.2", 88 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 89 | "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" 90 | }, 91 | "@protobufjs/pool": { 92 | "version": "1.1.0", 93 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 94 | "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" 95 | }, 96 | "@protobufjs/utf8": { 97 | "version": "1.1.0", 98 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 99 | "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" 100 | }, 101 | "@types/accepts": { 102 | "version": "1.3.5", 103 | "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", 104 | "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", 105 | "requires": { 106 | "@types/node": "*" 107 | } 108 | }, 109 | "@types/aws-lambda": { 110 | "version": "8.10.46", 111 | "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.46.tgz", 112 | "integrity": "sha512-88E4Hlypo3AE40wslm7N4n09lCIJwgYJm5wsaA3/Vib1xqjC/ANePTaPRpPdj9NzBSpw7Tgon58qGMYEArx4oA==" 113 | }, 114 | "@types/body-parser": { 115 | "version": "1.19.0", 116 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", 117 | "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", 118 | "requires": { 119 | "@types/connect": "*", 120 | "@types/node": "*" 121 | } 122 | }, 123 | "@types/connect": { 124 | "version": "3.4.33", 125 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", 126 | "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", 127 | "requires": { 128 | "@types/node": "*" 129 | } 130 | }, 131 | "@types/cookies": { 132 | "version": "0.7.4", 133 | "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz", 134 | "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==", 135 | "requires": { 136 | "@types/connect": "*", 137 | "@types/express": "*", 138 | "@types/keygrip": "*", 139 | "@types/node": "*" 140 | } 141 | }, 142 | "@types/express": { 143 | "version": "4.17.3", 144 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz", 145 | "integrity": "sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==", 146 | "requires": { 147 | "@types/body-parser": "*", 148 | "@types/express-serve-static-core": "*", 149 | "@types/serve-static": "*" 150 | } 151 | }, 152 | "@types/express-serve-static-core": { 153 | "version": "4.17.2", 154 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz", 155 | "integrity": "sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg==", 156 | "requires": { 157 | "@types/node": "*", 158 | "@types/range-parser": "*" 159 | } 160 | }, 161 | "@types/fs-capacitor": { 162 | "version": "2.0.0", 163 | "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz", 164 | "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==", 165 | "requires": { 166 | "@types/node": "*" 167 | } 168 | }, 169 | "@types/graphql-upload": { 170 | "version": "8.0.3", 171 | "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-8.0.3.tgz", 172 | "integrity": "sha512-hmLg9pCU/GmxBscg8GCr1vmSoEmbItNNxdD5YH2TJkXm//8atjwuprB+xJBK714JG1dkxbbhp5RHX+Pz1KsCMA==", 173 | "requires": { 174 | "@types/express": "*", 175 | "@types/fs-capacitor": "*", 176 | "@types/koa": "*", 177 | "graphql": "^14.5.3" 178 | } 179 | }, 180 | "@types/http-assert": { 181 | "version": "1.5.1", 182 | "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", 183 | "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==" 184 | }, 185 | "@types/keygrip": { 186 | "version": "1.0.2", 187 | "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", 188 | "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" 189 | }, 190 | "@types/koa": { 191 | "version": "2.11.2", 192 | "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.2.tgz", 193 | "integrity": "sha512-2UPelagNNW6bnc1I5kIzluCaheXRA9S+NyOdXEFFj9Az7jc15ek5V03kb8OTbb3tdZ5i2BIJObe86PhHvpMolg==", 194 | "requires": { 195 | "@types/accepts": "*", 196 | "@types/cookies": "*", 197 | "@types/http-assert": "*", 198 | "@types/keygrip": "*", 199 | "@types/koa-compose": "*", 200 | "@types/node": "*" 201 | } 202 | }, 203 | "@types/koa-compose": { 204 | "version": "3.2.5", 205 | "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", 206 | "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", 207 | "requires": { 208 | "@types/koa": "*" 209 | } 210 | }, 211 | "@types/long": { 212 | "version": "4.0.1", 213 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", 214 | "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" 215 | }, 216 | "@types/mime": { 217 | "version": "2.0.1", 218 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", 219 | "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==" 220 | }, 221 | "@types/node": { 222 | "version": "13.9.1", 223 | "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.1.tgz", 224 | "integrity": "sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==" 225 | }, 226 | "@types/node-fetch": { 227 | "version": "2.5.5", 228 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.5.tgz", 229 | "integrity": "sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==", 230 | "requires": { 231 | "@types/node": "*", 232 | "form-data": "^3.0.0" 233 | } 234 | }, 235 | "@types/range-parser": { 236 | "version": "1.2.3", 237 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", 238 | "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" 239 | }, 240 | "@types/serve-static": { 241 | "version": "1.13.3", 242 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", 243 | "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", 244 | "requires": { 245 | "@types/express-serve-static-core": "*", 246 | "@types/mime": "*" 247 | } 248 | }, 249 | "@types/ws": { 250 | "version": "6.0.4", 251 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", 252 | "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", 253 | "requires": { 254 | "@types/node": "*" 255 | } 256 | }, 257 | "@wry/equality": { 258 | "version": "0.1.9", 259 | "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.9.tgz", 260 | "integrity": "sha512-mB6ceGjpMGz1ZTza8HYnrPGos2mC6So4NhS1PtZ8s4Qt0K7fBiIGhpSxUbQmhwcSWE3no+bYxmI2OL6KuXYmoQ==", 261 | "requires": { 262 | "tslib": "^1.9.3" 263 | } 264 | }, 265 | "apollo-cache-control": { 266 | "version": "0.9.0", 267 | "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.9.0.tgz", 268 | "integrity": "sha512-iLT6IT4Ul5cMfBcJAvhpk3a7AD6fXqvFxNmJEPVapVJHbSKYIjra4PTis13sOyN5Y3WQS6a+NRFxAW8+hL3q3Q==", 269 | "requires": { 270 | "apollo-server-env": "^2.4.3", 271 | "graphql-extensions": "^0.11.0" 272 | } 273 | }, 274 | "apollo-datasource": { 275 | "version": "0.7.0", 276 | "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.0.tgz", 277 | "integrity": "sha512-Yja12BgNQhzuFGG/5Nw2MQe0hkuQy2+9er09HxeEyAf2rUDIPnhPrn1MDoZTB8MU7UGfjwITC+1ofzKkkrZobA==", 278 | "requires": { 279 | "apollo-server-caching": "^0.5.1", 280 | "apollo-server-env": "^2.4.3" 281 | } 282 | }, 283 | "apollo-engine-reporting": { 284 | "version": "1.7.0", 285 | "resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-1.7.0.tgz", 286 | "integrity": "sha512-jsjSnoHrRmk4XXK4aFU17YSJILmWsilKRwIeN74QJsSxjn5SCVF4EI/ebf/MNrTHpft8EhShx+wdkAcOD9ivqA==", 287 | "requires": { 288 | "apollo-engine-reporting-protobuf": "^0.4.4", 289 | "apollo-graphql": "^0.4.0", 290 | "apollo-server-caching": "^0.5.1", 291 | "apollo-server-env": "^2.4.3", 292 | "apollo-server-errors": "^2.4.0", 293 | "apollo-server-types": "^0.3.0", 294 | "async-retry": "^1.2.1", 295 | "graphql-extensions": "^0.11.0" 296 | } 297 | }, 298 | "apollo-engine-reporting-protobuf": { 299 | "version": "0.4.4", 300 | "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.4.4.tgz", 301 | "integrity": "sha512-SGrIkUR7Q/VjU8YG98xcvo340C4DaNUhg/TXOtGsMlfiJDzHwVau/Bv6zifAzBafp2lj0XND6Daj5kyT/eSI/w==", 302 | "requires": { 303 | "@apollo/protobufjs": "^1.0.3" 304 | } 305 | }, 306 | "apollo-env": { 307 | "version": "0.6.2", 308 | "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.2.tgz", 309 | "integrity": "sha512-Vb/doL1ZbzkNDJCQ6kYGOrphRx63rMERYo3MT2pzm2pNEdm6AK60InMgJaeh3RLK3cjGllOXFAgP8IY+m+TaEg==", 310 | "requires": { 311 | "@types/node-fetch": "2.5.5", 312 | "core-js": "^3.0.1", 313 | "node-fetch": "^2.2.0", 314 | "sha.js": "^2.4.11" 315 | } 316 | }, 317 | "apollo-graphql": { 318 | "version": "0.4.1", 319 | "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.4.1.tgz", 320 | "integrity": "sha512-dz2wtGeCqUDAKAj4KXLKLZiFY791aoXduul3KcLo8/6SwqWlsuZiPe0oB8mENHZZc/EchCpTMTJZX2ZENsOt2A==", 321 | "requires": { 322 | "apollo-env": "^0.6.2", 323 | "lodash.sortby": "^4.7.0" 324 | } 325 | }, 326 | "apollo-link": { 327 | "version": "1.2.13", 328 | "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.13.tgz", 329 | "integrity": "sha512-+iBMcYeevMm1JpYgwDEIDt/y0BB7VWyvlm/7x+TIPNLHCTCMgcEgDuW5kH86iQZWo0I7mNwQiTOz+/3ShPFmBw==", 330 | "requires": { 331 | "apollo-utilities": "^1.3.0", 332 | "ts-invariant": "^0.4.0", 333 | "tslib": "^1.9.3", 334 | "zen-observable-ts": "^0.8.20" 335 | } 336 | }, 337 | "apollo-server-caching": { 338 | "version": "0.5.1", 339 | "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.1.tgz", 340 | "integrity": "sha512-L7LHZ3k9Ao5OSf2WStvQhxdsNVplRQi7kCAPfqf9Z3GBEnQ2uaL0EgO0hSmtVHfXTbk5CTRziMT1Pe87bXrFIw==", 341 | "requires": { 342 | "lru-cache": "^5.0.0" 343 | } 344 | }, 345 | "apollo-server-core": { 346 | "version": "2.11.0", 347 | "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.11.0.tgz", 348 | "integrity": "sha512-jHLOqwTRlyWzqWNRlwr2M/xfrt+lw2pHtKYyxUGRjWFo8EM5TX1gDcTKtbtvx9p5m+ZBDAhcWp/rpq0vSz4tqg==", 349 | "requires": { 350 | "@apollographql/apollo-tools": "^0.4.3", 351 | "@apollographql/graphql-playground-html": "1.6.24", 352 | "@types/graphql-upload": "^8.0.0", 353 | "@types/ws": "^6.0.0", 354 | "apollo-cache-control": "^0.9.0", 355 | "apollo-datasource": "^0.7.0", 356 | "apollo-engine-reporting": "^1.7.0", 357 | "apollo-server-caching": "^0.5.1", 358 | "apollo-server-env": "^2.4.3", 359 | "apollo-server-errors": "^2.4.0", 360 | "apollo-server-plugin-base": "^0.7.0", 361 | "apollo-server-types": "^0.3.0", 362 | "apollo-tracing": "^0.9.0", 363 | "fast-json-stable-stringify": "^2.0.0", 364 | "graphql-extensions": "^0.11.0", 365 | "graphql-tag": "^2.9.2", 366 | "graphql-tools": "^4.0.0", 367 | "graphql-upload": "^8.0.2", 368 | "sha.js": "^2.4.11", 369 | "subscriptions-transport-ws": "^0.9.11", 370 | "ws": "^6.0.0" 371 | } 372 | }, 373 | "apollo-server-env": { 374 | "version": "2.4.3", 375 | "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.3.tgz", 376 | "integrity": "sha512-23R5Xo9OMYX0iyTu2/qT0EUb+AULCBriA9w8HDfMoChB8M+lFClqUkYtaTTHDfp6eoARLW8kDBhPOBavsvKAjA==", 377 | "requires": { 378 | "node-fetch": "^2.1.2", 379 | "util.promisify": "^1.0.0" 380 | } 381 | }, 382 | "apollo-server-errors": { 383 | "version": "2.4.0", 384 | "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.0.tgz", 385 | "integrity": "sha512-ZouZfr2sGavvI18rgdRcyY2ausRAlVtWNOax9zca8ZG2io86dM59jXBmUVSNlVZSmBsIh45YxYC0eRvr2vmRdg==" 386 | }, 387 | "apollo-server-lambda": { 388 | "version": "2.11.0", 389 | "resolved": "https://registry.npmjs.org/apollo-server-lambda/-/apollo-server-lambda-2.11.0.tgz", 390 | "integrity": "sha512-44jkwT0vKsw8F8/ytC5vOu2mXZlcp1XwAg7QykhqLHi/jKvMe94GeTnhOgZPIHAZwjrEVhFQjEPJdkXw1ccm8A==", 391 | "requires": { 392 | "@apollographql/graphql-playground-html": "1.6.24", 393 | "@types/aws-lambda": "^8.10.31", 394 | "apollo-server-core": "^2.11.0", 395 | "apollo-server-env": "^2.4.3", 396 | "apollo-server-types": "^0.3.0", 397 | "graphql-tools": "^4.0.0" 398 | } 399 | }, 400 | "apollo-server-plugin-base": { 401 | "version": "0.7.0", 402 | "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.7.0.tgz", 403 | "integrity": "sha512-//xgYrBYLQSr92W0z3mYsFGoVz3wxKNsv3KcOUBhbOCGTbjZgP7vHOE1vhHhRcpZKKXmjXTVONdrnNJ+XVGi6A==", 404 | "requires": { 405 | "apollo-server-types": "^0.3.0" 406 | } 407 | }, 408 | "apollo-server-types": { 409 | "version": "0.3.0", 410 | "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.3.0.tgz", 411 | "integrity": "sha512-FMo7kbTkhph9dfIQ3xDbRLObqmdQH9mwSjxhGsX+JxGMRPPXgd3+GZvCeVKOi/udxh//w1otSeAqItjvbj0tfQ==", 412 | "requires": { 413 | "apollo-engine-reporting-protobuf": "^0.4.4", 414 | "apollo-server-caching": "^0.5.1", 415 | "apollo-server-env": "^2.4.3" 416 | } 417 | }, 418 | "apollo-tracing": { 419 | "version": "0.9.0", 420 | "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.9.0.tgz", 421 | "integrity": "sha512-oqspTrf4BLGbKkIk1vF+I31C2v7PPJmF36TFpT/+zJxNvJw54ji4ZMhtytgVqbVldQEintJmdHQIidYBGKmu+g==", 422 | "requires": { 423 | "apollo-server-env": "^2.4.3", 424 | "graphql-extensions": "^0.11.0" 425 | } 426 | }, 427 | "apollo-utilities": { 428 | "version": "1.3.3", 429 | "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.3.tgz", 430 | "integrity": "sha512-F14aX2R/fKNYMvhuP2t9GD9fggID7zp5I96MF5QeKYWDWTrkRdHRp4+SVfXUVN+cXOaB/IebfvRtzPf25CM0zw==", 431 | "requires": { 432 | "@wry/equality": "^0.1.2", 433 | "fast-json-stable-stringify": "^2.0.0", 434 | "ts-invariant": "^0.4.0", 435 | "tslib": "^1.10.0" 436 | } 437 | }, 438 | "async-limiter": { 439 | "version": "1.0.1", 440 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 441 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" 442 | }, 443 | "async-retry": { 444 | "version": "1.3.1", 445 | "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.1.tgz", 446 | "integrity": "sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==", 447 | "requires": { 448 | "retry": "0.12.0" 449 | } 450 | }, 451 | "asynckit": { 452 | "version": "0.4.0", 453 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 454 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 455 | }, 456 | "backo2": { 457 | "version": "1.0.2", 458 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 459 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 460 | }, 461 | "base64-js": { 462 | "version": "1.3.1", 463 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 464 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 465 | }, 466 | "btoa-lite": { 467 | "version": "1.0.0", 468 | "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", 469 | "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=" 470 | }, 471 | "busboy": { 472 | "version": "0.3.1", 473 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", 474 | "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", 475 | "requires": { 476 | "dicer": "0.3.0" 477 | } 478 | }, 479 | "combined-stream": { 480 | "version": "1.0.8", 481 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 482 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 483 | "requires": { 484 | "delayed-stream": "~1.0.0" 485 | } 486 | }, 487 | "core-js": { 488 | "version": "3.6.4", 489 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", 490 | "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==" 491 | }, 492 | "cross-fetch": { 493 | "version": "3.0.4", 494 | "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz", 495 | "integrity": "sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==", 496 | "requires": { 497 | "node-fetch": "2.6.0", 498 | "whatwg-fetch": "3.0.0" 499 | } 500 | }, 501 | "define-properties": { 502 | "version": "1.1.3", 503 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 504 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 505 | "requires": { 506 | "object-keys": "^1.0.12" 507 | } 508 | }, 509 | "delayed-stream": { 510 | "version": "1.0.0", 511 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 512 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 513 | }, 514 | "depd": { 515 | "version": "1.1.2", 516 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 517 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 518 | }, 519 | "deprecated-decorator": { 520 | "version": "0.1.6", 521 | "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", 522 | "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=" 523 | }, 524 | "dicer": { 525 | "version": "0.3.0", 526 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", 527 | "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", 528 | "requires": { 529 | "streamsearch": "0.1.2" 530 | } 531 | }, 532 | "dotenv": { 533 | "version": "8.2.0", 534 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", 535 | "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" 536 | }, 537 | "es-abstract": { 538 | "version": "1.17.4", 539 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", 540 | "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", 541 | "requires": { 542 | "es-to-primitive": "^1.2.1", 543 | "function-bind": "^1.1.1", 544 | "has": "^1.0.3", 545 | "has-symbols": "^1.0.1", 546 | "is-callable": "^1.1.5", 547 | "is-regex": "^1.0.5", 548 | "object-inspect": "^1.7.0", 549 | "object-keys": "^1.1.1", 550 | "object.assign": "^4.1.0", 551 | "string.prototype.trimleft": "^2.1.1", 552 | "string.prototype.trimright": "^2.1.1" 553 | } 554 | }, 555 | "es-to-primitive": { 556 | "version": "1.2.1", 557 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 558 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 559 | "requires": { 560 | "is-callable": "^1.1.4", 561 | "is-date-object": "^1.0.1", 562 | "is-symbol": "^1.0.2" 563 | } 564 | }, 565 | "eventemitter3": { 566 | "version": "3.1.2", 567 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", 568 | "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" 569 | }, 570 | "fast-json-stable-stringify": { 571 | "version": "2.1.0", 572 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 573 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" 574 | }, 575 | "faunadb": { 576 | "version": "2.13.0", 577 | "resolved": "https://registry.npmjs.org/faunadb/-/faunadb-2.13.0.tgz", 578 | "integrity": "sha512-iWLgDW7+9cnPkRE4WfV75NxV3Lz3EEp3ytvYUXdzqWfpGI0bVD7tDMjst1mXrDb8WjPCQRzTj6S5Qer87ftN0Q==", 579 | "requires": { 580 | "base64-js": "^1.2.0", 581 | "btoa-lite": "^1.0.0", 582 | "cross-fetch": "^3.0.4", 583 | "dotenv": "^8.2.0", 584 | "fn-annotate": "^1.1.3", 585 | "object-assign": "^4.1.0", 586 | "url-parse": "^1.4.7", 587 | "util-deprecate": "^1.0.2" 588 | } 589 | }, 590 | "fn-annotate": { 591 | "version": "1.2.0", 592 | "resolved": "https://registry.npmjs.org/fn-annotate/-/fn-annotate-1.2.0.tgz", 593 | "integrity": "sha1-KNoAARfephhC/mHzU/Qc9Mk6en4=" 594 | }, 595 | "form-data": { 596 | "version": "3.0.0", 597 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", 598 | "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", 599 | "requires": { 600 | "asynckit": "^0.4.0", 601 | "combined-stream": "^1.0.8", 602 | "mime-types": "^2.1.12" 603 | } 604 | }, 605 | "fs-capacitor": { 606 | "version": "2.0.4", 607 | "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", 608 | "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==" 609 | }, 610 | "function-bind": { 611 | "version": "1.1.1", 612 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 613 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 614 | }, 615 | "graphql": { 616 | "version": "14.6.0", 617 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.6.0.tgz", 618 | "integrity": "sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg==", 619 | "requires": { 620 | "iterall": "^1.2.2" 621 | } 622 | }, 623 | "graphql-extensions": { 624 | "version": "0.11.0", 625 | "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.11.0.tgz", 626 | "integrity": "sha512-zd4qfUiJoYBx2MwJusM36SEJ+YmJ1ki8YF8nlm9mgaPDUzsnmFq4lxULxUfhLAXFwZw7MbEN2vV4V6WiNgSJLg==", 627 | "requires": { 628 | "@apollographql/apollo-tools": "^0.4.3", 629 | "apollo-server-env": "^2.4.3", 630 | "apollo-server-types": "^0.3.0" 631 | } 632 | }, 633 | "graphql-tag": { 634 | "version": "2.10.3", 635 | "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.3.tgz", 636 | "integrity": "sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA==" 637 | }, 638 | "graphql-tools": { 639 | "version": "4.0.7", 640 | "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.7.tgz", 641 | "integrity": "sha512-rApl8sT8t/W1uQRcwzxMYyUBiCl/XicluApiDkNze5TX/GR0BSTQMjM2UcRGdTmkbsb1Eqq6afkyyeG/zMxZYQ==", 642 | "requires": { 643 | "apollo-link": "^1.2.3", 644 | "apollo-utilities": "^1.0.1", 645 | "deprecated-decorator": "^0.1.6", 646 | "iterall": "^1.1.3", 647 | "uuid": "^3.1.0" 648 | } 649 | }, 650 | "graphql-upload": { 651 | "version": "8.1.0", 652 | "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.1.0.tgz", 653 | "integrity": "sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q==", 654 | "requires": { 655 | "busboy": "^0.3.1", 656 | "fs-capacitor": "^2.0.4", 657 | "http-errors": "^1.7.3", 658 | "object-path": "^0.11.4" 659 | } 660 | }, 661 | "has": { 662 | "version": "1.0.3", 663 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 664 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 665 | "requires": { 666 | "function-bind": "^1.1.1" 667 | } 668 | }, 669 | "has-symbols": { 670 | "version": "1.0.1", 671 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 672 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" 673 | }, 674 | "http-errors": { 675 | "version": "1.7.3", 676 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", 677 | "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", 678 | "requires": { 679 | "depd": "~1.1.2", 680 | "inherits": "2.0.4", 681 | "setprototypeof": "1.1.1", 682 | "statuses": ">= 1.5.0 < 2", 683 | "toidentifier": "1.0.0" 684 | } 685 | }, 686 | "inherits": { 687 | "version": "2.0.4", 688 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 689 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 690 | }, 691 | "is-callable": { 692 | "version": "1.1.5", 693 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", 694 | "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" 695 | }, 696 | "is-date-object": { 697 | "version": "1.0.2", 698 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 699 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" 700 | }, 701 | "is-regex": { 702 | "version": "1.0.5", 703 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", 704 | "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", 705 | "requires": { 706 | "has": "^1.0.3" 707 | } 708 | }, 709 | "is-symbol": { 710 | "version": "1.0.3", 711 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 712 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 713 | "requires": { 714 | "has-symbols": "^1.0.1" 715 | } 716 | }, 717 | "iterall": { 718 | "version": "1.3.0", 719 | "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", 720 | "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" 721 | }, 722 | "lodash.sortby": { 723 | "version": "4.7.0", 724 | "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", 725 | "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" 726 | }, 727 | "long": { 728 | "version": "4.0.0", 729 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 730 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 731 | }, 732 | "lru-cache": { 733 | "version": "5.1.1", 734 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 735 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 736 | "requires": { 737 | "yallist": "^3.0.2" 738 | } 739 | }, 740 | "mime-db": { 741 | "version": "1.43.0", 742 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 743 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 744 | }, 745 | "mime-types": { 746 | "version": "2.1.26", 747 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 748 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 749 | "requires": { 750 | "mime-db": "1.43.0" 751 | } 752 | }, 753 | "node-fetch": { 754 | "version": "2.6.0", 755 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", 756 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" 757 | }, 758 | "object-assign": { 759 | "version": "4.1.1", 760 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 761 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 762 | }, 763 | "object-inspect": { 764 | "version": "1.7.0", 765 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 766 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" 767 | }, 768 | "object-keys": { 769 | "version": "1.1.1", 770 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 771 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" 772 | }, 773 | "object-path": { 774 | "version": "0.11.4", 775 | "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", 776 | "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" 777 | }, 778 | "object.assign": { 779 | "version": "4.1.0", 780 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 781 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 782 | "requires": { 783 | "define-properties": "^1.1.2", 784 | "function-bind": "^1.1.1", 785 | "has-symbols": "^1.0.0", 786 | "object-keys": "^1.0.11" 787 | } 788 | }, 789 | "object.getownpropertydescriptors": { 790 | "version": "2.1.0", 791 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", 792 | "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", 793 | "requires": { 794 | "define-properties": "^1.1.3", 795 | "es-abstract": "^1.17.0-next.1" 796 | } 797 | }, 798 | "querystringify": { 799 | "version": "2.1.1", 800 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", 801 | "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" 802 | }, 803 | "requires-port": { 804 | "version": "1.0.0", 805 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 806 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" 807 | }, 808 | "retry": { 809 | "version": "0.12.0", 810 | "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", 811 | "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" 812 | }, 813 | "safe-buffer": { 814 | "version": "5.2.0", 815 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 816 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 817 | }, 818 | "setprototypeof": { 819 | "version": "1.1.1", 820 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 821 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 822 | }, 823 | "sha.js": { 824 | "version": "2.4.11", 825 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", 826 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", 827 | "requires": { 828 | "inherits": "^2.0.1", 829 | "safe-buffer": "^5.0.1" 830 | } 831 | }, 832 | "statuses": { 833 | "version": "1.5.0", 834 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 835 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 836 | }, 837 | "streamsearch": { 838 | "version": "0.1.2", 839 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", 840 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" 841 | }, 842 | "string.prototype.trimleft": { 843 | "version": "2.1.1", 844 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", 845 | "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", 846 | "requires": { 847 | "define-properties": "^1.1.3", 848 | "function-bind": "^1.1.1" 849 | } 850 | }, 851 | "string.prototype.trimright": { 852 | "version": "2.1.1", 853 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", 854 | "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", 855 | "requires": { 856 | "define-properties": "^1.1.3", 857 | "function-bind": "^1.1.1" 858 | } 859 | }, 860 | "subscriptions-transport-ws": { 861 | "version": "0.9.16", 862 | "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz", 863 | "integrity": "sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw==", 864 | "requires": { 865 | "backo2": "^1.0.2", 866 | "eventemitter3": "^3.1.0", 867 | "iterall": "^1.2.1", 868 | "symbol-observable": "^1.0.4", 869 | "ws": "^5.2.0" 870 | }, 871 | "dependencies": { 872 | "ws": { 873 | "version": "5.2.2", 874 | "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", 875 | "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", 876 | "requires": { 877 | "async-limiter": "~1.0.0" 878 | } 879 | } 880 | } 881 | }, 882 | "symbol-observable": { 883 | "version": "1.2.0", 884 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", 885 | "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" 886 | }, 887 | "toidentifier": { 888 | "version": "1.0.0", 889 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 890 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 891 | }, 892 | "ts-invariant": { 893 | "version": "0.4.4", 894 | "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", 895 | "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", 896 | "requires": { 897 | "tslib": "^1.9.3" 898 | } 899 | }, 900 | "tslib": { 901 | "version": "1.11.1", 902 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", 903 | "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" 904 | }, 905 | "url-parse": { 906 | "version": "1.4.7", 907 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", 908 | "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", 909 | "requires": { 910 | "querystringify": "^2.1.1", 911 | "requires-port": "^1.0.0" 912 | } 913 | }, 914 | "util-deprecate": { 915 | "version": "1.0.2", 916 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 917 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 918 | }, 919 | "util.promisify": { 920 | "version": "1.0.1", 921 | "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", 922 | "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", 923 | "requires": { 924 | "define-properties": "^1.1.3", 925 | "es-abstract": "^1.17.2", 926 | "has-symbols": "^1.0.1", 927 | "object.getownpropertydescriptors": "^2.1.0" 928 | } 929 | }, 930 | "uuid": { 931 | "version": "3.4.0", 932 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 933 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 934 | }, 935 | "whatwg-fetch": { 936 | "version": "3.0.0", 937 | "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", 938 | "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" 939 | }, 940 | "ws": { 941 | "version": "6.2.1", 942 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", 943 | "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", 944 | "requires": { 945 | "async-limiter": "~1.0.0" 946 | } 947 | }, 948 | "yallist": { 949 | "version": "3.1.1", 950 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 951 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 952 | }, 953 | "zen-observable": { 954 | "version": "0.8.15", 955 | "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", 956 | "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" 957 | }, 958 | "zen-observable-ts": { 959 | "version": "0.8.20", 960 | "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.20.tgz", 961 | "integrity": "sha512-2rkjiPALhOtRaDX6pWyNqK1fnP5KkJJybYebopNSn6wDG1lxBoFs2+nwwXKoA6glHIrtwrfBBy6da0stkKtTAA==", 962 | "requires": { 963 | "tslib": "^1.9.3", 964 | "zen-observable": "^0.8.0" 965 | } 966 | } 967 | } 968 | } 969 | -------------------------------------------------------------------------------- /functions/apollo-graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apollo-graphql", 3 | "version": "1.0.0", 4 | "description": "netlify functions:create - set up for apollo graphql", 5 | "main": "apollo-graphql.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "netlify", 11 | "serverless", 12 | "js", 13 | "apollo" 14 | ], 15 | "author": "Netlify", 16 | "license": "MIT", 17 | "dependencies": { 18 | "apollo-server-lambda": "^2.4.8", 19 | "graphql": "^14.1.1", 20 | "dotenv": "^8.2.0", 21 | "faunadb": "^2.13.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | const React = require("react") 2 | const { client } = require("./src/client") 3 | const { ApolloProvider } = require("@apollo/react-hooks") 4 | 5 | const { Identity } = require("./src/components/Identity") 6 | 7 | const { SkinContextProvider } = require("./src/context") 8 | 9 | const anchorScroll = location => { 10 | // only get the anchors that aren't part of the nav. h5 is importatnt here, check the linked headings in mdx 11 | const anchor = document.querySelectorAll(`h5 > a[href="${location.hash}"]`)[0] 12 | 13 | if (location && location.hash && anchor) { 14 | // as above 15 | const item = document.querySelectorAll(`h5 > a[href="${location.hash}"]`)[0] 16 | .offsetTop 17 | 18 | const mainNavHeight = document.querySelector(`header`).offsetHeight * 2.2 19 | 20 | setTimeout(() => { 21 | window.scrollTo({ 22 | top: item - mainNavHeight, 23 | behavior: "smooth", 24 | }) 25 | }, 50) 26 | } 27 | } 28 | 29 | exports.shouldUpdateScroll = ({ routerProps: { location } }) => { 30 | if (location && location.action === "PUSH") { 31 | setTimeout(() => window.scrollTo({ top: 0 }), 250) 32 | } 33 | 34 | anchorScroll(location) 35 | return false 36 | } 37 | 38 | exports.onRouteUpdate = ({ location }) => { 39 | anchorScroll(location) 40 | return true 41 | } 42 | 43 | exports.wrapRootElement = ({ element }) => ( 44 | 45 | 46 | {element} 47 | 48 | 49 | ) 50 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Skin UI`, 4 | description: `A Theme UI Live Preview and Code Editor`, 5 | keywords: [`gatsby`, `gatsbyjs`, `theme-ui`], 6 | url: `https://www.skin-ui.com`, 7 | ogImage: `images/skin-ui-open-graph-image.jpg`, 8 | bgImage: `images/skin-ui-background-image.jpg`, 9 | lang: `en`, 10 | author: `@pauliescanlon`, 11 | config: { 12 | sidebarWidth: 220, 13 | drawerWidth: 320, 14 | editorCollapseWidth: 60, 15 | }, 16 | }, 17 | plugins: [ 18 | `gatsby-plugin-react-helmet`, 19 | { 20 | resolve: `gatsby-plugin-mdx`, 21 | options: { 22 | extensions: [`.mdx`, `.md`], 23 | }, 24 | }, 25 | { 26 | resolve: "gatsby-plugin-google-analytics", 27 | options: { 28 | trackingId: "UA-76055934-9", 29 | }, 30 | }, 31 | ], 32 | } 33 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulieScanlon/skin-ui/4c86c5783e392f6b1a8f7fdb6698d0d7bf63de5e/gatsby-node.js -------------------------------------------------------------------------------- /gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | export { wrapRootElement } from "./gatsby-browser" 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config() 2 | const faunadb = require("faunadb") 3 | const q = faunadb.query 4 | 5 | const client = new faunadb.Client({ secret: process.env.FAUNA }) 6 | 7 | async function run() { 8 | // get theme by id 9 | // const results = await client.query( 10 | // q.Get(q.Ref(q.Collection("skin-ui-themes"), "260230131177488898")) 11 | // ) 12 | // get all public themes 13 | // the false string relates to the theme_is_private data value 14 | const results = await client.query( 15 | q.Paginate(q.Match(q.Index("get-all-themes"), false)) 16 | ) 17 | // get light / dark themes 18 | // const results = await client.query( 19 | // q.Paginate(q.Match(q.Index("get-themes-by-style"), "dark")) 20 | // ) 21 | // get themes by user 22 | // const results = await client.query( 23 | // q.Paginate( 24 | // q.Match( 25 | // q.Index("get-themes-by-user"), 26 | // "dbbe4b2e-0cc3-41ce-aa81-84d63bb07727" 27 | // ) 28 | // ) 29 | // ) 30 | // update a value for a given id 31 | // const results = await client.query( 32 | // q.Update(q.Ref(q.Collection("skin-ui-themes"), "260230901859877387"), { 33 | // data: { theme_name: "Pauls test theme 1" }, 34 | // }) 35 | // ) 36 | // create a new theme / user 37 | // const results = await client.query( 38 | // q.Create(q.Collection("skin-ui-themes"), { 39 | // data: { 40 | // user_id: "789", 41 | // theme_author: "Paul", 42 | // theme_name: "Pauls third theme", 43 | // theme_description: "This is the description for Pauls third theme", 44 | // theme_style: "Dark", 45 | // theme_is_private: false, 46 | // }, 47 | // }) 48 | // ) 49 | 50 | // delete theme by id 51 | // const results = await client.query( 52 | // q.Delete(q.Ref(q.Collection("skin-ui-themes"), "260951562436739586")) 53 | // ) 54 | 55 | console.log("results: ", JSON.stringify(results, null, 2)) 56 | // console.log("results.ref: ", results.data) 57 | } 58 | 59 | run() 60 | 61 | // console.log("hello from index.js") 62 | // console.log(process.env.FAUNA) 63 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "yarn build && cd functions/apollo-graphql && yarn" 3 | functions = "functions" 4 | publish = "public/" 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "skin-ui", 3 | "private": true, 4 | "description": "...", 5 | "version": "0.1.0", 6 | "author": "Paul Scanlon ", 7 | "dependencies": { 8 | "@apollo/react-hooks": "^3.1.3", 9 | "@mdx-js/mdx": "^1.5.7", 10 | "@mdx-js/react": "^1.5.7", 11 | "@theme-ui/color": "^0.3.1", 12 | "@theme-ui/components": "0.3.1", 13 | "apollo-boost": "^0.4.7", 14 | "apollo-cache-inmemory": "^1.6.5", 15 | "apollo-client": "^2.6.8", 16 | "clipboard-copy": "^3.1.0", 17 | "codemirror": "^5.52.0", 18 | "faunadb": "^2.13.0", 19 | "gatsby": "^2.19.40", 20 | "gatsby-plugin-google-analytics": "^2.1.37", 21 | "gatsby-plugin-google-fonts": "^1.0.1", 22 | "gatsby-plugin-mdx": "^1.0.74", 23 | "gatsby-plugin-react-helmet": "^3.1.23", 24 | "graphql": "^14.6.0", 25 | "isomorphic-fetch": "^2.2.1", 26 | "netlify-identity-widget": "^1.5.6", 27 | "object-key-validator": "^1.1.2", 28 | "prop-types": "^15.7.2", 29 | "query-string": "^6.11.1", 30 | "react": "^16.13.0", 31 | "react-codemirror": "^1.0.0", 32 | "react-codemirror2": "^7.0.0", 33 | "react-dom": "^16.13.0", 34 | "react-helmet": "^5.2.1", 35 | "react-visibility-sensor": "^5.1.1", 36 | "theme-ui": "0.3.1", 37 | "unique-names-generator": "^4.2.0" 38 | }, 39 | "devDependencies": { 40 | "netlify-lambda": "^1.6.3", 41 | "prettier": "^1.19.1" 42 | }, 43 | "keywords": [ 44 | "gatsby" 45 | ], 46 | "license": "MIT", 47 | "scripts": { 48 | "build": "gatsby build", 49 | "develop": "gatsby develop", 50 | "format": "prettier --write \"**/*.{js,jsx,json,md}\"", 51 | "start": "npm run develop", 52 | "serve": "gatsby serve", 53 | "clean": "gatsby clean", 54 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1", 55 | "postinstall": "netlify-lambda install" 56 | }, 57 | "repository": { 58 | "type": "git", 59 | "url": "https://github.com/PaulieScanlon/skin-ui" 60 | }, 61 | "bugs": { 62 | "url": "https://github.com/PaulieScanlon/skin-ui/issues" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | import { ApolloClient } from "apollo-client" 2 | import { InMemoryCache } from "apollo-cache-inmemory" 3 | import { HttpLink } from "apollo-link-http" 4 | import fetch from "isomorphic-fetch" 5 | 6 | export const client = new ApolloClient({ 7 | cache: new InMemoryCache(), 8 | link: new HttpLink({ 9 | uri: "/.netlify/functions/apollo-graphql", 10 | }), 11 | fetch, 12 | }) 13 | -------------------------------------------------------------------------------- /src/components/Application/Application.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { memo, useContext } from "react" 3 | import PropTypes from "prop-types" 4 | import { jsx } from "theme-ui" 5 | import { Flex, Box } from "@theme-ui/components" 6 | 7 | import { Editor } from "../Editor" 8 | import { EditorToolbar } from "../EditorToolbar" 9 | import { Preview } from "../Preview" 10 | import { PreviewToolbar } from "../PreviewToolbar" 11 | import { Source } from "../Source" 12 | 13 | import { SkinContext } from "../../context" 14 | 15 | import { ThemeWrapper } from "../ThemeWrapper" 16 | import { useSiteMetadata } from "../../data/useSiteMetadata" 17 | 18 | export const Application = memo(({ mdx }) => { 19 | const { 20 | site: { 21 | siteMetadata: { 22 | config: { sidebarWidth, editorCollapseWidth }, 23 | }, 24 | }, 25 | } = useSiteMetadata() 26 | 27 | const { state } = useContext(SkinContext) 28 | 29 | const conditionalWidth = state.isFullScreen ? "100%" : "60%" 30 | 31 | return ( 32 | 33 | 34 | {!state.isFullScreen && ( 35 | 52 | 53 | 54 | 55 | )} 56 | 75 | 76 | {state.isSourceVisible ? : } 77 | 78 | 79 | 80 | ) 81 | }) 82 | 83 | Application.propTypes = { 84 | /** React children passed from mdx */ 85 | mdx: PropTypes.any, 86 | } 87 | -------------------------------------------------------------------------------- /src/components/Application/index.js: -------------------------------------------------------------------------------- 1 | export { Application } from "./Application" 2 | -------------------------------------------------------------------------------- /src/components/Drawer/Drawer.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext, useState, memo, Fragment } from "react" 3 | import PropTypes from "prop-types" 4 | import { jsx } from "theme-ui" 5 | import { darken } from "@theme-ui/color" 6 | import VisibilitySensor from "react-visibility-sensor" 7 | 8 | import { Close } from "@theme-ui/components" 9 | 10 | import { SkinContext } from "../../context" 11 | 12 | import { ThemeWrapper } from "../ThemeWrapper" 13 | 14 | import { SET_IS_SETTINGS_OPEN } from "../../utils/const" 15 | 16 | import { useSiteMetadata } from "../../data/useSiteMetadata" 17 | 18 | export const Drawer = memo(({ children }) => { 19 | const { 20 | site: { 21 | siteMetadata: { 22 | config: { drawerWidth }, 23 | }, 24 | }, 25 | } = useSiteMetadata() 26 | 27 | const { state, dispatch } = useContext(SkinContext) 28 | 29 | const [isElementVisible, setIsElementVisible] = useState(true) 30 | 31 | const handleVisibilityChange = isVisible => { 32 | setIsElementVisible(isVisible) 33 | } 34 | 35 | return ( 36 | 37 |
theme.zIndices.drawer, 47 | }} 48 | > 49 | 50 | 51 |
`0px ${theme.space[3]}px`, 59 | }} 60 | > 61 | 65 | dispatch({ 66 | type: SET_IS_SETTINGS_OPEN, 67 | isSettingsOpen: state.isSettingsOpen, 68 | }) 69 | } 70 | /> 71 |
72 |
`calc(100% - ${theme.sizes.header}px)`, 75 | color: "gray", 76 | px: 3, 77 | overflow: "auto", 78 | }} 79 | > 80 | {children(isElementVisible)} 81 |
82 |
83 |
84 |
85 |
86 | ) 87 | }) 88 | 89 | Drawer.propTypes = { 90 | /** children nav items from parent */ 91 | children: PropTypes.any, 92 | } 93 | -------------------------------------------------------------------------------- /src/components/Drawer/index.js: -------------------------------------------------------------------------------- 1 | export { Drawer } from "./Drawer" 2 | -------------------------------------------------------------------------------- /src/components/Dropdown/Dropdown.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useState, useEffect } from "react" 3 | import PropTypes from "prop-types" 4 | import { jsx } from "theme-ui" 5 | import { Box } from "@theme-ui/components" 6 | 7 | export const Dropdown = ({ trigger, children, ...sx }) => { 8 | const [isMenuOpen, setIsMenuOpen] = useState(false) 9 | 10 | const handleClickedOutside = () => { 11 | setIsMenuOpen(false) 12 | } 13 | 14 | useEffect(() => { 15 | if (isMenuOpen) { 16 | document.addEventListener("click", handleClickedOutside) 17 | } else { 18 | document.removeEventListener("click", handleClickedOutside) 19 | } 20 | 21 | return () => document.removeEventListener("click", handleClickedOutside) 22 | }, [isMenuOpen]) 23 | 24 | return ( 25 | 32 | {trigger(isMenuOpen, setIsMenuOpen)} 33 | {isMenuOpen && ( 34 | 41 | {children} 42 | 43 | )} 44 | 45 | ) 46 | } 47 | 48 | Dropdown.prototypes = { 49 | /** trigger */ 50 | trigger: PropTypes.func.isRequired, 51 | /** jsx sx spread */ 52 | sx: PropTypes.any, 53 | /** children */ 54 | children: PropTypes.node, 55 | } 56 | -------------------------------------------------------------------------------- /src/components/Dropdown/index.js: -------------------------------------------------------------------------------- 1 | export { Dropdown } from "./Dropdown" 2 | -------------------------------------------------------------------------------- /src/components/Editor/Editor.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext, useState, useEffect } from "react" 3 | import { jsx } from "theme-ui" 4 | import { Box } from "@theme-ui/components" 5 | import { Controlled as CodeMirror } from "react-codemirror2" 6 | 7 | import { SkinContext } from "../../context" 8 | 9 | import { ThemeWrapper } from "../ThemeWrapper" 10 | 11 | if (typeof window !== `undefined`) { 12 | require("codemirror/mode/javascript/javascript") 13 | require("codemirror/theme/isotope.css") 14 | } 15 | 16 | import { UPDATE_DEFAULT_THEME_OBJECT } from "../../utils/const" 17 | import { checkAndReplaceQuotes } from "../../utils/checkAndReplaceQuotes" 18 | import { checkAndAddQuotes } from "../../utils/checkAndAddQuotes" 19 | 20 | export const Editor = () => { 21 | const { state, dispatch } = useContext(SkinContext) 22 | 23 | const handleEditorChange = value => { 24 | dispatch({ 25 | type: UPDATE_DEFAULT_THEME_OBJECT, 26 | defaultThemeObject: value, 27 | }) 28 | } 29 | 30 | const conditionalHeight = state.isEditorHeightCollapsed ? "50vh" : "100%" 31 | 32 | return ( 33 | 34 | [ 38 | `${conditionalHeight}`, 39 | `${conditionalHeight}`, 40 | `${conditionalHeight}`, 41 | `calc(100vh - ${theme.sizes.doubleHeader}px)`, 42 | ], 43 | ["> .react-codemirror2"]: { 44 | textarea: { 45 | opacity: 0, 46 | }, 47 | ["> .CodeMirror"]: { 48 | height: theme => [ 49 | `${conditionalHeight}`, 50 | `${conditionalHeight}`, 51 | `${conditionalHeight}`, 52 | `calc(100vh - ${theme.sizes.doubleHeader}px)`, 53 | ], 54 | }, 55 | }, 56 | }} 57 | > 58 | 61 | handleEditorChange(checkAndAddQuotes(value)) 62 | } 63 | options={{ 64 | mode: { name: "javascript", json: true }, 65 | theme: "isotope", 66 | lineNumbers: true, 67 | viewportMargin: Infinity, 68 | tabindex: -1, 69 | }} 70 | /> 71 | 72 | 73 | ) 74 | } 75 | -------------------------------------------------------------------------------- /src/components/Editor/index.js: -------------------------------------------------------------------------------- 1 | export { Editor } from "./Editor" 2 | -------------------------------------------------------------------------------- /src/components/EditorToolbar/EditorToolbar.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext, Fragment } from "react" 3 | import { jsx } from "theme-ui" 4 | import { Flex, Box, Button, Spinner } from "@theme-ui/components" 5 | import copy from "clipboard-copy" 6 | 7 | import { useMutation } from "@apollo/react-hooks" 8 | 9 | import { 10 | uniqueNamesGenerator, 11 | adjectives, 12 | colors, 13 | animals, 14 | } from "unique-names-generator" 15 | 16 | import { SkinContext } from "../../context" 17 | 18 | import { Toolbar } from "../Toolbar" 19 | import { IconButton } from "../IconButton" 20 | import { SvgIcon } from "../SvgIcon" 21 | 22 | import { checkAndReplaceQuotes } from "../../utils/checkAndReplaceQuotes" 23 | 24 | import { 25 | EXPAND_ICON, 26 | COLLAPSE_ICON, 27 | SETTINGS_ICON, 28 | COPY_ICON, 29 | SAVE_ICON, 30 | } from "../../utils/iconPaths" 31 | import { 32 | SET_IS_EDITOR_WIDTH_COLLAPSED, 33 | SET_IS_EDITOR_HEIGHT_COLLAPSED, 34 | SET_IS_SETTINGS_OPEN, 35 | } from "../../utils/const" 36 | 37 | import { SET_DATABASE_THEME_BY_ID } from "../../utils/const" 38 | import { UPDATE_THEME_BY_ID, FORK_THEME_WITH_ID } from "../../utils/graphql" 39 | 40 | const nameConfig = { 41 | dictionaries: [adjectives, colors, animals], 42 | separator: "-", 43 | length: 3, 44 | } 45 | 46 | export const EditorToolbar = () => { 47 | const { state, dispatch } = useContext(SkinContext) 48 | 49 | const [updateThemeById, { loading, error }] = useMutation( 50 | UPDATE_THEME_BY_ID, 51 | { 52 | onCompleted({ updateThemeById }) { 53 | dispatch({ 54 | type: SET_DATABASE_THEME_BY_ID, 55 | databaseThemeById: { 56 | ...updateThemeById, 57 | }, 58 | }) 59 | }, 60 | } 61 | ) 62 | 63 | const [forkThemeWithId] = useMutation(FORK_THEME_WITH_ID, { 64 | onCompleted({ forkThemeWithId }) { 65 | location.search = `?theme_id=${forkThemeWithId.ref}` 66 | 67 | dispatch({ 68 | type: SET_DATABASE_THEME_BY_ID, 69 | databaseThemeById: { 70 | ...forkThemeWithId, 71 | }, 72 | }) 73 | }, 74 | }) 75 | 76 | const handleSave = () => { 77 | updateThemeById({ 78 | variables: { 79 | theme_id: state.databaseThemeById.ref, 80 | theme_name: state.databaseThemeById.theme_name, 81 | theme_description: state.databaseThemeById.theme_description, 82 | theme_style: state.databaseThemeById.theme_style, 83 | theme_object: state.defaultThemeObject, 84 | }, 85 | }) 86 | } 87 | 88 | const handleFork = () => { 89 | forkThemeWithId({ 90 | variables: { 91 | user_id: state.user.id, 92 | theme_author: state.user.user_metadata.full_name, 93 | theme_name: uniqueNamesGenerator(nameConfig), 94 | theme_description: "A fork of the default theme", 95 | theme_style: "light", 96 | theme_object: state.defaultThemeObject, 97 | }, 98 | }) 99 | } 100 | 101 | // TODO Netlify env vars are undefined, dunno why 102 | // console.log("SKIN_UI_USER_ID: ", process.env.SKIN_UI_USER_ID) 103 | // console.log(state.user && state.user.id) 104 | 105 | return ( 106 | 107 | 114 | 120 | 125 | dispatch({ 126 | type: SET_IS_EDITOR_HEIGHT_COLLAPSED, 127 | isEditorHeightCollapsed: state.isEditorHeightCollapsed, 128 | }) 129 | } 130 | sx={{ 131 | display: ["block", "block", "block", "none"], 132 | transform: "rotate(-90deg)", 133 | }} 134 | aria-label={`${ 135 | state.isEditorHeightCollapsed ? "Expand" : "Collapse" 136 | } Editor`} 137 | iconPath={ 138 | state.isEditorHeightCollapsed ? COLLAPSE_ICON : EXPAND_ICON 139 | } 140 | /> 141 | 142 | 147 | dispatch({ 148 | type: SET_IS_EDITOR_WIDTH_COLLAPSED, 149 | isEditorWidthCollapsed: state.isEditorWidthCollapsed, 150 | }) 151 | } 152 | sx={{ 153 | display: ["none", "none", "none", "block"], 154 | }} 155 | aria-label={`${ 156 | state.isEditorWidthCollapsed ? "Expand" : "Collapse" 157 | } Editor`} 158 | iconPath={ 159 | state.isEditorWidthCollapsed ? COLLAPSE_ICON : EXPAND_ICON 160 | } 161 | /> 162 | 163 | 169 | 172 | copy( 173 | `export default \n${checkAndReplaceQuotes( 174 | state.defaultThemeObject 175 | )}` 176 | ) 177 | } 178 | aria-label="Copy Theme UI object" 179 | iconPath={COPY_ICON} 180 | sx={{ 181 | color: "primary", 182 | }} 183 | /> 184 | 185 | {state.user ? ( 186 | 187 | {state.isUserOwner || 188 | (state.user.id === process.env.SKIN_UI_USER_ID && ( 189 | 190 | {loading ? ( 191 | 194 | ) : ( 195 | handleSave()} 198 | aria-label="Save" 199 | iconPath={SAVE_ICON} 200 | sx={{ 201 | color: "primary", 202 | }} 203 | /> 204 | )} 205 | 206 | ))} 207 | 208 | ) : null} 209 | 210 | {state.user ? ( 211 | 212 | {state.isUserOwner || 213 | state.user.id === process.env.SKIN_UI_USER_ID ? ( 214 | 239 | ) : ( 240 | 248 | )} 249 | 250 | ) : null} 251 | 252 | 253 | 254 | ) 255 | } 256 | -------------------------------------------------------------------------------- /src/components/EditorToolbar/index.js: -------------------------------------------------------------------------------- 1 | export { EditorToolbar } from "./EditorToolbar" 2 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from "theme-ui" 3 | import { Box, Link } from "@theme-ui/components" 4 | 5 | import { ThemeWrapper } from "../ThemeWrapper" 6 | 7 | import { IconButton } from "../IconButton" 8 | import { TWITTER_ICON, GITHUB_ICON } from "../../utils/iconPaths" 9 | 10 | export const Footer = () => ( 11 | 12 |
`${theme.space[2]}px ${theme.space[3]}px`, 26 | a: { 27 | ":focus": { 28 | outline: "none", 29 | }, 30 | }, 31 | }} 32 | > 33 | 34 | 40 | 41 | 42 | 51 | 52 | 53 | 54 |
55 |
56 | ) 57 | -------------------------------------------------------------------------------- /src/components/Footer/index.js: -------------------------------------------------------------------------------- 1 | export { Footer } from "./Footer" 2 | -------------------------------------------------------------------------------- /src/components/Header/Header.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext, useState, useEffect, Fragment } from "react" 3 | import PropTypes from "prop-types" 4 | import { jsx } from "theme-ui" 5 | import netlifyIdentity from "netlify-identity-widget" 6 | import { NavLink, Button, Flex, Box, Divider } from "@theme-ui/components" 7 | 8 | import { SkinContext } from "../../context" 9 | 10 | import { ThemeWrapper } from "../ThemeWrapper" 11 | import { Dropdown } from "../Dropdown" 12 | import { SvgIcon } from "../SvgIcon" 13 | 14 | import { ARROW_DOWN_ICON, ARROW_UP_ICON } from "../../utils/iconPaths" 15 | 16 | import { useSiteMetadata } from "../../data/useSiteMetadata" 17 | 18 | export const Header = ({ isEditorRoute, left }) => { 19 | const { 20 | site: { 21 | siteMetadata: { 22 | config: { sidebarWidth }, 23 | }, 24 | }, 25 | } = useSiteMetadata() 26 | 27 | const { state } = useContext(SkinContext) 28 | 29 | const [hasHeaderLoaded, setHasHeaderLoaded] = useState(false) 30 | 31 | useEffect(() => { 32 | setTimeout(() => { 33 | setHasHeaderLoaded(true) 34 | }, 100) 35 | }, []) 36 | 37 | return ( 38 | 39 | theme.zIndices.header, 52 | a: { 53 | ":focus": { 54 | outline: "none", 55 | }, 56 | }, 57 | }} 58 | > 59 | 74 | {left} 75 | 76 | 77 | {state.user ? ( 78 | ( 83 | 98 | )} 99 | > 100 | 118 | 119 | Your Themes 120 | 121 | Code Editor 122 | 123 | Showcase 124 | 125 | 126 | 127 | 128 | 137 | 138 | 139 | 140 | ) : ( 141 | 142 | {hasHeaderLoaded && ( 143 | 144 | 150 | 159 | 160 | )} 161 | 162 | )} 163 | 164 | 165 | 166 | 167 | 168 | ) 169 | } 170 | 171 | Header.defaultProps = { 172 | isEditorRoute: false, 173 | } 174 | 175 | Header.propTypes = { 176 | /** Boolean to control Menu Button and package text visibility */ 177 | isEditorRoute: PropTypes.bool, 178 | /** Render content on the left */ 179 | left: PropTypes.node, 180 | } 181 | -------------------------------------------------------------------------------- /src/components/Header/index.js: -------------------------------------------------------------------------------- 1 | export { Header } from "./Header" 2 | -------------------------------------------------------------------------------- /src/components/IconButton/IconButton.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import PropTypes from "prop-types" 3 | import { jsx } from "theme-ui" 4 | import { IconButton as ThemeUIIconButton } from "@theme-ui/components" 5 | 6 | import { SvgIcon } from "../SvgIcon" 7 | 8 | export const IconButton = ({ iconPath, sx, ...rest }) => { 9 | return ( 10 | 11 | 12 | 13 | ) 14 | } 15 | 16 | IconButton.propTypes = { 17 | /** Svg icon path */ 18 | iconPath: PropTypes.string.isRequired, 19 | /** jsx sx spread */ 20 | sx: PropTypes.any, 21 | } 22 | -------------------------------------------------------------------------------- /src/components/IconButton/index.js: -------------------------------------------------------------------------------- 1 | export { IconButton } from "./IconButton" 2 | -------------------------------------------------------------------------------- /src/components/Identity/Identity.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useContext, Fragment } from "react" 2 | import netlifyIdentity from "netlify-identity-widget" 3 | 4 | import { SkinContext } from "../../context" 5 | 6 | import { SET_IS_USER_LOGGED_IN } from "../../utils/const" 7 | 8 | export const Identity = ({ children }) => { 9 | const { dispatch } = useContext(SkinContext) 10 | 11 | useEffect(() => { 12 | netlifyIdentity.init({}) 13 | 14 | if (netlifyIdentity.currentUser()) { 15 | dispatch({ 16 | type: SET_IS_USER_LOGGED_IN, 17 | user: netlifyIdentity.currentUser(), 18 | }) 19 | } 20 | }, []) 21 | 22 | netlifyIdentity.on("login", user => { 23 | netlifyIdentity.close() 24 | dispatch({ 25 | type: SET_IS_USER_LOGGED_IN, 26 | user: user, 27 | }) 28 | }) 29 | 30 | netlifyIdentity.on("logout", user => { 31 | netlifyIdentity.close() 32 | dispatch({ type: SET_IS_USER_LOGGED_IN, user: user }) 33 | }) 34 | 35 | return {children} 36 | } 37 | -------------------------------------------------------------------------------- /src/components/Identity/index.js: -------------------------------------------------------------------------------- 1 | export { Identity } from "./Identity" 2 | -------------------------------------------------------------------------------- /src/components/Lightbox/Lightbox.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { memo, useContext } from "react" 3 | import { jsx } from "theme-ui" 4 | import { transparentize } from "@theme-ui/color" 5 | import { Close } from "@theme-ui/components" 6 | 7 | import { SkinContext } from "../../context" 8 | 9 | import { ThemeWrapper } from "../ThemeWrapper" 10 | 11 | import { SET_IS_NAV_OPEN } from "../../utils/const" 12 | 13 | export const Lightbox = memo(() => { 14 | const { state, dispatch } = useContext(SkinContext) 15 | 16 | const handleClose = () => { 17 | dispatch({ type: SET_IS_NAV_OPEN, isNavOpen: false }) 18 | } 19 | 20 | return ( 21 | 22 |
(event.key === "Enter" ? handleClose : {})} 27 | sx={{ 28 | backgroundColor: transparentize("black", 0.2), 29 | display: [ 30 | state.isNavOpen ? "flex" : "none", 31 | state.isNavOpen ? "flex" : "none", 32 | state.isNavOpen ? "flex" : "none", 33 | "none", 34 | ], 35 | height: "100%", 36 | justifyContent: "flex-end", 37 | p: 3, 38 | position: "fixed", 39 | transition: ".2s linear background-color", 40 | width: "100%", 41 | zIndex: theme => theme.zIndices.lightbox, 42 | ":focus": { 43 | backgroundColor: transparentize("black", 0.4), 44 | }, 45 | }} 46 | > 47 | 52 |
53 |
54 | ) 55 | }) 56 | -------------------------------------------------------------------------------- /src/components/Lightbox/index.js: -------------------------------------------------------------------------------- 1 | export { Lightbox } from "./Lightbox" 2 | -------------------------------------------------------------------------------- /src/components/Logo/Logo.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext } from "react" 3 | import PropTypes from "prop-types" 4 | import { jsx } from "theme-ui" 5 | 6 | import { ThemeWrapper } from "../ThemeWrapper" 7 | import { commonFocus } from "../../theme" 8 | 9 | import { useSiteMetadata } from "../../data/useSiteMetadata" 10 | 11 | export const Logo = ({ isElementVisible }) => { 12 | const { 13 | site: { 14 | siteMetadata: { url }, 15 | }, 16 | } = useSiteMetadata() 17 | 18 | return ( 19 | 20 | 33 | 39 | 48 | 52 | 53 | 57 | 58 | 64 | 65 | 66 | 67 | 68 | ) 69 | } 70 | 71 | Logo.propTypes = { 72 | /** parent state isElementVisible */ 73 | isElementVisible: PropTypes.bool, 74 | } 75 | -------------------------------------------------------------------------------- /src/components/Logo/index.js: -------------------------------------------------------------------------------- 1 | export { Logo } from "./Logo" 2 | -------------------------------------------------------------------------------- /src/components/Preview/Preivew.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext, memo } from "react" 3 | import PropTypes from "prop-types" 4 | import { MDXProvider } from "@mdx-js/react" 5 | import { ThemeProvider, jsx } from "theme-ui" 6 | import { Box } from "@theme-ui/components" 7 | 8 | import { SkinContext } from "../../context" 9 | 10 | import { checkAndParse } from "../../utils/checkAndParse" 11 | 12 | import * as themeUiComponents from "@theme-ui/components" 13 | 14 | export const Preview = memo(({ children }) => { 15 | const { state } = useContext(SkinContext) 16 | 17 | const checkBeforeProvider = () => { 18 | try { 19 | // console.log("Skin UI ok!") 20 | return checkAndParse(state.defaultThemeObject) 21 | } catch (e) { 22 | if (e instanceof SyntaxError) { 23 | // console.error("Skin UI Syntax Error") 24 | } 25 | } 26 | } 27 | 28 | return ( 29 | 30 | 31 | {children} 32 | 33 | 34 | ) 35 | }) 36 | 37 | Preview.propTypes = { 38 | /** React children passed from mdx */ 39 | children: PropTypes.any, 40 | } 41 | -------------------------------------------------------------------------------- /src/components/Preview/index.js: -------------------------------------------------------------------------------- 1 | export { Preview } from "./Preivew" 2 | -------------------------------------------------------------------------------- /src/components/PreviewToolbar/PreviewToolbar.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext } from "react" 3 | 4 | import { jsx } from "theme-ui" 5 | import { Flex, Box, Label, Checkbox } from "@theme-ui/components" 6 | 7 | import { SkinContext } from "../../context" 8 | 9 | import { Toolbar } from "../Toolbar" 10 | import { IconButton } from "../IconButton" 11 | import { ThemeWrapper } from "../ThemeWrapper" 12 | 13 | import { 14 | ENTER_FULLSCREEN_ICON, 15 | EXIT_FULLSCREEN_ICON, 16 | PREVIEW_ICON, 17 | SOURCE_ICON, 18 | } from "../../utils/iconPaths" 19 | 20 | import { 21 | MARKDOWN, 22 | COMPONENTS, 23 | SET_FULL_SCREEN, 24 | SET_IS_SOURCE_VISIBLE, 25 | SET_FILTER_CHILDREN, 26 | } from "../../utils/const" 27 | 28 | export const PreviewToolbar = () => { 29 | const { state, dispatch } = useContext(SkinContext) 30 | 31 | const handleChange = event => { 32 | dispatch({ 33 | type: SET_FILTER_CHILDREN, 34 | filterChildren: event.target.name, 35 | }) 36 | } 37 | 38 | return ( 39 | 40 | 46 | 52 | 58 | 75 | 76 | 81 | 97 | 98 | 99 | 105 | 106 | 109 | dispatch({ 110 | type: SET_IS_SOURCE_VISIBLE, 111 | isSourceVisible: state.isSourceVisible, 112 | }) 113 | } 114 | sx={{ 115 | mr: 1, 116 | }} 117 | aria-label={`View ${ 118 | state.isSourceVisible ? "Preview" : "Source" 119 | }`} 120 | iconPath={state.isSourceVisible ? SOURCE_ICON : PREVIEW_ICON} 121 | /> 122 | 123 | 126 | dispatch({ 127 | type: SET_FULL_SCREEN, 128 | isFullScreen: state.isFullScreen, 129 | }) 130 | } 131 | aria-label={`${state.isFullScreen ? "Exit" : "Enter"} Fullscreen`} 132 | iconPath={ 133 | state.isFullScreen 134 | ? EXIT_FULLSCREEN_ICON 135 | : ENTER_FULLSCREEN_ICON 136 | } 137 | /> 138 | 139 | 140 | 141 | 142 | ) 143 | } 144 | -------------------------------------------------------------------------------- /src/components/PreviewToolbar/index.js: -------------------------------------------------------------------------------- 1 | export { PreviewToolbar } from "./PreviewToolbar" 2 | -------------------------------------------------------------------------------- /src/components/Seo/Seo.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { memo } from "react" 3 | import PropTypes from "prop-types" 4 | import { Helmet } from "react-helmet" 5 | 6 | export const Seo = memo( 7 | ({ 8 | author, 9 | title, 10 | titleTemplate, 11 | description, 12 | url, 13 | ogImage, 14 | path, 15 | keywords, 16 | lang, 17 | }) => { 18 | const formatTitleTemplate = `${title} ${ 19 | titleTemplate ? `| ${titleTemplate}` : "" 20 | }` 21 | 22 | return ( 23 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | {/* Facebook */} 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {/* Twitter */} 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | ) 69 | } 70 | ) 71 | 72 | Seo.propTypes = { 73 | /** The twitter creator */ 74 | author: PropTypes.string.isRequired, 75 | /** The site title */ 76 | title: PropTypes.string.isRequired, 77 | /** The site individual route */ 78 | titleTemplate: PropTypes.string.isRequired, 79 | /** The site description */ 80 | description: PropTypes.string.isRequired, 81 | /** The site URL */ 82 | url: PropTypes.string.isRequired, 83 | /** Image url to use for opengraph image */ 84 | ogImage: PropTypes.string, 85 | /** Absolute URL path */ 86 | path: PropTypes.string.isRequired, 87 | /** Keywords to use in meta keywords */ 88 | keywords: PropTypes.arrayOf(PropTypes.string), 89 | /** Lang to use as meta lang */ 90 | lang: PropTypes.string.isRequired, 91 | } 92 | 93 | Seo.defaultProps = { 94 | lang: "eng", 95 | } 96 | -------------------------------------------------------------------------------- /src/components/Seo/index.js: -------------------------------------------------------------------------------- 1 | export { Seo } from "./Seo" 2 | -------------------------------------------------------------------------------- /src/components/Settings/Settings.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useContext, useState, memo, Fragment, useEffect } from "react" 3 | import PropTypes from "prop-types" 4 | import { jsx } from "theme-ui" 5 | 6 | import { 7 | Flex, 8 | Box, 9 | Text, 10 | Button, 11 | Label, 12 | Input, 13 | Textarea, 14 | Radio, 15 | Divider, 16 | Spinner, 17 | } from "@theme-ui/components" 18 | import copy from "clipboard-copy" 19 | 20 | import { useMutation } from "@apollo/react-hooks" 21 | 22 | import { IconButton } from "../IconButton" 23 | import { SkinContext } from "../../context" 24 | 25 | import { checkAndReplaceQuotes } from "../../utils/checkAndReplaceQuotes" 26 | 27 | import { 28 | COPY_ICON, 29 | DOWNLOAD_ICON, 30 | DELETE_THEME_ICON, 31 | } from "../../utils/iconPaths" 32 | 33 | import { useSiteMetadata } from "../../data/useSiteMetadata" 34 | import { SET_DATABASE_THEME_BY_ID } from "../../utils/const" 35 | import { UPDATE_THEME_BY_ID, DELETE_THEME_BY_ID } from "../../utils/graphql" 36 | 37 | const THEME_STYLE_LIGHT = "light" 38 | const THEME_STYLE_DARK = "dark" 39 | 40 | export const Settings = memo(({ isElementVisible }) => { 41 | const { 42 | site: { 43 | siteMetadata: { url }, 44 | }, 45 | } = useSiteMetadata() 46 | 47 | const { state, dispatch } = useContext(SkinContext) 48 | 49 | const [updateThemeById, { loading, error }] = useMutation( 50 | UPDATE_THEME_BY_ID, 51 | { 52 | onCompleted({ updateThemeById }) { 53 | dispatch({ 54 | type: SET_DATABASE_THEME_BY_ID, 55 | databaseThemeById: { 56 | ...updateThemeById, 57 | }, 58 | }) 59 | }, 60 | } 61 | ) 62 | 63 | const [deleteThemeById] = useMutation(DELETE_THEME_BY_ID, { 64 | onCompleted() { 65 | location.search = null 66 | }, 67 | }) 68 | 69 | const handleSave = () => { 70 | updateThemeById({ 71 | variables: { 72 | theme_id: state.databaseThemeById.ref, 73 | theme_name: formValues.theme_name, 74 | theme_description: formValues.theme_description, 75 | theme_style: formValues.theme_style, 76 | theme_object: state.defaultThemeObject, 77 | }, 78 | }) 79 | } 80 | 81 | const handleDelete = () => { 82 | deleteThemeById({ 83 | variables: { 84 | theme_id: state.databaseThemeById.ref, 85 | }, 86 | }) 87 | } 88 | 89 | const [formValues, setFormValues] = useState({ 90 | theme_name: "", 91 | theme_description: "", 92 | theme_style: "", 93 | }) 94 | 95 | useEffect(() => { 96 | setFormValues({ 97 | theme_name: state.databaseThemeById.theme_name, 98 | theme_description: state.databaseThemeById.theme_description, 99 | theme_style: state.databaseThemeById.theme_style, 100 | }) 101 | }, [state.databaseThemeById]) 102 | 103 | return ( 104 | 105 | 112 | 119 | 120 | 125 | setFormValues({ 126 | ...formValues, 127 | theme_name: event.target.value, 128 | }) 129 | } 130 | /> 131 | 132 |