├── cachiql-demo ├── .eslintignore ├── src │ ├── client │ │ ├── Components │ │ │ ├── AboutUs │ │ │ │ ├── index.ts │ │ │ │ ├── styles.ts │ │ │ │ ├── members.ts │ │ │ │ └── AboutUs.tsx │ │ │ ├── Avatar │ │ │ │ ├── index.ts │ │ │ │ └── Avatars.tsx │ │ │ ├── Banner │ │ │ │ ├── index.ts │ │ │ │ ├── Star.tsx │ │ │ │ ├── makeStars.tsx │ │ │ │ ├── style.ts │ │ │ │ └── Banner.tsx │ │ │ ├── BarChart │ │ │ │ ├── index.ts │ │ │ │ └── BarChart.tsx │ │ │ ├── TitleGraph.tsx │ │ │ ├── Metrics.tsx │ │ │ ├── Navigation.tsx │ │ │ ├── GraphiQL.tsx │ │ │ ├── Demologo.tsx │ │ │ ├── Stepper.tsx │ │ │ ├── Cards.tsx │ │ │ └── PersonalLinks.tsx │ │ ├── assets │ │ │ ├── Vanessa.jpeg │ │ │ ├── cachiqlDemo.png │ │ │ ├── vanessaPic.jpg │ │ │ ├── T01V0N825N3-U0235GQ1GGY-56cdf8f46852-512.jpeg │ │ │ ├── SmallCachiql.svg │ │ │ ├── blueBackCachiql.svg │ │ │ ├── cachiqlWhiteLogo.svg │ │ │ ├── teamCachiql.svg │ │ │ ├── cachiql_(1)-svg_(2).svg │ │ │ ├── cachiql_(1)-svg_(1).svg │ │ │ └── white1024.svg │ │ ├── custom.d.ts │ │ ├── index.tsx │ │ ├── index.html │ │ ├── interfaces │ │ │ └── interfaces.ts │ │ └── app.tsx │ └── server │ │ ├── models │ │ ├── book.js │ │ └── author.js │ │ ├── AuthorLoader.js │ │ ├── BookLoader.js │ │ ├── cachiql.js │ │ └── server.js ├── .prettierrc ├── dist │ ├── index.html │ ├── 574.bundle.js │ ├── 768.bundle.js │ ├── 744.bundle.js │ └── 980.bundle.js ├── tsconfig.json ├── .eslintrc ├── __tests__ │ └── cachiql.js ├── package.json └── webpack.config.js ├── .gitignore ├── cachiql ├── package.json ├── README.md └── index.js ├── LICENSE └── README.md /cachiql-demo/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist/* 3 | webpack.config.js 4 | __tests__ -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/AboutUs/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AboutUs' -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Avatar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Avatars'; 2 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Banner/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Banner'; 2 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/BarChart/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './BarChart'; 2 | -------------------------------------------------------------------------------- /cachiql-demo/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "arrowParens": "avoid" 5 | } 6 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/Vanessa.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/CachiQL/HEAD/cachiql-demo/src/client/assets/Vanessa.jpeg -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/cachiqlDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/CachiQL/HEAD/cachiql-demo/src/client/assets/cachiqlDemo.png -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/vanessaPic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/CachiQL/HEAD/cachiql-demo/src/client/assets/vanessaPic.jpg -------------------------------------------------------------------------------- /cachiql-demo/src/client/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const content: React.FunctionComponent>; 3 | export default content; 4 | } -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/T01V0N825N3-U0235GQ1GGY-56cdf8f46852-512.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/CachiQL/HEAD/cachiql-demo/src/client/assets/T01V0N825N3-U0235GQ1GGY-56cdf8f46852-512.jpeg -------------------------------------------------------------------------------- /cachiql-demo/src/client/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import App from './app'; 5 | 6 | ReactDOM.render(, document.querySelector('#root')); 7 | -------------------------------------------------------------------------------- /cachiql-demo/dist/index.html: -------------------------------------------------------------------------------- 1 | CachiQL
-------------------------------------------------------------------------------- /cachiql-demo/src/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | CachiQL 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /cachiql-demo/src/server/models/book.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/ 2 | const mongoose = require('mongoose'); 3 | const authorSchema = require('./book') 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const bookSchema = new Schema({ 8 | title: { 9 | type: String, 10 | required: true 11 | }, 12 | Author: { type: mongoose.Schema.Types.ObjectId, ref: 'authours' } 13 | }) 14 | 15 | module.exports = mongoose.model('books', bookSchema, 'books'); -------------------------------------------------------------------------------- /cachiql-demo/src/client/interfaces/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface MemberType { 2 | name: string; 3 | image: string; 4 | imageLarge: React.FunctionComponent>; 5 | github: string; 6 | linkedIn: string; 7 | } 8 | 9 | export interface QueryResult { 10 | label: string; 11 | queryResult: any; 12 | cachedRunTime: number; 13 | uncachedRunTime: number; 14 | added: boolean; 15 | cleared: boolean; 16 | } 17 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/TitleGraph.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Typography from '@material-ui/core/Typography'; 4 | 5 | export const TitleGraph = (props) => { 6 | return ( 7 | 8 | {props.children} 9 | 10 | ); 11 | }; 12 | 13 | TitleGraph.propTypes = { 14 | children: PropTypes.node 15 | }; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | # dependencies 3 | node_modules/ 4 | 5 | # testing 6 | /coverage 7 | 8 | # production 9 | /build 10 | 11 | # IDEs and editors 12 | /.idea 13 | /.vscode 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | node_modules/ 26 | cachiql-demo/package-lock.json/ -------------------------------------------------------------------------------- /cachiql-demo/src/server/models/author.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/ 2 | const mongoose = require('mongoose'); 3 | const bookSchema = require('./book') 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | authourSchema = new Schema({ 8 | firstName: String, 9 | lastName: String, 10 | books: [{ type: mongoose.Schema.Types.ObjectID, ref: 'books' }], 11 | }) 12 | 13 | module.exports = mongoose.model('Authour', authourSchema, 'authours'); 14 | 15 | 16 | //[{ type: mongoose.Schema.Types.ObjectID, ref: 'books' }] -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Banner/Star.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useStyles } from './style'; 3 | 4 | const Star = ({ x, y, duration, size }: any) => { 5 | const classes = useStyles(); 6 | const style = { 7 | left: `${x}px`, 8 | top: `${y}px`, 9 | width: `${1 + size}px`, 10 | height: `${1 + size}px`, 11 | animationDuration: `${5 + duration}s`, 12 | animationDelay: `${1 + duration}s`, 13 | }; 14 | return ; 15 | }; 16 | 17 | export default Star; 18 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Avatar/Avatars.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Avatar from '@material-ui/core/Avatar'; 3 | import { MemberType } from '../../interfaces/interfaces'; 4 | import { teamMembers } from '../AboutUs/members'; 5 | const Avatars: React.FC = () => { 6 | return ( 7 | 8 | {teamMembers.map((member: MemberType) => { 9 | return ; 10 | })} 11 | 12 | ); 13 | }; 14 | 15 | export default Avatars; 16 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Banner/makeStars.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Star from './Star'; 3 | 4 | export const makeStars = () => { 5 | let i = 0; 6 | const starArr = new Array(500); 7 | while (i < starArr.length) { 8 | const x = Math.floor(Math.random() * 2000); 9 | const y = Math.floor(Math.random() * 2000); 10 | const duration = Math.random() * 10; 11 | const size = Math.random() * 2; 12 | starArr[i] = ; 13 | i += 1; 14 | } 15 | return starArr; 16 | }; 17 | -------------------------------------------------------------------------------- /cachiql-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src", "custom.d.ts"] 20 | } 21 | -------------------------------------------------------------------------------- /cachiql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cachiql", 3 | "version": "1.0.0", 4 | "description": "Batching and caching solution for Graphql", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/oslabs-beta/CachiQL.git" 12 | }, 13 | "keywords": [ 14 | "graphql" 15 | ], 16 | "author": "Kaden Johnson, Vanessa Lutz, Fahad Shaikh, Eddy Zapata.", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/oslabs-beta/CachiQL/issues" 20 | }, 21 | "homepage": "https://github.com/oslabs-beta/CachiQL#readme" 22 | } 23 | -------------------------------------------------------------------------------- /cachiql-demo/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:react/recommended", 10 | "plugin:@typescript-eslint/recommended", 11 | "prettier" 12 | ], 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { 15 | "ecmaFeatures": { 16 | "jsx": true 17 | }, 18 | "ecmaVersion": "latest", 19 | "sourceType": "module" 20 | }, 21 | "plugins": ["react", "@typescript-eslint"], 22 | "rules": { 23 | "@typescript-eslint/no-unused-vars": "error", 24 | "@typescript-eslint/consistent-type-definitions": ["error", "interface"] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cachiql-demo/src/server/AuthorLoader.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable */ 2 | const { Cachiql } = require('./cachiql'); 3 | 4 | const Author = require('./models/author'); 5 | 6 | // const formatResult = (authors, ids) => { 7 | // const authorMap = {}; 8 | 9 | // authors.forEach(author => { 10 | // authorMap[author.id] = author; 11 | // }); 12 | 13 | // return ids.map(id => authorMap[id]); 14 | // } 15 | 16 | // batches authors using ids. Returns Authors. 17 | const batchAuthors = async (ids) => { 18 | try { 19 | const authors = await Author.find({ _id: { $in: ids } }); 20 | //return formatResult(authors, ids); 21 | return authors; 22 | } catch (err) { 23 | throw new Error('There was an error getting the Authors'); 24 | } 25 | }; 26 | 27 | module.exports = batchAuthors; 28 | -------------------------------------------------------------------------------- /cachiql-demo/src/server/BookLoader.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable */ 2 | const { Cachiql } = require('./cachiql'); 3 | 4 | const Book = require('./models/book'); 5 | 6 | // const formatResult = (authors, ids) => { 7 | // const authorMap = {}; 8 | 9 | // authors.forEach(author => { 10 | // authorMap[author.id] = author; 11 | // }); 12 | 13 | // return ids.map(id => authorMap[id]); 14 | // } 15 | 16 | // batches book using ids by querieng for a match on id. Returns books. 17 | const batchBooks = async (ids) => { 18 | try { 19 | const books = await Book.find({ _id: { $in: ids } }); 20 | //return formatResult(authors, ids); 21 | return books; 22 | } catch (err) { 23 | throw new Error('There was an error getting the Books'); 24 | } 25 | }; 26 | 27 | module.exports = batchBooks; 28 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/AboutUs/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from '@material-ui/core/styles'; 2 | 3 | export const useStyles = makeStyles(theme => ({ 4 | cardGrid: { 5 | paddingTop: theme.spacing(8), 6 | paddingBottom: theme.spacing(8), 7 | }, 8 | card: { 9 | paddingTop: '5%', 10 | height: '100%', 11 | display: 'flex', 12 | flexDirection: 'column', 13 | alignItems: 'center', 14 | }, 15 | cardMedia: { 16 | borderRadius: '50%', // 16:9 17 | }, 18 | cardContent: { 19 | flexGrow: 1, 20 | justifyContent: 'center', 21 | }, 22 | svgIcon: { 23 | transform: 'scale(1.0)', 24 | }, 25 | cardMedia2: { 26 | borderRadius: '50%', 27 | margin: '10px', 28 | }, 29 | container: { 30 | paddingTop: '10px', 31 | alignContent: 'space-between', 32 | }, 33 | teamIcon: { 34 | transform: 'scale(0.7)', 35 | }, 36 | })); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 OSLabs Beta 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 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Banner/style.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from '@material-ui/core/styles'; 2 | 3 | export const useStyles = makeStyles(theme => ({ 4 | heroContent: { 5 | backgroundColor: theme.palette.background.paper, 6 | position: 'relative', 7 | width: '100%', 8 | background: 'linear-gradient(#111425,#3751e0)', 9 | padding: theme.spacing(8, 0, 6), 10 | color: theme.palette.common.white, 11 | backgroundAttachment: 'fixed', 12 | overflow: 'hidden', 13 | boxSizing: 'border-box', 14 | }, 15 | svg_icons: { 16 | width: '100%', 17 | height: '100%', 18 | padding: '40px', 19 | }, 20 | i: { 21 | position: 'absolute', 22 | background: '#fff', 23 | borderRadius: '50%', 24 | animation: '$animate linear infinite', 25 | }, 26 | '@keyframes animate': { 27 | '0%': { 28 | opacity: 0, 29 | transform: 'translateY(0)', 30 | }, 31 | '10%, 90%': { 32 | opacity: 1, 33 | }, 34 | '100%': { 35 | opacity: 0, 36 | transform: 'translateY(-100px)', 37 | }, 38 | }, 39 | npmframe: { 40 | padding: '200px', 41 | }, 42 | })); 43 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/AboutUs/members.ts: -------------------------------------------------------------------------------- 1 | import { MemberType } from '../../interfaces/interfaces'; 2 | import Kaden from '../../assets/resizedKaden-svg.svg'; 3 | import Vanessa from '../../assets/resizedVanessa-svg.svg'; 4 | import Eddy from '../../assets/resizedEddy-svg.svg'; 5 | import Fahad from '../../assets/resizedFahad-svg.svg'; 6 | 7 | export const teamMembers: MemberType[] = [ 8 | { 9 | name: 'Kaden Johnson', 10 | linkedIn: 'https://www.linkedin.com/in/kaden-johnson/', 11 | github: 'https://github.com/Kadenj117', 12 | imageLarge: Kaden, 13 | image: 'kadenPic.jpg', 14 | }, 15 | { 16 | name: 'Vanessa Lutz', 17 | linkedIn: 'https://www.linkedin.com/in/vanessa-lutz/', 18 | github: 'https://github.com/vanessalutz', 19 | imageLarge: Vanessa, 20 | image: 'vanessaPic.jpg', 21 | }, 22 | { 23 | name: 'Eddy Zapata', 24 | linkedIn: 'http://www.linkedin.com/in/eddy-zapata', 25 | github: 'https://github.com/zapata124', 26 | imageLarge: Eddy, 27 | image: 'eddyPic.jpg', 28 | }, 29 | { 30 | name: 'Fahad Shaikh', 31 | linkedIn: 'https://www.linkedin.com/in/fahadmshaikh/', 32 | github: 'https://github.com/fahdie', 33 | imageLarge: Fahad, 34 | image: 'fahadPic.jpg', 35 | }, 36 | ]; -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/BarChart/BarChart.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import React from 'react'; 3 | import { TitleGraph } from '../TitleGraph'; 4 | import { 5 | BarChart, 6 | Bar, 7 | XAxis, 8 | YAxis, 9 | CartesianGrid, 10 | Tooltip, 11 | Legend, 12 | } from 'recharts'; 13 | 14 | const BarStyle = styled.div` 15 | font-family: sans-serif; 16 | text-align: center; 17 | `; 18 | 19 | interface Props { 20 | recentQueries: any[]; 21 | setRecentQueries: React.Dispatch>; 22 | } 23 | 24 | const BarChartComp: React.FC = ({ recentQueries, setRecentQueries }) => { 25 | return ( 26 | <> 27 | CachiQL Results 28 | 29 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ); 51 | }; 52 | 53 | export default BarChartComp; 54 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Metrics.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles } from '@material-ui/core/styles'; 3 | import Typography from '@material-ui/core/Typography'; 4 | import { TitleGraph } from './TitleGraph'; 5 | import Sparkle from 'react-sparkle'; 6 | import TrendingDownIcon from '@material-ui/icons/TrendingDown'; 7 | 8 | const useStyles = makeStyles({ 9 | depositContext: { 10 | flex: 1, 11 | paddingTop: '30px', 12 | paddingBottom: '30px' 13 | }, 14 | sparkle: { 15 | position: 'relative' 16 | }, 17 | trendIcon: { 18 | display: 'flex', 19 | alignItems: 'center', 20 | height: 50, 21 | width: 50 22 | } 23 | }); 24 | interface Props { 25 | recentQueries: any[]; 26 | setRecentQueries: React.Dispatch>; 27 | } 28 | 29 | export const Metrics: React.FC = ({ 30 | recentQueries, 31 | setRecentQueries 32 | }) => { 33 | const classes = useStyles(); 34 | 35 | return ( 36 | 37 | CachiQL Metrics 38 | 39 | 40 | {recentQueries[0]?.CachiQL ?? 'Make A Query'} 41 | 42 | 43 | 44 | 45 | With CachiQL 46 | 47 | 48 | 49 | {recentQueries[0]?.GraphQL ?? 'Make A Query'} 50 | 51 | 52 | Standard GraphQL Queries 53 | 54 | 55 | ); 56 | }; 57 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Navigation.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { NavMenu, NavItem } from '@mui-treasury/components/menu/navigation'; 3 | import { useFloatNavigationMenuStyles } from '@mui-treasury/styles/navigationMenu/float'; 4 | import GitHubIcon from '@material-ui/icons/GitHub'; 5 | import OndemandVideoIcon from '@material-ui/icons/OndemandVideo'; 6 | import AutorenewIcon from '@material-ui/icons/Autorenew'; 7 | import RateReviewIcon from '@material-ui/icons/RateReview'; 8 | import InfoIcon from '@material-ui/icons/Info'; 9 | import CssBaseline from '@material-ui/core/CssBaseline'; 10 | import { Link } from '@material-ui/core'; 11 | 12 | 13 | export const FloatNavigationMenuStyle = React.memo( 14 | function FloatNavigationMenu() { 15 | return ( 16 | <> 17 | 18 | 19 | 20 | 21 | MAGICAL CACHiQL 22 | 23 | window.open('https://www.npmjs.com/package/cachiql')} 25 | > 26 | 27 | NPM PACKAGE 28 | 29 | 30 | 31 | DEMO 32 | 33 | 35 | window.open( 36 | 'https://medium.com/@vanessayplutz/deeply-understand-the-graphql-n-1-issue-and-dataloader-5a2c8b4de050' 37 | ) 38 | } 39 | > 40 | 41 | MEDIUM 42 | 43 | 44 | 45 | ABOUT US 46 | 47 | 48 | 49 | ); 50 | } 51 | ); 52 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/GraphiQL.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import GraphiQL from 'graphiql'; 3 | import styled from 'styled-components'; 4 | import 'graphiql/graphiql.min.css'; 5 | import { execute } from 'graphql'; 6 | 7 | const Stylegraphiql = styled.div` 8 | margin: auto; 9 | max-width: 60%; 10 | margin-bottom: 25px; 11 | .graphiql { 12 | height: 50vh; 13 | } 14 | `; 15 | 16 | interface Props { 17 | recentQueries: any[]; 18 | setRecentQueries: React.Dispatch>; 19 | } 20 | export const Graphiql: React.FC = ({ 21 | recentQueries, 22 | setRecentQueries 23 | }) => { 24 | const getCounter = () => { 25 | fetch('/counter') 26 | .then((res) => res.json()) 27 | .then((data) => { 28 | setRecentQueries([...recentQueries, ...data] || [...recentQueries]); 29 | }); 30 | }; 31 | 32 | return ( 33 | 34 |
35 | { 37 | const data = await fetch('graphql', { 38 | method: 'POST', 39 | headers: { 40 | Accept: 'application/json', 41 | 'Content-Type': 'application/json' 42 | }, 43 | body: JSON.stringify(graphQLParams), 44 | credentials: 'same-origin' 45 | }); 46 | return data.json().catch(() => { 47 | data.text(); 48 | }); 49 | }} 50 | > 51 | 52 | Compare CachiQL 53 | getCounter()} 55 | title="ToolbarButton" 56 | label="Display Results" 57 | /> 58 | 59 | 60 |
61 |
62 | ); 63 | }; 64 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Banner/Banner.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Typography from '@material-ui/core/Typography'; 3 | import { makeStyles } from '@material-ui/core/styles'; 4 | import CssBaseline from '@material-ui/core/CssBaseline'; 5 | import Container from '@material-ui/core/Container'; 6 | import Grid from '@material-ui/core/Grid'; 7 | import CachiQLLogo from '../../assets/white1024.svg'; 8 | import Paper from '@material-ui/core/Paper'; 9 | import { Button } from '@material-ui/core'; 10 | import CloudDownloadIcon from '@material-ui/icons/CloudDownload'; 11 | import { useStyles } from './style'; 12 | import Star from './Star'; 13 | import { makeStars } from './makeStars'; 14 | 15 | const Banner = () => { 16 | const classes = useStyles(); 17 | return ( 18 | 19 | 20 |
21 | {/* Hero unit */} 22 | 23 | {makeStars()} 24 | 25 | 26 | 27 | 28 | 29 | {' '} 30 | 36 | Experience the Magic 37 | 38 | 39 | Try an ultra light-weight NPM Package to batch and cache nested 40 | GraphQL queries. 41 | 42 | 50 | 51 | 52 | 53 |
54 |
55 | ); 56 | }; 57 | 58 | export default Banner; 59 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Demologo.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { makeStyles } from '@material-ui/core/styles'; 3 | import Paper from '@material-ui/core/Paper'; 4 | import Typography from '@material-ui/core/Typography'; 5 | import Grid from '@material-ui/core/Grid'; 6 | import CQDemoLogo from '../../assets/whitedemo1024.svg'; 7 | import CQDemo from '../../assets/cachiqlDemo.png'; 8 | import Sparkle from 'react-sparkle'; 9 | 10 | const useStyles = makeStyles((theme) => ({ 11 | mainFeaturedPost: { 12 | position: 'relative', 13 | background: 'linear-gradient(#111425,#3751e0)', 14 | color: theme.palette.common.white, 15 | marginBottom: theme.spacing(4), 16 | backgroundSize: 'cover', 17 | backgroundRepeat: 'no-repeat', 18 | backgroundPosition: 'center' 19 | }, 20 | overlay: { 21 | position: 'absolute', 22 | top: 0, 23 | bottom: 0, 24 | right: 0, 25 | left: 0, 26 | backgroundColor: 'linear-gradient(#111425,#3751e0)' 27 | }, 28 | svg_demo: { 29 | transform: 'scale(1.0)', 30 | position: 'relative' 31 | }, 32 | mainFeaturedPostContent: { 33 | position: 'relative', 34 | padding: theme.spacing(3), 35 | [theme.breakpoints.up('md')]: { 36 | padding: theme.spacing(6), 37 | paddingRight: 0 38 | } 39 | } 40 | })); 41 | 42 | export const Demo = () => { 43 | const classes = useStyles(); 44 | 45 | return ( 46 | 47 |
48 | 49 | 50 | 51 | 52 |
53 | 59 | Experience Magical CachiQL 60 | 61 | 62 | Take a look at all that CachiQL has to offer by using GraphiQL to make a query. 63 | 64 |
65 |
66 |
67 | 68 | ); 69 | }; 70 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/AboutUs/AboutUs.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import LinkedInIcon from '@material-ui/icons/LinkedIn'; 3 | import GitHubIcon from '@material-ui/icons/GitHub'; 4 | import Card from '@material-ui/core/Card'; 5 | import Container from '@material-ui/core/Container'; 6 | import IconButton from '@material-ui/core/IconButton'; 7 | import Typography from '@material-ui/core/Typography'; 8 | import TeamCachiql from '../../assets/teamCachiql.svg'; 9 | import { Box, Grid } from '@material-ui/core'; 10 | import { useStyles } from './styles'; 11 | import { teamMembers } from './members'; 12 | 13 | const AboutUs = () => { 14 | const classes = useStyles(); 15 | const [cards, setCards] = useState(teamMembers); 16 | return ( 17 | <> 18 | 19 | 26 | 27 | 28 | 29 | {cards.map((card: any, i) => ( 30 | 31 | 32 | 33 | {card.name} 34 | 35 | window.open(card.linkedIn)} 39 | > 40 | 41 | 42 | window.open(card.github)} 46 | > 47 | 48 | 49 | 50 | 51 | 52 | ))} 53 | 54 | 55 | 56 | ); 57 | }; 58 | 59 | export default AboutUs; 60 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/app.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { FloatNavigationMenuStyle } from './Components/Navigation'; 3 | import { Graphiql } from './Components/GraphiQL'; 4 | import BarChartComp from './Components/BarChart'; 5 | import Container from '@material-ui/core/Container'; 6 | import Grid from '@material-ui/core/Grid'; 7 | import CssBaseline from '@material-ui/core/CssBaseline'; 8 | import Paper from '@material-ui/core/Paper'; 9 | import { makeStyles } from '@material-ui/core/styles'; 10 | import { Metrics } from './Components/Metrics'; 11 | import clsx from 'clsx'; 12 | import Banner from './Components/Banner'; 13 | import { WhyCachiQL } from './Components/Cards'; 14 | import { Demo } from './Components/Demologo'; 15 | import Stepper from './Components/Stepper'; 16 | import AboutUs from './Components/AboutUs'; 17 | 18 | const useStyles = makeStyles(theme => ({ 19 | root: { 20 | display: 'flex', 21 | }, 22 | container: { 23 | paddingTop: theme.spacing(4), 24 | paddingBottom: theme.spacing(4), 25 | }, 26 | paper: { 27 | padding: theme.spacing(2), 28 | display: 'flex', 29 | overflow: 'auto', 30 | flexDirection: 'column', 31 | }, 32 | fixedHeight: { 33 | height: 380, 34 | }, 35 | metrics: { 36 | alignItems: 'center', 37 | }, 38 | })); 39 | 40 | const App: React.FC = () => { 41 | const [recentQueries, setRecentQueries] = useState([]); 42 | const classes = useStyles(); 43 | const fixedHeightPaper = clsx(classes.paper, classes.fixedHeight); 44 | const metricsPaper = clsx( 45 | classes.paper, 46 | classes.fixedHeight, 47 | classes.metrics 48 | ); 49 | return ( 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | {/* BuildBarChart */} 65 | 66 | 67 | 68 | 69 | 70 | {/* Metrics */} 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 | ); 81 | }; 82 | 83 | export default App; 84 | -------------------------------------------------------------------------------- /cachiql-demo/__tests__/cachiql.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/ 2 | const { JsxEmit } = require('typescript'); 3 | const { Cachiql } = require('../src/server/cachiql') 4 | 5 | const testLoader = () => { 6 | const arr = [] 7 | const loader = new Cachiql(keys => { 8 | arr.push(keys) 9 | return Promise.resolve(keys); 10 | }); 11 | return [loader, arr]; 12 | } 13 | 14 | describe('CachiQL', () => { 15 | describe('load() functionality', () => { 16 | test('given a value the function should return a promise', async () => { 17 | const loader = new Cachiql(async keys => keys) 18 | const nullVal = null; 19 | 20 | 21 | expect(loader.load(1)).toBeInstanceOf(Promise); 22 | expect(loader.load('testString1')).toBeInstanceOf(Promise); 23 | expect(loader.load({ 1: 'TestObject' })).toBeInstanceOf(Promise); 24 | // expect(loader.load(nullVal)).toThrow(Error) 25 | 26 | }) 27 | 28 | test('given a null value should return an error', async () => { 29 | const loader = new Cachiql(async keys => keys) 30 | const nullVal = null; 31 | //jest.fn 32 | 33 | //expect(await loader.load(nullVal)).toThrow('The key passed into the function is undefined please use valid key') 34 | 35 | }) 36 | }) 37 | 38 | describe('LoadAll() functionality', () => { 39 | it('Should return return a promise', async () => { 40 | const loader = new Cachiql(async keys => keys); 41 | 42 | const promise = loader.loadAll([1, 2, 3, 4, 5, 3, 4, 2, 3]) 43 | expect(promise).toBeInstanceOf(Promise); 44 | }) 45 | 46 | it('Should return no duplicates once promise is resolved', async () => { 47 | const loader = new Cachiql(async keys => keys); 48 | 49 | const clearBatch = (batch) => { 50 | batch.hasSent = false; 51 | batch.keys = []; 52 | batch.cbs = []; 53 | } 54 | 55 | const promise = loader.loadAll([1, 2, 3, 4, 5, 3, 4, 2, 3]) 56 | expect(promise).toBeInstanceOf(Promise); 57 | expect(await promise).toEqual([1, 2, 3, 4, 5]) 58 | clearBatch(loader.batch) 59 | }) 60 | }) 61 | 62 | describe('batch functionality', () => { 63 | it('Should show key value pairs in the batch', async () => { 64 | const batch = new Cachiql(async keys => keys); 65 | 66 | const clearBatch = (batch) => { 67 | batch.hasSent = false; 68 | batch.keys = []; 69 | batch.cbs = []; 70 | } 71 | 72 | batch.loadAll([1, 2, 3, 4, 5, 4, 3, 2, 1]) 73 | expect(batch.batch.keys.length).toEqual(5); 74 | expect(batch.batch.hasSent).toEqual(true); 75 | clearBatch(batch.batch) 76 | }) 77 | 78 | it('Should clear cache when called', () => { 79 | const loader = new Cachiql(async keys => keys); 80 | 81 | expect(loader.batch).toEqual(null) 82 | }) 83 | }) 84 | }) -------------------------------------------------------------------------------- /cachiql-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cachiql-demo", 3 | "version": "1.0.0", 4 | "description": "Create the demo of the cachiql module", 5 | "main": "./src/client/index.tsx", 6 | "scripts": { 7 | "start": "cross-env NODE_ENV=PRODUCTION node ./src/server/server.js", 8 | "build": "cross-env NODE_ENV=PRODUCTION webpack --progress", 9 | "dev": "concurrently \"cross-env NODE_ENV=development webpack serve --open --hot \" \"nodemon ./src/server/server.js\"", 10 | "test": "jest", 11 | "lint": "eslint --ext .ts", 12 | "prettier-format": "prettier --config .prettierrc './**/*.ts' --write", 13 | "prettier-watch": "onchange './**/*.ts' -- prettier --write {{changed}}" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/oslabs-beta/CachiQL.git" 18 | }, 19 | "author": "Vanessa Lutz, Fahad Shaikh, Eddy Zapata, Kaden Johnson", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/oslabs-beta/CachiQL/issues" 23 | }, 24 | "homepage": "https://github.com/oslabs-beta/CachiQL#readme", 25 | "dependencies": { 26 | "@babel/polyfill": "^7.12.1", 27 | "@babel/preset-env": "^7.14.7", 28 | "@babel/preset-react": "^7.14.5", 29 | "@material-ui/core": "^4.12.2", 30 | "@material-ui/icons": "^4.11.2", 31 | "@mui-treasury/components": "^1.10.1", 32 | "@mui-treasury/styles": "^1.13.1", 33 | "@svgr/webpack": "^5.5.0", 34 | "babel": "^6.23.0", 35 | "babel-core": "^6.26.3", 36 | "babel-loader": "^8.2.2", 37 | "babel-polyfill": "^6.26.0", 38 | "babel-preset-env": "^1.7.0", 39 | "babel-preset-react": "^6.24.1", 40 | "clsx": "^1.1.1", 41 | "concurrently": "^6.2.0", 42 | "cross-env": "^7.0.3", 43 | "css-loader": "^5.2.7", 44 | "dom": "^0.0.3", 45 | "eslint-webpack-plugin": "^2.5.4", 46 | "express": "^4.17.1", 47 | "express-graphql": "^0.12.0", 48 | "faker": "^5.5.3", 49 | "file-loader": "^6.2.0", 50 | "fork-ts-checker-webpack-plugin": "^6.2.12", 51 | "graphiql": "^1.4.2", 52 | "graphql": "^15.5.1", 53 | "html-webpack-plugin": "^5.3.2", 54 | "image-webpack-loader": "^7.0.1", 55 | "material-ui-image": "^3.3.2", 56 | "memory-cache": "^0.2.0", 57 | "mini-css-extract-plugin": "^2.1.0", 58 | "mongoose": "^5.13.3", 59 | "react": "^17.0.2", 60 | "react-dom": "^17.0.2", 61 | "react-helmet": "^6.1.0", 62 | "react-router-hash-link": "^2.4.3", 63 | "react-sparkle": "^1.0.8", 64 | "recharts": "^2.0.10", 65 | "redis": "^3.1.2", 66 | "router": "^1.3.5", 67 | "styled-components": "^5.3.0", 68 | "svg.js": "^2.7.1", 69 | "svgjs": "^2.6.2", 70 | "ts-loader": "^9.2.3", 71 | "webpack": "^5.44.0", 72 | "webpack-cli": "^4.7.2", 73 | "webpack-dev-server": "^3.11.2" 74 | }, 75 | "devDependencies": { 76 | "@babel/preset-typescript": "^7.14.5", 77 | "@types/react": "^17.0.14", 78 | "@types/react-dom": "^17.0.9", 79 | "@types/react-router-hash-link": "^2.4.1", 80 | "@types/styled-components": "^5.1.11", 81 | "@typescript-eslint/eslint-plugin": "^4.28.3", 82 | "@typescript-eslint/parser": "^4.28.3", 83 | "eslint": "^7.30.0", 84 | "eslint-config-prettier": "^8.3.0", 85 | "eslint-plugin-prettier": "^3.4.0", 86 | "jest": "^27.0.6", 87 | "nodemon": "^2.0.12", 88 | "onchange": "^7.1.0", 89 | "prettier": "^2.3.2", 90 | "svg-url-loader": "^7.1.1", 91 | "typescript": "^4.3.5" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Stepper.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles } from '@material-ui/core/styles'; 3 | import Stepper from '@material-ui/core/Stepper'; 4 | import Step from '@material-ui/core/Step'; 5 | import StepLabel from '@material-ui/core/StepLabel'; 6 | import StepContent from '@material-ui/core/StepContent'; 7 | import Button from '@material-ui/core/Button'; 8 | import Paper from '@material-ui/core/Paper'; 9 | import Typography from '@material-ui/core/Typography'; 10 | 11 | const useStyles = makeStyles((theme) => ({ 12 | root: { 13 | width: '100%', 14 | }, 15 | button: { 16 | marginTop: theme.spacing(1), 17 | marginRight: theme.spacing(1), 18 | }, 19 | actionsContainer: { 20 | marginBottom: theme.spacing(2), 21 | }, 22 | resetContainer: { 23 | padding: theme.spacing(3), 24 | }, 25 | })); 26 | 27 | function getSteps() { 28 | return [ 29 | 'Select GraphQL query', 30 | 'View the results', 31 | 'Compare CachiQL metrics' 32 | ]; 33 | } 34 | 35 | function getStepContent(step) { 36 | switch (step) { 37 | case 0: 38 | return `First, enter in a query above using the GraphiQL interface provided. Then, receive your GraphQL test queries back.`; 39 | case 1: 40 | return `Take note of the amount of fetches from the database. Now, make compare the magic of CachiQL.`; 41 | case 2: 42 | return `Try out different GraphQL queries to measure the difference between the metrics calculations of fetch trips in your results.`; 43 | default: 44 | return 'Unknown step'; 45 | } 46 | } 47 | 48 | export default function VerticalLinearStepper() { 49 | const classes = useStyles(); 50 | const [activeStep, setActiveStep] = React.useState(0); 51 | const steps = getSteps(); 52 | 53 | const handleNext = () => { 54 | setActiveStep((prevActiveStep) => prevActiveStep + 1); 55 | }; 56 | 57 | const handleBack = () => { 58 | setActiveStep((prevActiveStep) => prevActiveStep - 1); 59 | }; 60 | 61 | const handleReset = () => { 62 | setActiveStep(0); 63 | }; 64 | 65 | return ( 66 |
67 | 68 | {steps.map((label, index) => ( 69 | 70 | {label} 71 | 72 | {getStepContent(index)} 73 |
74 |
75 | 82 | 90 |
91 |
92 |
93 |
94 | ))} 95 |
96 | {activeStep === steps.length && ( 97 | 98 | All steps completed - you're finished 99 | 102 | 103 | )} 104 |
105 | ); 106 | } -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/Cards.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Card from '@material-ui/core/Card'; 3 | import CardContent from '@material-ui/core/CardContent'; 4 | import CssBaseline from '@material-ui/core/CssBaseline'; 5 | import Grid from '@material-ui/core/Grid'; 6 | import { makeStyles } from '@material-ui/core/styles'; 7 | import Container from '@material-ui/core/Container'; 8 | import Typography from '@material-ui/core/Typography'; 9 | import AutorenewIcon from '@material-ui/icons/Autorenew'; 10 | import QueryBuilderIcon from '@material-ui/icons/QueryBuilder'; 11 | import CodeIcon from '@material-ui/icons/Code'; 12 | 13 | const useStyles = makeStyles((theme) => ({ 14 | cardGrid: { 15 | paddingTop: theme.spacing(8), 16 | paddingBottom: theme.spacing(8) 17 | }, 18 | card: { 19 | height: '100%', 20 | display: 'flex', 21 | flexDirection: 'column', 22 | alignItems: 'center', 23 | alignContent: 'center' 24 | }, 25 | cardMedia: { 26 | paddingTop: '56.25%' // 16:9 27 | }, 28 | cardContent: { 29 | flexGrow: 1 30 | }, 31 | playIcon: { 32 | display: 'flex', 33 | alignItems: 'center', 34 | height: 50, 35 | width: 50 36 | }, 37 | })); 38 | 39 | export const WhyCachiQL = () => { 40 | const classes = useStyles(); 41 | return ( 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | SOLVING THE N+1 ISSUE OF GRAPHQL 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {/* End hero unit */} 59 | 60 | 61 | 62 | 63 | 64 | 65 | The Magic of CachiQL 66 | 67 | 68 | Store, access and maintain deeply-nested GraphQL queries with 69 | CachiQL. 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Saving Time 80 | 81 | 82 | Reduce the amount of database round trips for nested GraphQL queries. 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | Documentation 93 | 94 | 95 | CachiQL is a well-documented, light-weight, open source 96 | library, built for performance. 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | ); 105 | }; 106 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/SmallCachiql.svg: -------------------------------------------------------------------------------- 1 | 2 | cachiql (1)-svg-svg 3 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/blueBackCachiql.svg: -------------------------------------------------------------------------------- 1 | 2 | cachiql (1)-svg-svg 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/cachiqlWhiteLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | cachiql (1)-svg-svg 3 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /cachiql-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 4 | const webpack = require('webpack'); 5 | 6 | 7 | module.exports = { 8 | entry: ['@babel/polyfill', './src/client/index.tsx'], 9 | mode: 'production', 10 | devtool: 'eval-source-map', 11 | output: { 12 | path: path.resolve(__dirname, 'dist'), 13 | publicPath: '/', 14 | filename: 'bundle.js' 15 | }, 16 | devServer: { 17 | host: 'localhost', 18 | contentBase: path.resolve(__dirname, 'dist'), 19 | hot: true, 20 | port: 8080, 21 | publicPath: '/', 22 | inline: true, 23 | proxy: { 24 | '/': { 25 | target: 'http://localhost:3000' 26 | }, 27 | '/graphql': { 28 | target: 'http://localhost:3000' 29 | }, 30 | '/counter': { 31 | target: 'http://localhost:3000' 32 | }, 33 | '/assets': { 34 | target: 'http://localhost:3000' 35 | } 36 | } 37 | }, 38 | module: { 39 | rules: [ 40 | { 41 | test: /\.(ts|js)x?$/i, 42 | exclude: [/node_modules/, __dirname + './splash'], 43 | use: { 44 | loader: 'babel-loader', 45 | options: { 46 | presets: [ 47 | '@babel/preset-env', 48 | '@babel/preset-react', 49 | '@babel/preset-typescript' 50 | ] 51 | } 52 | } 53 | }, 54 | { 55 | test: /\.svg$/, 56 | use: ['@svgr/webpack'], 57 | }, 58 | { 59 | test: /\.(gif|png|jpeg|jpg)$/i, 60 | use: [ 61 | 'file-loader', 62 | { 63 | loader: 'image-webpack-loader', 64 | options: { 65 | bypassOnDebug: true, 66 | disable: true, 67 | webp: { 68 | quality: 75, 69 | } 70 | } 71 | } 72 | ] 73 | }, 74 | { 75 | test: /\.[sac]ss$/i, 76 | use: [MiniCssExtractPlugin.loader, 'css-loader'], 77 | }, 78 | ] 79 | }, 80 | plugins: [ 81 | new HtmlWebpackPlugin({ 82 | template: './src/client/index.html', 83 | inject: true, 84 | filename: 'index.html' 85 | }), 86 | new MiniCssExtractPlugin(), 87 | new webpack.HotModuleReplacementPlugin(), 88 | ], 89 | resolve: { 90 | extensions: ['.tsx', '.ts', '.js'] 91 | } 92 | }; 93 | 94 | // import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; 95 | // import ESLintPlugin from 'eslint-webpack-plugin'; 96 | 97 | // import { Configuration as WebpackConfiguration } from 'webpack'; 98 | // import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server'; 99 | 100 | // interface Configuration extends WebpackConfiguration { 101 | // devServer?: WebpackDevServerConfiguration; 102 | // } 103 | 104 | // const config: Configuration = { 105 | // mode: 'development', 106 | // output: { 107 | // publicPath: '/' 108 | // }, 109 | // entry: './src/client/index.tsx', 110 | // module: { 111 | // rules: [ 112 | // { 113 | // test: /\.(ts|js)x?$/i, 114 | // exclude: [/node_modules/, __dirname + './splash'], 115 | // use: { 116 | // loader: 'babel-loader', 117 | // options: { 118 | // presets: [ 119 | // '@babel/preset-env', 120 | // '@babel/preset-react', 121 | // '@babel/preset-typescript' 122 | // ] 123 | // } 124 | // } 125 | // } 126 | // ] 127 | // }, 128 | // resolve: { 129 | // extensions: ['.tsx', '.ts', '.js'] 130 | // }, 131 | // plugins: [ 132 | // new HtmlWebpackPlugin({ 133 | // template: './src/client/index.html', 134 | // favicon: './src/client/img/favicon.svg' 135 | // }), 136 | // new webpack.HotModuleReplacementPlugin(), 137 | // new ForkTsCheckerWebpackPlugin({ 138 | // async: false, 139 | // typescript: { 140 | // configFile: './src/client/tsconfig.json' 141 | // } 142 | // }), 143 | // new ESLintPlugin({ 144 | // extensions: ['js', 'jsx', 'ts', 'tsx'] 145 | // }) 146 | // ], 147 | // devtool: 'inline-source-map', 148 | // devServer: { 149 | // proxy: { 150 | // '/': 'http://localhost:3000' 151 | // }, 152 | // contentBase: path.join(__dirname, 'build'), 153 | // historyApiFallback: true, 154 | // port: 8080, 155 | // open: false, 156 | // hot: true 157 | // } 158 | // }; 159 | 160 | // export default config; 161 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Alt text](./cachiql-demo/src/client/assets/cachiqlWhiteLogo.svg) 2 | 3 | # About CachiQL 4 | 5 | [![Twitter](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Fcachiql)](https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Foslabs-beta%2FCachiQL) 6 | [![GitHub Stars](https://img.shields.io/github/stars/oslabs-beta/CachiQL)](https://github.com/oslabs-beta/CachiQL/stargazers) 7 | [![GitHub license](https://img.shields.io/github/license/oslabs-beta/CachiQL)](https://github.com/oslabs-beta/CachiQL/blob/dev/LICENSE) 8 | ![npm bundle size](https://img.shields.io/bundlephobia/min/cachiql) 9 | 10 | CachiQL is an ultra-lightweight library designed to batch and cache [graphql-js](https://github.com/graphql/graphql-js "GraphQL JS") queries to reduce calls to databases. Additionally, CachiQL is written in Javascript for use in Node.js. 11 | 12 | Note that batching and caching multiple data requests is not novel to Javascript and Node.js. Additionally, the inspiration behind CachiQL is to deeply understand the implementation of [DataLoader](https://github.com/graphql/dataloader "DataLoader GitHub"), which was created by [Lee Byron](https://github.com/leebyron "Lee Bryon GitHub") at Facebook to solve the common N +1 issue of a naive GraphQL server. Our team’s purpose is not to replace DataLoader but rather, to help others understand the rationale behind DataLoader and create a simplified and lightweight NPM package. 13 | 14 | ## Installation 15 | 16 | --- 17 | 18 | Install the CachiQL package using npm. 19 | 20 | ```JavaScript 21 | npm install --save cachiql 22 | ``` 23 | 24 | Now in order to use CachiQL, create a new instance of CachiQL. Each instance is created for each request using a web server, such as [express](https://github.com/expressjs/express "Express GitHub"). 25 | 26 | Although CachiQL does not require any dependencies, this package requires a global Javascript run-time environment with ES6 Promise. 27 | 28 | ## How to Use CachiQL 29 | 30 | --- 31 | 32 | Batch processing is the cornerstone of the functionality of the CachiQL package. Because GraphQL standardizes resolvers with a depth-first-search execution query, the issue of N+1 arises. Simply put, the server then executes multiple and unnecessary trips to the database, over-fetching to waste computing resources and bandwidth. 33 | 34 | ```JavaScript**_NOTE:_** 35 | const cachiql = require(‘cachiql’); 36 | 37 | const schema = new GraphQLSchema({ 38 | query: RootQueryType 39 | }); 40 | 41 | app.use( 42 | '/graphql', 43 | graphqlHTTP({ 44 | schema: schema, 45 | graphiql: true, 46 | context: { 47 | authorLoader: new Cachiql(AuthorLoader), 48 | bookLoader: new Cachiql(BookLoader), 49 | cachedData: [] 50 | } 51 | }) 52 | ); 53 | 54 | ``` 55 | 56 | ### Batching 57 | 58 | --- 59 | 60 | The CachiQL class constructor includes a batch loader that takes in an array of keys and returns a promise for each key which eventually resolves to the return array of values or the promise is rejected. 61 | 62 | A loader enables a load of individual values before executing the batch with all the included keys. 63 | 64 | ```JavaScript 65 | 66 | const batchAuthors = async (ids) => { 67 | try { 68 | const authors = await Author.find({ _id: { $in: ids } }); 69 | return authors; 70 | } catch (err) { 71 | throw new Error('There was an error getting the Authors'); 72 | } 73 | }; 74 | 75 | module.exports = batchAuthors; 76 | 77 | const batchBooks = async (ids) => { 78 | try { 79 | const books = await Book.find({ _id: { $in: ids } }); 80 | return books; 81 | } catch (err) { 82 | throw new Error('There was an error getting the Books'); 83 | } 84 | }; 85 | 86 | module.exports = batchBooks; 87 | 88 | ``` 89 | 90 | ### Caching 91 | 92 | --- 93 | 94 | CachiQL includes a memoized cache for the loads. Additionally, CachiQL further parses through the array of keys, removing duplicates. Finally, note that you can use application-level caches such as Redis. The idea behind CachiQL’s memoized cache is just not to repeat the same data in each request. 95 | 96 | ### CachiQL and GraphQL 97 | 98 | --- 99 | 100 | The utility of CachiQL is to eliminate the depth-first search structure of GraphQL standard resolvers. In other words, CachiQL aims to solve the N+1 issue that a GraphQL server creates when new database requests are issued as fields are resolved. 101 | 102 | In the example provided, using a GraphQL standard resolver, querying a database containing 16 books by three different authors means that submitting a singular deeply nested query issues 16 trips for the information. However, using CachiQL creates more efficiency by only making two round trips to the backend. 103 | 104 | **_NOTE:_** The array of values needs to be the same length as the array of keys. 105 | -------------------------------------------------------------------------------- /cachiql/README.md: -------------------------------------------------------------------------------- 1 | ![Alt text](../cachiql-demo/src/assets/SmallCachiql.svg) 2 | 3 | # About CachiQL 4 | 5 | [![Twitter](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Fcachiql)](https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Foslabs-beta%2FCachiQL) 6 | [![GitHub Stars](https://img.shields.io/github/stars/oslabs-beta/CachiQL)](https://github.com/oslabs-beta/CachiQL/stargazers) 7 | [![GitHub license](https://img.shields.io/github/license/oslabs-beta/CachiQL)](https://github.com/oslabs-beta/CachiQL/blob/dev/LICENSE) 8 | ![npm bundle size](https://img.shields.io/bundlephobia/min/cachiql) 9 | 10 | CachiQL is an ultra-lightweight library designed to batch and cache [graphql-js](https://github.com/graphql/graphql-js "GraphQL JS") queries to reduce calls to databases. Additionally, CachiQL is written in Javascript for use in Node.js. 11 | 12 | Note that batching and caching multiple data requests is not novel to Javascript and Node.js. Additionally, the inspiration behind CachiQL is to deeply understand the implementation of [DataLoader](https://github.com/graphql/dataloader "DataLoader GitHub"), which was created by [Lee Byron](https://github.com/leebyron "Lee Bryon GitHub") at Facebook to solve the common N +1 issue of a naive GraphQL server. Our team’s purpose is not to replace DataLoader but rather, to help others understand the rationale behind DataLoader and create a simplified and lightweight NPM package. 13 | 14 | ## Installation 15 | 16 | --- 17 | 18 | Install the CachiQL package using npm. 19 | 20 | ```JavaScript 21 | npm install --save cachiql 22 | ``` 23 | 24 | Now in order to use CachiQL, create a new instance of CachiQL. Each instance is created for each request using a web server, such as [express](https://github.com/expressjs/express "Express GitHub"). 25 | 26 | Although CachiQL does not require any dependencies, this package requires a global Javascript run-time environment with ES6 Promise. 27 | 28 | ## How to Use CachiQL 29 | 30 | --- 31 | 32 | Batch processing is the cornerstone of the functionality of the CachiQL package. Because GraphQL standardizes resolvers with a depth-first-search execution query, the issue of N+1 arises. Simply put, the server then executes multiple and unnecessary trips to the database, over-fetching to waste computing resources and bandwidth. 33 | 34 | ```JavaScript**_NOTE:_** 35 | const cachiql = require(‘cachiql’); 36 | 37 | const schema = new GraphQLSchema({ 38 | query: RootQueryType 39 | }); 40 | 41 | app.use( 42 | '/graphql', 43 | graphqlHTTP({ 44 | schema: schema, 45 | graphiql: true, 46 | context: { 47 | authorLoader: new Cachiql(AuthorLoader), 48 | bookLoader: new Cachiql(BookLoader), 49 | cachedData: [] 50 | } 51 | }) 52 | ); 53 | 54 | ``` 55 | 56 | ### Batching 57 | 58 | --- 59 | 60 | The CachiQL class constructor includes a batch loader that takes in an array of keys and returns a promise for each key which eventually resolves to the return array of values or the promise is rejected. 61 | 62 | A loader enables a load of individual values before executing the batch with all the included keys. 63 | 64 | ```JavaScript 65 | 66 | const batchAuthors = async (ids) => { 67 | try { 68 | const authors = await Author.find({ _id: { $in: ids } }); 69 | return authors; 70 | } catch (err) { 71 | throw new Error('There was an error getting the Authors'); 72 | } 73 | }; 74 | 75 | module.exports = batchAuthors; 76 | 77 | const batchBooks = async (ids) => { 78 | try { 79 | const books = await Book.find({ _id: { $in: ids } }); 80 | return books; 81 | } catch (err) { 82 | throw new Error('There was an error getting the Books'); 83 | } 84 | }; 85 | 86 | module.exports = batchBooks; 87 | 88 | ``` 89 | 90 | ### Caching 91 | 92 | --- 93 | 94 | CachiQL includes a memoized cache for the loads. Additionally, CachiQL further parses through the array of keys, removing duplicates. Finally, note that you can use application-level caches such as Redis. The idea behind CachiQL’s memoized cache is just not to repeat the same data in each request. 95 | 96 | ### CachiQL and GraphQL 97 | 98 | --- 99 | 100 | The utility of CachiQL is to eliminate the depth-first search structure of GraphQL standard resolvers. In other words, CachiQL aims to solve the N+1 issue that a GraphQL server creates when new database requests are issued as fields are resolved. 101 | 102 | In the example provided, using a GraphQL standard resolver, querying a database containing 16 books by three different authors means that submitting a singular deeply nested query issues 16 trips for the information. However, using CachiQL creates more efficiency by only making two round trips to the backend. 103 | 104 | **_NOTE:_** The array of values needs to be the same length as the array of keys. 105 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/Components/PersonalLinks.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LinkedInIcon from '@material-ui/icons/LinkedIn'; 3 | import GitHubIcon from '@material-ui/icons/GitHub'; 4 | import Card from '@material-ui/core/Card'; 5 | import Container from '@material-ui/core/Container'; 6 | import { makeStyles } from '@material-ui/core/styles'; 7 | // import Typography from '@material-ui/core/Typography'; 8 | // import Link from '@material-ui/core/Link'; 9 | import IconButton from '@material-ui/core/IconButton'; 10 | // import Avatar from '@material-ui/core/Avatar'; 11 | // import { Avatars } from './Avatars'; 12 | import Typography from '@material-ui/core/Typography'; 13 | import Kaden from '../../assets/resizedKaden-svg.svg'; 14 | import Vanessa from '../../assets/resizedVanessa-svg.svg'; 15 | import Eddie from '../../assets/resizedEddy-svg.svg'; 16 | import Fahad from '../../assets/resizedFahad-svg.svg'; 17 | 18 | const useStyles = makeStyles((theme) => ({ 19 | cardGrid: { 20 | paddingTop: theme.spacing(8), 21 | paddingBottom: theme.spacing(8) 22 | }, 23 | card: { 24 | height: '100%', 25 | display: 'flex', 26 | flexDirection: 'column', 27 | alignItems: 'center', 28 | alignContent: 'center' 29 | }, 30 | cardMedia: { 31 | paddingTop: '56.25%' // 16:9 32 | }, 33 | cardContent: { 34 | flexGrow: 1 35 | }, 36 | svgIcon: { 37 | transform: 'scale(1.0)' 38 | }, 39 | cardMedia: { 40 | borderRadius: '50%', 41 | margin: '28px' 42 | }, 43 | cardMedia2: { 44 | borderRadius: '50%', 45 | margin: '38px', 46 | paddingRight: '81px' 47 | }, 48 | container: { 49 | paddingTop: '20px', 50 | alignContent: 'space-between' 51 | } 52 | })); 53 | 54 | export const Linkage = () => { 55 | const classes = useStyles(); 56 | return ( 57 | 58 | 59 | 60 | 61 | Kaden Johnson 62 | 63 | 64 | 65 | 66 | 67 | 71 | window.open('https://www.linkedin.com/in/kaden-johnson/') 72 | } 73 | > 74 | 75 | 76 | 80 | window.open('https://www.linkedin.com/in/vanessa-lutz/') 81 | } 82 | > 83 | 84 | 85 | 89 | window.open('https://www.linkedin.com/in/eddy-zapata/') 90 | } 91 | > 92 | 93 | 94 | 98 | window.open('http://www.linkedin.com/in/fahadmshaikh') 99 | } 100 | > 101 | 102 | 103 | 104 | 105 | window.open('https://github.com/Kadenj117')} 109 | > 110 | 111 | 112 | window.open('https://github.com/vanessalutz')} 116 | > 117 | 118 | 119 | window.open('http://github.com/zapata124')} 123 | > 124 | 125 | 126 | window.open('https://github.com/fahdie')} 130 | > 131 | 132 | 133 | 134 | 135 | 136 | ); 137 | }; 138 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/teamCachiql.svg: -------------------------------------------------------------------------------- 1 | 2 | cachiql (1)-svg-svg 3 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /cachiql/index.js: -------------------------------------------------------------------------------- 1 | // A function which will return a promise 2 | // INPUT: array of values 3 | // OUTPUT: promise of arrays values or errors 4 | const loader = (keys) => { 5 | return new Promise(keys) || new Error; 6 | }; 7 | 8 | 9 | // Cachiql class which returns promises for each key and 10 | // removes unnecessary duplicates to minify the batch that needs 11 | // to be queried by the database. Best used for large databases to 12 | // stop collecting the same data multiple times 13 | // INPUT: Loader Function with an array of keys 14 | // OUTPUT: minified Array of keys without duplicates 15 | class Cachiql { 16 | constructor(loader) { 17 | //Error handler to check for the correct parameter type 18 | if (typeof loader !== 'function') { 19 | throw new Error( 20 | 'Cachiql must have a function passed in as a parameter but received', loader 21 | ); 22 | }; 23 | // save variables for the function and the batch which will be returned 24 | this.loader = loader; 25 | this.batch = null; 26 | 27 | }; 28 | 29 | // Creates a promise for each individual key and waits for a resolve or a reject 30 | // INPUT: a single key 31 | // OUTPUT: a promise for the key 32 | load(key) { 33 | // Error handling for unusable variable types 34 | if (key == null || key === undefined) { 35 | throw new Error( 36 | 'The key passed into the function is undefined please use valid key' 37 | ); 38 | }; 39 | 40 | // Create or add to the batch to save both key and promise 41 | const batch = getBatch(this); 42 | 43 | // Add key to the instance of the batch and create the promise 44 | // for the key and add them to the batch to be checked later 45 | batch.keys.push(key); 46 | const keyPromise = new Promise((resolve, reject) => { 47 | batch.cbs.push({ resolve, reject }); 48 | }); 49 | 50 | // Return the key promise to bundle the promises 51 | return keyPromise; 52 | } 53 | 54 | // Removes any duplicates from the array of keys and 55 | // creates a promise for each key and bundles them together to be resolved 56 | // INPUT: array of keys 57 | // OUTPUT: Array of Promises for each key 58 | loadAll(keys) { 59 | 60 | // Error Handling to check if the parameter is an array 61 | if (!Array.isArray(keys)) { 62 | throw new Error( 63 | 'The value passed into the loadAll() function is not an array' 64 | ) 65 | } 66 | 67 | // Checks if the batch is empty and if not clears it for 68 | // use in the following code 69 | if(this.batch !== null) clearBatch(this.batch) 70 | 71 | // Helper function to remove any duplicated keys from the array 72 | // INPUT: Array of keys sent by the user 73 | // OUTPUT: Altered and minified array 74 | function removeDuplicates(data) { 75 | const arr = [] 76 | data.forEach((el, i) => { 77 | let length = arr.length; 78 | let included = false 79 | for (let i = 0; i < length; i++) { 80 | if (el.toString() === arr[i].toString()) { 81 | included = true; 82 | } 83 | } 84 | if (!included) arr.push(el) 85 | }) 86 | return arr; 87 | } 88 | 89 | const uniqueKeys = removeDuplicates(keys) 90 | 91 | // Running the load() function on each individual key in the array 92 | const promiseLoader = []; 93 | for (let i = 0; i < uniqueKeys.length; i++) { 94 | promiseLoader.push(this.load(uniqueKeys[i]).catch(error => error)); 95 | 96 | } 97 | 98 | // Sending the new batch with all the added in promises and 99 | // key values to the loader function 100 | sendBatch(this, this.batch); 101 | 102 | // Returns all the promises to be resolved later 103 | return Promise.all(promiseLoader); 104 | } 105 | 106 | 107 | } 108 | 109 | 110 | // Setup the batch object for use in the cachiql class 111 | const batch = { 112 | hasSent: false, 113 | keys: [], 114 | cbs: [], 115 | cacheHits: [] 116 | } 117 | 118 | // Clears the Batch of any data if having error with batching 119 | // INPUT: The current batch that needs cleared 120 | // OUTPUT: the emptied batch 121 | const clearBatch = (batch) => { 122 | batch.hasSent = false; 123 | batch.keys = [] 124 | batch.cbs = [] 125 | cacheHits = [] 126 | 127 | } 128 | 129 | // Setup the batch to save the data for the promises 130 | // INPUT: the current cachiql instance 131 | // OUTPUT: the newly created batch object 132 | const getBatch = (cachiql) => { 133 | cachiql.batch = batch; 134 | return batch; 135 | } 136 | 137 | // Handles Errors with rejected promises and runs the loader function on the keys 138 | // INPUT: the current instance of cachiql and the current batch 139 | // OUTPUT: nothing to return just throwing errors for rejected data 140 | const sendBatch = (cachiql, batch) => { 141 | batch.hasSent = true; 142 | 143 | // Check to make sure the batch is loaded before running the loader function 144 | if (batch.keys.length === 0) { 145 | return; 146 | } 147 | 148 | // Run the loader function and save the data that is returned 149 | const promisedBatch = cachiql.loader(batch.keys); 150 | 151 | // Handle errors with the promisedBatch to make sure it in not null and function 152 | if (!promisedBatch || typeof promisedBatch.then !== 'function') { 153 | throw new Error( 154 | 'The cachiql class must be built with a function that takes an array and returns a promise' 155 | ) 156 | } 157 | 158 | // Checks the batch to see if the data returned is an array 159 | promisedBatch.then(data => { 160 | if (!Array.isArray(data)) { 161 | throw new Error( 162 | 'The data returned needs to be an array' 163 | ) 164 | } 165 | 166 | // Compare lengths to make sure that the developer received 167 | // the same amount of data that was called 168 | if (data.length !== batch.keys.length) { 169 | throw new Error( 170 | 'The batch object does not contain the correct length of keys' 171 | ) 172 | } 173 | 174 | // Iterate through the array of data and handle resolves and rejects 175 | // Note: rejects should only return if the key did not query any data 176 | for (let i = 0; i < batch.cbs.length; i++) { 177 | let val = data[i]; 178 | if (val instanceof Error) { 179 | batch.cbs[i].reject(val); 180 | } 181 | else { 182 | batch.cbs[i].resolve(val); 183 | } 184 | } 185 | }).catch(error => error) 186 | } 187 | 188 | 189 | module.exports = { Cachiql }; -------------------------------------------------------------------------------- /cachiql-demo/src/server/cachiql.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/ 2 | 3 | /** 4 | * This function loader returns a singular promise 5 | * @param {*} keys Takes in an array of values 6 | * @returns A promise of values or errors 7 | */ 8 | 9 | const loader = (keys) => { 10 | return new Promise(keys) || new Error(); 11 | }; 12 | 13 | /** 14 | * The CachiQL class constructor returns promises for each key, 15 | removing unnecessary duplicates to minify the batch that needs 16 | to be queried by the database. Best used for large databases to 17 | optimize collection of the same data multiple times. 18 | 19 | INPUT: Takes in a loader function with an array of keys. 20 | OUTPUT: Returns a minified array of keys without duplicate values. 21 | */ 22 | 23 | class Cachiql { 24 | constructor(loader) { 25 | //Error handling to ensure a function is entered. 26 | if (typeof loader !== 'function') { 27 | throw new Error( 28 | 'Cachiql must have a function passed in as a parameter but received', 29 | loader 30 | ); 31 | } 32 | //Save variables for the function and the batch 33 | this.loader = loader; 34 | this.batch = null; 35 | } 36 | 37 | /** 38 | * Creates a promise for each individual key and awaits for a resolve or a reject. 39 | * @param {*} key Takes in a single key 40 | * @returns Returns a promise for the singular key 41 | */ 42 | 43 | load(key) { 44 | // Error handling for invalid variable types 45 | if (key == null || key === undefined || Array.isArray(key)) { 46 | throw new Error( 47 | 'The key passed into the function is undefined please use valid key' 48 | ); 49 | } 50 | 51 | // Create or add to the batch to save key and promise 52 | const batch = getBatch(this); 53 | 54 | // Add key to the instance of the batch and create the promise 55 | // Allows for the key to be added to the batch to be resolved or rejected at a later time 56 | batch.keys.push(key); 57 | const keyPromise = new Promise((resolve, reject) => { 58 | batch.cbs.push({ resolve, reject }); 59 | }); 60 | 61 | // Return the key promise to bundle the promises 62 | return keyPromise; 63 | } 64 | 65 | /** 66 | * Removes any duplicates from the array of keys and 67 | * creates a promise for each key by bundling together for eventual resolving 68 | * 69 | * @param {*} keys Takes in an array of keys 70 | * @returns Returns an array of promises for each key 71 | */ 72 | 73 | loadAll(keys) { 74 | // Error Handling to ensure the parameter is an array 75 | if (!Array.isArray(keys)) { 76 | throw new Error( 77 | 'The value passed into the loadAll() function is not an array' 78 | ); 79 | } 80 | 81 | // Checks for an empty batch and if the batch is not empty, clears it. 82 | 83 | if (this.batch !== null) clearBatch(this.batch); 84 | 85 | /** 86 | * Helper function to remove duplicated keys from the array 87 | * @param {*} data Takes in an array of keys sent by the user 88 | * @returns Returns an altered and minified array 89 | */ 90 | 91 | function removeDuplicates(data) { 92 | const arr = []; 93 | data.forEach((el, i) => { 94 | let length = arr.length; 95 | let included = false; 96 | for (let i = 0; i < length; i++) { 97 | if (el.toString() === arr[i].toString()) { 98 | included = true; 99 | } 100 | } 101 | if (!included) arr.push(el); 102 | }); 103 | return arr; 104 | } 105 | 106 | const uniqueKeys = removeDuplicates(keys); 107 | 108 | // Runs the load() function on each individual key in the array 109 | const promiseLoader = []; 110 | for (let i = 0; i < uniqueKeys.length; i++) { 111 | promiseLoader.push(this.load(uniqueKeys[i]).catch((error) => error)); 112 | } 113 | 114 | // Sends the new batch with all the additional promises and 115 | // key values to the loader function 116 | sendBatch(this, this.batch); 117 | 118 | // Returns all the promises to be resolved later 119 | return Promise.all(promiseLoader); 120 | } 121 | } 122 | 123 | //Creating a batch object for the CachiQL class 124 | 125 | const batch = { 126 | hasSent: false, 127 | keys: [], 128 | cbs: [] 129 | }; 130 | 131 | /** 132 | * Clears the batch of data if an error occurs with batching 133 | * @param {*} batch Takes in the current batch that needs cleared 134 | */ 135 | 136 | const clearBatch = (batch) => { 137 | batch.hasSent = false; 138 | batch.keys = []; 139 | batch.cbs = []; 140 | }; 141 | 142 | /** 143 | * Setup for the batch and saving data for the promises 144 | * @param {*} cachiql Takes in the current CachiQL instance 145 | * @returns Returns the newly created batch object 146 | * 147 | */ 148 | 149 | const getBatch = (cachiql) => { 150 | cachiql.batch = batch; 151 | return batch; 152 | }; 153 | 154 | /** 155 | * Handles errors for rejected promises and runs the loader function on the keys 156 | * @param {*} cachiql Takes in the current instance of CachiQL and the current batch 157 | * @param {*} batch 158 | * @returns No return needed, unless errors are thrown for rejected data. 159 | */ 160 | 161 | const sendBatch = (cachiql, batch) => { 162 | batch.hasSent = true; 163 | 164 | // Check to ensure the batch is loaded before running the loader function 165 | if (batch.keys.length === 0) { 166 | return; 167 | } 168 | 169 | // Runs the loader function and saves returned data 170 | const promisedBatch = cachiql.loader(batch.keys); 171 | 172 | // Error handling of the promisedBatch 173 | if (!promisedBatch || typeof promisedBatch.then !== 'function') { 174 | throw new Error( 175 | 'The cachiql class must be built with a function that takes an array and returns a promise' 176 | ); 177 | } 178 | 179 | // Checks the batch to ensure that an array is returned 180 | promisedBatch 181 | .then((data) => { 182 | if (!Array.isArray(data)) { 183 | throw new Error('The data returned needs to be an array'); 184 | } 185 | 186 | // Compare lengths that the developer received 187 | // the same amount of data that was called 188 | if (data.length !== batch.keys.length) { 189 | throw new Error( 190 | 'The batch object does not contain the correct length of keys' 191 | ); 192 | } 193 | 194 | // Iterate through the array of data and handle resolves and rejects 195 | // Note: rejects should only return if the key did not query any data 196 | for (let i = 0; i < batch.cbs.length; i++) { 197 | let val = data[i]; 198 | if (val instanceof Error) { 199 | batch.cbs[i].reject(val); 200 | } else { 201 | batch.cbs[i].resolve(val); 202 | } 203 | } 204 | }) 205 | .catch((error) => error); 206 | }; 207 | 208 | module.exports = { Cachiql }; 209 | -------------------------------------------------------------------------------- /cachiql-demo/src/server/server.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/ 2 | 3 | const express = require('express'); 4 | const mongoose = require('mongoose'); 5 | const { graphqlHTTP } = require('express-graphql'); 6 | const { 7 | GraphQLSchema, 8 | GraphQLObjectType, 9 | GraphQLString, 10 | GraphQLList, 11 | GraphQLInt, 12 | GraphQLNonNull, 13 | GraphQLID 14 | } = require('graphql'); 15 | const Author = require('./models/author'); 16 | const Book = require('./models/book'); 17 | const app = express(); 18 | const cache = require('memory-cache'); 19 | const AuthorLoader = require('./AuthorLoader'); 20 | const BookLoader = require('./BookLoader'); 21 | const { Cachiql } = require('./cachiql'); 22 | const path = require('path'); 23 | //const {AuthorType, BookType} = require('./resolvercache') 24 | 25 | let mockCounter = 0; 26 | let counter = 0; 27 | 28 | app.use(express.static(path.resolve(__dirname, '../../dist'))) 29 | 30 | 31 | 32 | app.get('/counter', (req, res) => { 33 | let num = counter; 34 | res.locals.num = num; 35 | res.locals.mockNum = mockCounter; 36 | counter = 0; 37 | mockCounter = 0; 38 | console.log('count: ', num); 39 | return res.status(200).json([ 40 | { 41 | name: 'Query Results', 42 | GraphQL: res.locals.mockNum, 43 | CachiQL: res.locals.num 44 | } 45 | ]); 46 | }); 47 | 48 | app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, '../../dist/index.html'))) 49 | 50 | const AuthorType = new GraphQLObjectType({ 51 | name: 'Author', 52 | description: 'This represents an author of a book', 53 | fields: () => ({ 54 | _id: { type: GraphQLNonNull(GraphQLID) }, 55 | firstName: { type: GraphQLNonNull(GraphQLString) }, 56 | lastName: { type: GraphQLNonNull(GraphQLString) }, 57 | books: { 58 | type: new GraphQLList(BookType), 59 | resolve: async (author, _, context) => { 60 | if (context.cachedData.length === 0) { 61 | counter += 1; 62 | return await Book.find({ Author: author._id }); 63 | } else { 64 | const arr = []; 65 | for (let i = 0; i < context.cachedData.length; i++) { 66 | const book = context.cachedData[i]; 67 | for (let j = 0; j < author.books.length; j++) { 68 | const authBook = author.books[j]; 69 | if (authBook.toString() === book._id.toString()) { 70 | arr.push(book); 71 | } 72 | } 73 | } 74 | if (arr.length !== author.books.length) { 75 | counter += 1; 76 | return await Book.find({ Author: author._id }); 77 | } 78 | setTimeout(() => console.log('timed out'), 0); 79 | 80 | return arr; 81 | } 82 | } 83 | } 84 | }) 85 | }); 86 | 87 | const BookType = new GraphQLObjectType({ 88 | name: 'Book', 89 | description: 'This represents a book written by an author', 90 | fields: () => ({ 91 | _id: { type: GraphQLNonNull(GraphQLID) }, 92 | title: { type: GraphQLNonNull(GraphQLString) }, 93 | Author: { 94 | type: AuthorType, 95 | //need to change this to match db requirements 96 | resolve: async (book, _, context) => { 97 | if (context.cachedData.length === 0) { 98 | counter += 1; 99 | return await Author.findOne({ books: book._id }); 100 | } else { 101 | for (let i = 0; i < context.cachedData.length; i++) { 102 | const author = context.cachedData[i]; 103 | for (let j = 0; j < author.books.length; j++) { 104 | const authBook = author.books[j]; 105 | if (authBook.toString() === book._id.toString()) return author; 106 | } 107 | } 108 | counter += 1; 109 | 110 | return await Author.findOne({ books: book._id }); 111 | } 112 | } 113 | } 114 | }) 115 | }); 116 | 117 | const RootQueryType = new GraphQLObjectType({ 118 | name: 'Query', 119 | description: 'Root Query', 120 | context: () => console.log('hello'), 121 | fields: () => ({ 122 | book: { 123 | type: BookType, 124 | description: 'A single Book', 125 | args: { 126 | id: { type: GraphQLID } 127 | }, 128 | //db query instead to get this 129 | resolve: async (parent, args) => { 130 | let fetched = await Book.findById(args.id); 131 | counter += 1; 132 | return fetched; 133 | } 134 | }, 135 | books: { 136 | type: new GraphQLList(BookType), 137 | description: 'List of Books', 138 | //query db in resolve instead of returning the books object 139 | resolve: async (parent, other, context) => { 140 | //console.log(context.authorLoader) 141 | let fetched = await Book.find({}); 142 | counter += 1; 143 | mockCounter += 1; 144 | let keys = []; 145 | fetched.forEach((key) => keys.push(key.Author)); 146 | console.log(context.cachedData); 147 | 148 | context.cachedData = await context.authorLoader.loadAll(keys); 149 | if (context.cachedData.length !== 0) { 150 | counter += 1; 151 | } 152 | mockCounter += keys.length; 153 | console.log('mockCounter', mockCounter); 154 | setTimeout(() => (context.cachedData = []), 0); 155 | return fetched; 156 | } 157 | }, 158 | author: { 159 | type: AuthorType, 160 | description: 'A Single Author', 161 | args: { 162 | id: { type: GraphQLID } 163 | }, 164 | //query db in resolve instead of returning the books object 165 | resolve: async (parent, args) => { 166 | counter += 1; 167 | return Author.findOne({ _id: args.id }); 168 | } 169 | }, 170 | authors: { 171 | type: new GraphQLList(AuthorType), 172 | description: 'List of all Authors', 173 | //query db in resolve instead of returning the books object 174 | resolve: async (parent, _, context) => { 175 | let fetched = await Author.find({}); 176 | counter += 1; 177 | mockCounter += 1; 178 | let keys = []; 179 | fetched.forEach((key) => keys.push(...key.books)); 180 | mockCounter += keys.length; 181 | 182 | context.cachedData = await context.bookLoader.loadAll(keys); 183 | if (context.cachedData.length !== 0) { 184 | counter += 1; 185 | } 186 | 187 | console.log(mockCounter); 188 | return fetched; 189 | } 190 | } 191 | }) 192 | }); 193 | 194 | const schema = new GraphQLSchema({ 195 | query: RootQueryType 196 | }); 197 | 198 | app.use( 199 | '/graphql', 200 | graphqlHTTP({ 201 | schema: schema, 202 | graphiql: true, 203 | context: { 204 | authorLoader: new Cachiql(AuthorLoader), 205 | bookLoader: new Cachiql(BookLoader), 206 | cachedData: [] 207 | } 208 | }) 209 | ); 210 | const { PORT = 3000 } = process.env 211 | 212 | const uri = 213 | 'mongodb+srv://cachiql:cache@cachiql.pypfo.mongodb.net/cachiql?retryWrites=true&w=majority'; 214 | const options = { useNewUrlParser: true, useUnifiedTopology: true }; 215 | mongoose 216 | .connect(uri, options) 217 | .then(() => 218 | app.listen(PORT, console.log(` New Server running with mongodb on ${PORT}`)) 219 | ) 220 | .catch((error) => { 221 | throw error; 222 | }); 223 | -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/cachiql_(1)-svg_(2).svg: -------------------------------------------------------------------------------- 1 | 2 | cachiql (1)-svg 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /cachiql-demo/dist/574.bundle.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkcachiql_demo=self.webpackChunkcachiql_demo||[]).push([[574],{1574:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{eval('__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(97480);\n/* harmony import */ var _index_es_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(59361);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(67294);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(73935);\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, "name", { value, configurable: true });\n\n\n\n\n\n_codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.defineOption("info", false, (cm, options, old) => {\n if (old && old !== _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.Init) {\n const oldOnMouseOver = cm.state.info.onMouseOver;\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(cm.getWrapperElement(), "mouseover", oldOnMouseOver);\n clearTimeout(cm.state.info.hoverTimeout);\n delete cm.state.info;\n }\n if (options) {\n const state = cm.state.info = createState(options);\n state.onMouseOver = onMouseOver.bind(null, cm);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);\n }\n});\nfunction createState(options) {\n return {\n options: options instanceof Function ? { render: options } : options === true ? {} : options\n };\n}\n__name(createState, "createState");\nfunction getHoverTime(cm) {\n const options = cm.state.info.options;\n return (options === null || options === void 0 ? void 0 : options.hoverTime) || 500;\n}\n__name(getHoverTime, "getHoverTime");\nfunction onMouseOver(cm, e) {\n const state = cm.state.info;\n const target = e.target || e.srcElement;\n if (!(target instanceof HTMLElement)) {\n return;\n }\n if (target.nodeName !== "SPAN" || state.hoverTimeout !== void 0) {\n return;\n }\n const box = target.getBoundingClientRect();\n const onMouseMove = /* @__PURE__ */ __name(function() {\n clearTimeout(state.hoverTimeout);\n state.hoverTimeout = setTimeout(onHover, hoverTime);\n }, "onMouseMove");\n const onMouseOut = /* @__PURE__ */ __name(function() {\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(document, "mousemove", onMouseMove);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(cm.getWrapperElement(), "mouseout", onMouseOut);\n clearTimeout(state.hoverTimeout);\n state.hoverTimeout = void 0;\n }, "onMouseOut");\n const onHover = /* @__PURE__ */ __name(function() {\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(document, "mousemove", onMouseMove);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(cm.getWrapperElement(), "mouseout", onMouseOut);\n state.hoverTimeout = void 0;\n onMouseHover(cm, box);\n }, "onHover");\n const hoverTime = getHoverTime(cm);\n state.hoverTimeout = setTimeout(onHover, hoverTime);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.on(document, "mousemove", onMouseMove);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.on(cm.getWrapperElement(), "mouseout", onMouseOut);\n}\n__name(onMouseOver, "onMouseOver");\nfunction onMouseHover(cm, box) {\n const pos = cm.coordsChar({\n left: (box.left + box.right) / 2,\n top: (box.top + box.bottom) / 2\n });\n const state = cm.state.info;\n const options = state.options;\n const render = options.render || cm.getHelper(pos, "info");\n if (render) {\n const token = cm.getTokenAt(pos, true);\n if (token) {\n const info = render(token, options, cm, pos);\n if (info) {\n showPopup(cm, box, info);\n }\n }\n }\n}\n__name(onMouseHover, "onMouseHover");\nfunction showPopup(cm, box, info) {\n const popup = document.createElement("div");\n popup.className = "CodeMirror-info";\n popup.appendChild(info);\n document.body.appendChild(popup);\n const popupBox = popup.getBoundingClientRect();\n const popupStyle = window.getComputedStyle(popup);\n const popupWidth = popupBox.right - popupBox.left + parseFloat(popupStyle.marginLeft) + parseFloat(popupStyle.marginRight);\n const popupHeight = popupBox.bottom - popupBox.top + parseFloat(popupStyle.marginTop) + parseFloat(popupStyle.marginBottom);\n let topPos = box.bottom;\n if (popupHeight > window.innerHeight - box.bottom - 15 && box.top > window.innerHeight - box.bottom) {\n topPos = box.top - popupHeight;\n }\n if (topPos < 0) {\n topPos = box.bottom;\n }\n let leftPos = Math.max(0, window.innerWidth - popupWidth - 15);\n if (leftPos > box.left) {\n leftPos = box.left;\n }\n popup.style.opacity = "1";\n popup.style.top = topPos + "px";\n popup.style.left = leftPos + "px";\n let popupTimeout;\n const onMouseOverPopup = /* @__PURE__ */ __name(function() {\n clearTimeout(popupTimeout);\n }, "onMouseOverPopup");\n const onMouseOut = /* @__PURE__ */ __name(function() {\n clearTimeout(popupTimeout);\n popupTimeout = setTimeout(hidePopup, 200);\n }, "onMouseOut");\n const hidePopup = /* @__PURE__ */ __name(function() {\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(popup, "mouseover", onMouseOverPopup);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(popup, "mouseout", onMouseOut);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.off(cm.getWrapperElement(), "mouseout", onMouseOut);\n if (popup.style.opacity) {\n popup.style.opacity = "0";\n setTimeout(() => {\n if (popup.parentNode) {\n popup.parentNode.removeChild(popup);\n }\n }, 600);\n } else if (popup.parentNode) {\n popup.parentNode.removeChild(popup);\n }\n }, "hidePopup");\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.on(popup, "mouseover", onMouseOverPopup);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.on(popup, "mouseout", onMouseOut);\n _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.C.on(cm.getWrapperElement(), "mouseout", onMouseOut);\n}\n__name(showPopup, "showPopup");\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTU3NC5qcyIsIm1hcHBpbmdzIjoiOzs7OztBQUFBO0FBQ0EsNERBQTRELDJCQUEyQjtBQUNsQztBQUM5QjtBQUNOO0FBQ0Y7QUFDSTtBQUNuQiw2REFBdUI7QUFDdkIscUJBQXFCLHFEQUFlO0FBQ3BDO0FBQ0EsSUFBSSxvREFBYztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJLG1EQUFhO0FBQ2pCO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQSw2Q0FBNkMsa0JBQWtCLHdCQUF3QjtBQUN2RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxJQUFJLG9EQUFjO0FBQ2xCLElBQUksb0RBQWM7QUFDbEI7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLElBQUksb0RBQWM7QUFDbEIsSUFBSSxvREFBYztBQUNsQjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxFQUFFLG1EQUFhO0FBQ2YsRUFBRSxtREFBYTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxJQUFJLG9EQUFjO0FBQ2xCLElBQUksb0RBQWM7QUFDbEIsSUFBSSxvREFBYztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsTUFBTTtBQUNOO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRSxtREFBYTtBQUNmLEVBQUUsbURBQWE7QUFDZixFQUFFLG1EQUFhO0FBQ2Y7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2NhY2hpcWwtZGVtby8uL25vZGVfbW9kdWxlcy9AZ3JhcGhpcWwvcmVhY3QvZGlzdC9pbmZvLWFkZG9uLmVzLmpzP2I2N2YiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIF9fZGVmUHJvcCA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcbnZhciBfX25hbWUgPSAodGFyZ2V0LCB2YWx1ZSkgPT4gX19kZWZQcm9wKHRhcmdldCwgXCJuYW1lXCIsIHsgdmFsdWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9KTtcbmltcG9ydCB7IEMgYXMgQ29kZU1pcnJvciB9IGZyb20gXCIuL2NvZGVtaXJyb3IuZXMuanNcIjtcbmltcG9ydCBcIi4vaW5kZXguZXMuanNcIjtcbmltcG9ydCBcImdyYXBocWxcIjtcbmltcG9ydCBcInJlYWN0XCI7XG5pbXBvcnQgXCJyZWFjdC1kb21cIjtcbkNvZGVNaXJyb3IuZGVmaW5lT3B0aW9uKFwiaW5mb1wiLCBmYWxzZSwgKGNtLCBvcHRpb25zLCBvbGQpID0+IHtcbiAgaWYgKG9sZCAmJiBvbGQgIT09IENvZGVNaXJyb3IuSW5pdCkge1xuICAgIGNvbnN0IG9sZE9uTW91c2VPdmVyID0gY20uc3RhdGUuaW5mby5vbk1vdXNlT3ZlcjtcbiAgICBDb2RlTWlycm9yLm9mZihjbS5nZXRXcmFwcGVyRWxlbWVudCgpLCBcIm1vdXNlb3ZlclwiLCBvbGRPbk1vdXNlT3Zlcik7XG4gICAgY2xlYXJUaW1lb3V0KGNtLnN0YXRlLmluZm8uaG92ZXJUaW1lb3V0KTtcbiAgICBkZWxldGUgY20uc3RhdGUuaW5mbztcbiAgfVxuICBpZiAob3B0aW9ucykge1xuICAgIGNvbnN0IHN0YXRlID0gY20uc3RhdGUuaW5mbyA9IGNyZWF0ZVN0YXRlKG9wdGlvbnMpO1xuICAgIHN0YXRlLm9uTW91c2VPdmVyID0gb25Nb3VzZU92ZXIuYmluZChudWxsLCBjbSk7XG4gICAgQ29kZU1pcnJvci5vbihjbS5nZXRXcmFwcGVyRWxlbWVudCgpLCBcIm1vdXNlb3ZlclwiLCBzdGF0ZS5vbk1vdXNlT3Zlcik7XG4gIH1cbn0pO1xuZnVuY3Rpb24gY3JlYXRlU3RhdGUob3B0aW9ucykge1xuICByZXR1cm4ge1xuICAgIG9wdGlvbnM6IG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IHsgcmVuZGVyOiBvcHRpb25zIH0gOiBvcHRpb25zID09PSB0cnVlID8ge30gOiBvcHRpb25zXG4gIH07XG59XG5fX25hbWUoY3JlYXRlU3RhdGUsIFwiY3JlYXRlU3RhdGVcIik7XG5mdW5jdGlvbiBnZXRIb3ZlclRpbWUoY20pIHtcbiAgY29uc3Qgb3B0aW9ucyA9IGNtLnN0YXRlLmluZm8ub3B0aW9ucztcbiAgcmV0dXJuIChvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMuaG92ZXJUaW1lKSB8fCA1MDA7XG59XG5fX25hbWUoZ2V0SG92ZXJUaW1lLCBcImdldEhvdmVyVGltZVwiKTtcbmZ1bmN0aW9uIG9uTW91c2VPdmVyKGNtLCBlKSB7XG4gIGNvbnN0IHN0YXRlID0gY20uc3RhdGUuaW5mbztcbiAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgfHwgZS5zcmNFbGVtZW50O1xuICBpZiAoISh0YXJnZXQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHRhcmdldC5ub2RlTmFtZSAhPT0gXCJTUEFOXCIgfHwgc3RhdGUuaG92ZXJUaW1lb3V0ICE9PSB2b2lkIDApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgYm94ID0gdGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICBjb25zdCBvbk1vdXNlTW92ZSA9IC8qIEBfX1BVUkVfXyAqLyBfX25hbWUoZnVuY3Rpb24oKSB7XG4gICAgY2xlYXJUaW1lb3V0KHN0YXRlLmhvdmVyVGltZW91dCk7XG4gICAgc3RhdGUuaG92ZXJUaW1lb3V0ID0gc2V0VGltZW91dChvbkhvdmVyLCBob3ZlclRpbWUpO1xuICB9LCBcIm9uTW91c2VNb3ZlXCIpO1xuICBjb25zdCBvbk1vdXNlT3V0ID0gLyogQF9fUFVSRV9fICovIF9fbmFtZShmdW5jdGlvbigpIHtcbiAgICBDb2RlTWlycm9yLm9mZihkb2N1bWVudCwgXCJtb3VzZW1vdmVcIiwgb25Nb3VzZU1vdmUpO1xuICAgIENvZGVNaXJyb3Iub2ZmKGNtLmdldFdyYXBwZXJFbGVtZW50KCksIFwibW91c2VvdXRcIiwgb25Nb3VzZU91dCk7XG4gICAgY2xlYXJUaW1lb3V0KHN0YXRlLmhvdmVyVGltZW91dCk7XG4gICAgc3RhdGUuaG92ZXJUaW1lb3V0ID0gdm9pZCAwO1xuICB9LCBcIm9uTW91c2VPdXRcIik7XG4gIGNvbnN0IG9uSG92ZXIgPSAvKiBAX19QVVJFX18gKi8gX19uYW1lKGZ1bmN0aW9uKCkge1xuICAgIENvZGVNaXJyb3Iub2ZmKGRvY3VtZW50LCBcIm1vdXNlbW92ZVwiLCBvbk1vdXNlTW92ZSk7XG4gICAgQ29kZU1pcnJvci5vZmYoY20uZ2V0V3JhcHBlckVsZW1lbnQoKSwgXCJtb3VzZW91dFwiLCBvbk1vdXNlT3V0KTtcbiAgICBzdGF0ZS5ob3ZlclRpbWVvdXQgPSB2b2lkIDA7XG4gICAgb25Nb3VzZUhvdmVyKGNtLCBib3gpO1xuICB9LCBcIm9uSG92ZXJcIik7XG4gIGNvbnN0IGhvdmVyVGltZSA9IGdldEhvdmVyVGltZShjbSk7XG4gIHN0YXRlLmhvdmVyVGltZW91dCA9IHNldFRpbWVvdXQob25Ib3ZlciwgaG92ZXJUaW1lKTtcbiAgQ29kZU1pcnJvci5vbihkb2N1bWVudCwgXCJtb3VzZW1vdmVcIiwgb25Nb3VzZU1vdmUpO1xuICBDb2RlTWlycm9yLm9uKGNtLmdldFdyYXBwZXJFbGVtZW50KCksIFwibW91c2VvdXRcIiwgb25Nb3VzZU91dCk7XG59XG5fX25hbWUob25Nb3VzZU92ZXIsIFwib25Nb3VzZU92ZXJcIik7XG5mdW5jdGlvbiBvbk1vdXNlSG92ZXIoY20sIGJveCkge1xuICBjb25zdCBwb3MgPSBjbS5jb29yZHNDaGFyKHtcbiAgICBsZWZ0OiAoYm94LmxlZnQgKyBib3gucmlnaHQpIC8gMixcbiAgICB0b3A6IChib3gudG9wICsgYm94LmJvdHRvbSkgLyAyXG4gIH0pO1xuICBjb25zdCBzdGF0ZSA9IGNtLnN0YXRlLmluZm87XG4gIGNvbnN0IG9wdGlvbnMgPSBzdGF0ZS5vcHRpb25zO1xuICBjb25zdCByZW5kZXIgPSBvcHRpb25zLnJlbmRlciB8fCBjbS5nZXRIZWxwZXIocG9zLCBcImluZm9cIik7XG4gIGlmIChyZW5kZXIpIHtcbiAgICBjb25zdCB0b2tlbiA9IGNtLmdldFRva2VuQXQocG9zLCB0cnVlKTtcbiAgICBpZiAodG9rZW4pIHtcbiAgICAgIGNvbnN0IGluZm8gPSByZW5kZXIodG9rZW4sIG9wdGlvbnMsIGNtLCBwb3MpO1xuICAgICAgaWYgKGluZm8pIHtcbiAgICAgICAgc2hvd1BvcHVwKGNtLCBib3gsIGluZm8pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuX19uYW1lKG9uTW91c2VIb3ZlciwgXCJvbk1vdXNlSG92ZXJcIik7XG5mdW5jdGlvbiBzaG93UG9wdXAoY20sIGJveCwgaW5mbykge1xuICBjb25zdCBwb3B1cCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gIHBvcHVwLmNsYXNzTmFtZSA9IFwiQ29kZU1pcnJvci1pbmZvXCI7XG4gIHBvcHVwLmFwcGVuZENoaWxkKGluZm8pO1xuICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHBvcHVwKTtcbiAgY29uc3QgcG9wdXBCb3ggPSBwb3B1cC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgY29uc3QgcG9wdXBTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHBvcHVwKTtcbiAgY29uc3QgcG9wdXBXaWR0aCA9IHBvcHVwQm94LnJpZ2h0IC0gcG9wdXBCb3gubGVmdCArIHBhcnNlRmxvYXQocG9wdXBTdHlsZS5tYXJnaW5MZWZ0KSArIHBhcnNlRmxvYXQocG9wdXBTdHlsZS5tYXJnaW5SaWdodCk7XG4gIGNvbnN0IHBvcHVwSGVpZ2h0ID0gcG9wdXBCb3guYm90dG9tIC0gcG9wdXBCb3gudG9wICsgcGFyc2VGbG9hdChwb3B1cFN0eWxlLm1hcmdpblRvcCkgKyBwYXJzZUZsb2F0KHBvcHVwU3R5bGUubWFyZ2luQm90dG9tKTtcbiAgbGV0IHRvcFBvcyA9IGJveC5ib3R0b207XG4gIGlmIChwb3B1cEhlaWdodCA+IHdpbmRvdy5pbm5lckhlaWdodCAtIGJveC5ib3R0b20gLSAxNSAmJiBib3gudG9wID4gd2luZG93LmlubmVySGVpZ2h0IC0gYm94LmJvdHRvbSkge1xuICAgIHRvcFBvcyA9IGJveC50b3AgLSBwb3B1cEhlaWdodDtcbiAgfVxuICBpZiAodG9wUG9zIDwgMCkge1xuICAgIHRvcFBvcyA9IGJveC5ib3R0b207XG4gIH1cbiAgbGV0IGxlZnRQb3MgPSBNYXRoLm1heCgwLCB3aW5kb3cuaW5uZXJXaWR0aCAtIHBvcHVwV2lkdGggLSAxNSk7XG4gIGlmIChsZWZ0UG9zID4gYm94LmxlZnQpIHtcbiAgICBsZWZ0UG9zID0gYm94LmxlZnQ7XG4gIH1cbiAgcG9wdXAuc3R5bGUub3BhY2l0eSA9IFwiMVwiO1xuICBwb3B1cC5zdHlsZS50b3AgPSB0b3BQb3MgKyBcInB4XCI7XG4gIHBvcHVwLnN0eWxlLmxlZnQgPSBsZWZ0UG9zICsgXCJweFwiO1xuICBsZXQgcG9wdXBUaW1lb3V0O1xuICBjb25zdCBvbk1vdXNlT3ZlclBvcHVwID0gLyogQF9fUFVSRV9fICovIF9fbmFtZShmdW5jdGlvbigpIHtcbiAgICBjbGVhclRpbWVvdXQocG9wdXBUaW1lb3V0KTtcbiAgfSwgXCJvbk1vdXNlT3ZlclBvcHVwXCIpO1xuICBjb25zdCBvbk1vdXNlT3V0ID0gLyogQF9fUFVSRV9fICovIF9fbmFtZShmdW5jdGlvbigpIHtcbiAgICBjbGVhclRpbWVvdXQocG9wdXBUaW1lb3V0KTtcbiAgICBwb3B1cFRpbWVvdXQgPSBzZXRUaW1lb3V0KGhpZGVQb3B1cCwgMjAwKTtcbiAgfSwgXCJvbk1vdXNlT3V0XCIpO1xuICBjb25zdCBoaWRlUG9wdXAgPSAvKiBAX19QVVJFX18gKi8gX19uYW1lKGZ1bmN0aW9uKCkge1xuICAgIENvZGVNaXJyb3Iub2ZmKHBvcHVwLCBcIm1vdXNlb3ZlclwiLCBvbk1vdXNlT3ZlclBvcHVwKTtcbiAgICBDb2RlTWlycm9yLm9mZihwb3B1cCwgXCJtb3VzZW91dFwiLCBvbk1vdXNlT3V0KTtcbiAgICBDb2RlTWlycm9yLm9mZihjbS5nZXRXcmFwcGVyRWxlbWVudCgpLCBcIm1vdXNlb3V0XCIsIG9uTW91c2VPdXQpO1xuICAgIGlmIChwb3B1cC5zdHlsZS5vcGFjaXR5KSB7XG4gICAgICBwb3B1cC5zdHlsZS5vcGFjaXR5ID0gXCIwXCI7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgaWYgKHBvcHVwLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICBwb3B1cC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHBvcHVwKTtcbiAgICAgICAgfVxuICAgICAgfSwgNjAwKTtcbiAgICB9IGVsc2UgaWYgKHBvcHVwLnBhcmVudE5vZGUpIHtcbiAgICAgIHBvcHVwLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQocG9wdXApO1xuICAgIH1cbiAgfSwgXCJoaWRlUG9wdXBcIik7XG4gIENvZGVNaXJyb3Iub24ocG9wdXAsIFwibW91c2VvdmVyXCIsIG9uTW91c2VPdmVyUG9wdXApO1xuICBDb2RlTWlycm9yLm9uKHBvcHVwLCBcIm1vdXNlb3V0XCIsIG9uTW91c2VPdXQpO1xuICBDb2RlTWlycm9yLm9uKGNtLmdldFdyYXBwZXJFbGVtZW50KCksIFwibW91c2VvdXRcIiwgb25Nb3VzZU91dCk7XG59XG5fX25hbWUoc2hvd1BvcHVwLCBcInNob3dQb3B1cFwiKTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///1574\n')}}]); -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/cachiql_(1)-svg_(1).svg: -------------------------------------------------------------------------------- 1 | 2 | cachiql (1)-svg 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /cachiql-demo/dist/768.bundle.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkcachiql_demo=self.webpackChunkcachiql_demo||[]).push([[768],{10768:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "b": () => (/* binding */ braceFold$1)\n/* harmony export */ });\n/* harmony import */ var _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(97480);\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, "name", { value, configurable: true });\n\nfunction _mergeNamespaces(n, m) {\n m.forEach(function(e) {\n e && typeof e !== "string" && !Array.isArray(e) && Object.keys(e).forEach(function(k) {\n if (k !== "default" && !(k in n)) {\n var d = Object.getOwnPropertyDescriptor(e, k);\n Object.defineProperty(n, k, d.get ? d : {\n enumerable: true,\n get: function() {\n return e[k];\n }\n });\n }\n });\n });\n return Object.freeze(n);\n}\n__name(_mergeNamespaces, "_mergeNamespaces");\nvar braceFold$2 = { exports: {} };\n(function(module, exports) {\n (function(mod) {\n mod(_codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.a.exports);\n })(function(CodeMirror) {\n function bracketFolding(pairs) {\n return function(cm, start) {\n var line = start.line, lineText = cm.getLine(line);\n function findOpening(pair) {\n var tokenType;\n for (var at = start.ch, pass = 0; ; ) {\n var found2 = at <= 0 ? -1 : lineText.lastIndexOf(pair[0], at - 1);\n if (found2 == -1) {\n if (pass == 1)\n break;\n pass = 1;\n at = lineText.length;\n continue;\n }\n if (pass == 1 && found2 < start.ch)\n break;\n tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found2 + 1));\n if (!/^(comment|string)/.test(tokenType))\n return { ch: found2 + 1, tokenType, pair };\n at = found2 - 1;\n }\n }\n __name(findOpening, "findOpening");\n function findRange(found2) {\n var count = 1, lastLine = cm.lastLine(), end, startCh = found2.ch, endCh;\n outer:\n for (var i2 = line; i2 <= lastLine; ++i2) {\n var text = cm.getLine(i2), pos = i2 == line ? startCh : 0;\n for (; ; ) {\n var nextOpen = text.indexOf(found2.pair[0], pos), nextClose = text.indexOf(found2.pair[1], pos);\n if (nextOpen < 0)\n nextOpen = text.length;\n if (nextClose < 0)\n nextClose = text.length;\n pos = Math.min(nextOpen, nextClose);\n if (pos == text.length)\n break;\n if (cm.getTokenTypeAt(CodeMirror.Pos(i2, pos + 1)) == found2.tokenType) {\n if (pos == nextOpen)\n ++count;\n else if (!--count) {\n end = i2;\n endCh = pos;\n break outer;\n }\n }\n ++pos;\n }\n }\n if (end == null || line == end)\n return null;\n return {\n from: CodeMirror.Pos(line, startCh),\n to: CodeMirror.Pos(end, endCh)\n };\n }\n __name(findRange, "findRange");\n var found = [];\n for (var i = 0; i < pairs.length; i++) {\n var open = findOpening(pairs[i]);\n if (open)\n found.push(open);\n }\n found.sort(function(a, b) {\n return a.ch - b.ch;\n });\n for (var i = 0; i < found.length; i++) {\n var range = findRange(found[i]);\n if (range)\n return range;\n }\n return null;\n };\n }\n __name(bracketFolding, "bracketFolding");\n CodeMirror.registerHelper("fold", "brace", bracketFolding([["{", "}"], ["[", "]"]]));\n CodeMirror.registerHelper("fold", "brace-paren", bracketFolding([["{", "}"], ["[", "]"], ["(", ")"]]));\n CodeMirror.registerHelper("fold", "import", function(cm, start) {\n function hasImport(line) {\n if (line < cm.firstLine() || line > cm.lastLine())\n return null;\n var start2 = cm.getTokenAt(CodeMirror.Pos(line, 1));\n if (!/\\S/.test(start2.string))\n start2 = cm.getTokenAt(CodeMirror.Pos(line, start2.end + 1));\n if (start2.type != "keyword" || start2.string != "import")\n return null;\n for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) {\n var text = cm.getLine(i), semi = text.indexOf(";");\n if (semi != -1)\n return { startCh: start2.end, end: CodeMirror.Pos(i, semi) };\n }\n }\n __name(hasImport, "hasImport");\n var startLine = start.line, has = hasImport(startLine), prev;\n if (!has || hasImport(startLine - 1) || (prev = hasImport(startLine - 2)) && prev.end.line == startLine - 1)\n return null;\n for (var end = has.end; ; ) {\n var next = hasImport(end.line + 1);\n if (next == null)\n break;\n end = next.end;\n }\n return { from: cm.clipPos(CodeMirror.Pos(startLine, has.startCh + 1)), to: end };\n });\n CodeMirror.registerHelper("fold", "include", function(cm, start) {\n function hasInclude(line) {\n if (line < cm.firstLine() || line > cm.lastLine())\n return null;\n var start2 = cm.getTokenAt(CodeMirror.Pos(line, 1));\n if (!/\\S/.test(start2.string))\n start2 = cm.getTokenAt(CodeMirror.Pos(line, start2.end + 1));\n if (start2.type == "meta" && start2.string.slice(0, 8) == "#include")\n return start2.start + 8;\n }\n __name(hasInclude, "hasInclude");\n var startLine = start.line, has = hasInclude(startLine);\n if (has == null || hasInclude(startLine - 1) != null)\n return null;\n for (var end = startLine; ; ) {\n var next = hasInclude(end + 1);\n if (next == null)\n break;\n ++end;\n }\n return {\n from: CodeMirror.Pos(startLine, has + 1),\n to: cm.clipPos(CodeMirror.Pos(end))\n };\n });\n });\n})();\nvar braceFold = braceFold$2.exports;\nvar braceFold$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ _mergeNamespaces({\n __proto__: null,\n [Symbol.toStringTag]: "Module",\n "default": braceFold\n}, [braceFold$2.exports]));\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTA3NjguanMiLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNBLDREQUE0RCwyQkFBMkI7QUFDbEM7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0wsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0EsUUFBUSx3REFBa0I7QUFDMUIsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLGdCQUFnQjtBQUNoRDtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLGtCQUFrQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Qsd0JBQXdCLGtCQUFrQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLEtBQUs7QUFDdkUsd0VBQXdFLEtBQUs7QUFDN0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUVBQW1FLFFBQVE7QUFDM0UsMERBQTBEO0FBQzFEO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0gsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQzJCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vY2FjaGlxbC1kZW1vLy4vbm9kZV9tb2R1bGVzL0BncmFwaGlxbC9yZWFjdC9kaXN0L2JyYWNlLWZvbGQuZXMuanM/NGNhNCJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgX19kZWZQcm9wID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xudmFyIF9fbmFtZSA9ICh0YXJnZXQsIHZhbHVlKSA9PiBfX2RlZlByb3AodGFyZ2V0LCBcIm5hbWVcIiwgeyB2YWx1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0pO1xuaW1wb3J0IHsgYSBhcyBjb2RlbWlycm9yIH0gZnJvbSBcIi4vY29kZW1pcnJvci5lcy5qc1wiO1xuZnVuY3Rpb24gX21lcmdlTmFtZXNwYWNlcyhuLCBtKSB7XG4gIG0uZm9yRWFjaChmdW5jdGlvbihlKSB7XG4gICAgZSAmJiB0eXBlb2YgZSAhPT0gXCJzdHJpbmdcIiAmJiAhQXJyYXkuaXNBcnJheShlKSAmJiBPYmplY3Qua2V5cyhlKS5mb3JFYWNoKGZ1bmN0aW9uKGspIHtcbiAgICAgIGlmIChrICE9PSBcImRlZmF1bHRcIiAmJiAhKGsgaW4gbikpIHtcbiAgICAgICAgdmFyIGQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGUsIGspO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobiwgaywgZC5nZXQgPyBkIDoge1xuICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBlW2tdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuKTtcbn1cbl9fbmFtZShfbWVyZ2VOYW1lc3BhY2VzLCBcIl9tZXJnZU5hbWVzcGFjZXNcIik7XG52YXIgYnJhY2VGb2xkJDIgPSB7IGV4cG9ydHM6IHt9IH07XG4oZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG4gIChmdW5jdGlvbihtb2QpIHtcbiAgICBtb2QoY29kZW1pcnJvci5leHBvcnRzKTtcbiAgfSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICAgIGZ1bmN0aW9uIGJyYWNrZXRGb2xkaW5nKHBhaXJzKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY20sIHN0YXJ0KSB7XG4gICAgICAgIHZhciBsaW5lID0gc3RhcnQubGluZSwgbGluZVRleHQgPSBjbS5nZXRMaW5lKGxpbmUpO1xuICAgICAgICBmdW5jdGlvbiBmaW5kT3BlbmluZyhwYWlyKSB7XG4gICAgICAgICAgdmFyIHRva2VuVHlwZTtcbiAgICAgICAgICBmb3IgKHZhciBhdCA9IHN0YXJ0LmNoLCBwYXNzID0gMDsgOyApIHtcbiAgICAgICAgICAgIHZhciBmb3VuZDIgPSBhdCA8PSAwID8gLTEgOiBsaW5lVGV4dC5sYXN0SW5kZXhPZihwYWlyWzBdLCBhdCAtIDEpO1xuICAgICAgICAgICAgaWYgKGZvdW5kMiA9PSAtMSkge1xuICAgICAgICAgICAgICBpZiAocGFzcyA9PSAxKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBwYXNzID0gMTtcbiAgICAgICAgICAgICAgYXQgPSBsaW5lVGV4dC5sZW5ndGg7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhc3MgPT0gMSAmJiBmb3VuZDIgPCBzdGFydC5jaClcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB0b2tlblR5cGUgPSBjbS5nZXRUb2tlblR5cGVBdChDb2RlTWlycm9yLlBvcyhsaW5lLCBmb3VuZDIgKyAxKSk7XG4gICAgICAgICAgICBpZiAoIS9eKGNvbW1lbnR8c3RyaW5nKS8udGVzdCh0b2tlblR5cGUpKVxuICAgICAgICAgICAgICByZXR1cm4geyBjaDogZm91bmQyICsgMSwgdG9rZW5UeXBlLCBwYWlyIH07XG4gICAgICAgICAgICBhdCA9IGZvdW5kMiAtIDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIF9fbmFtZShmaW5kT3BlbmluZywgXCJmaW5kT3BlbmluZ1wiKTtcbiAgICAgICAgZnVuY3Rpb24gZmluZFJhbmdlKGZvdW5kMikge1xuICAgICAgICAgIHZhciBjb3VudCA9IDEsIGxhc3RMaW5lID0gY20ubGFzdExpbmUoKSwgZW5kLCBzdGFydENoID0gZm91bmQyLmNoLCBlbmRDaDtcbiAgICAgICAgICBvdXRlcjpcbiAgICAgICAgICAgIGZvciAodmFyIGkyID0gbGluZTsgaTIgPD0gbGFzdExpbmU7ICsraTIpIHtcbiAgICAgICAgICAgICAgdmFyIHRleHQgPSBjbS5nZXRMaW5lKGkyKSwgcG9zID0gaTIgPT0gbGluZSA/IHN0YXJ0Q2ggOiAwO1xuICAgICAgICAgICAgICBmb3IgKDsgOyApIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dE9wZW4gPSB0ZXh0LmluZGV4T2YoZm91bmQyLnBhaXJbMF0sIHBvcyksIG5leHRDbG9zZSA9IHRleHQuaW5kZXhPZihmb3VuZDIucGFpclsxXSwgcG9zKTtcbiAgICAgICAgICAgICAgICBpZiAobmV4dE9wZW4gPCAwKVxuICAgICAgICAgICAgICAgICAgbmV4dE9wZW4gPSB0ZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICBpZiAobmV4dENsb3NlIDwgMClcbiAgICAgICAgICAgICAgICAgIG5leHRDbG9zZSA9IHRleHQubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHBvcyA9IE1hdGgubWluKG5leHRPcGVuLCBuZXh0Q2xvc2UpO1xuICAgICAgICAgICAgICAgIGlmIChwb3MgPT0gdGV4dC5sZW5ndGgpXG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBpZiAoY20uZ2V0VG9rZW5UeXBlQXQoQ29kZU1pcnJvci5Qb3MoaTIsIHBvcyArIDEpKSA9PSBmb3VuZDIudG9rZW5UeXBlKSB7XG4gICAgICAgICAgICAgICAgICBpZiAocG9zID09IG5leHRPcGVuKVxuICAgICAgICAgICAgICAgICAgICArK2NvdW50O1xuICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIS0tY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgZW5kID0gaTI7XG4gICAgICAgICAgICAgICAgICAgIGVuZENoID0gcG9zO1xuICAgICAgICAgICAgICAgICAgICBicmVhayBvdXRlcjtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKytwb3M7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZW5kID09IG51bGwgfHwgbGluZSA9PSBlbmQpXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZnJvbTogQ29kZU1pcnJvci5Qb3MobGluZSwgc3RhcnRDaCksXG4gICAgICAgICAgICB0bzogQ29kZU1pcnJvci5Qb3MoZW5kLCBlbmRDaClcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIF9fbmFtZShmaW5kUmFuZ2UsIFwiZmluZFJhbmdlXCIpO1xuICAgICAgICB2YXIgZm91bmQgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYWlycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBvcGVuID0gZmluZE9wZW5pbmcocGFpcnNbaV0pO1xuICAgICAgICAgIGlmIChvcGVuKVxuICAgICAgICAgICAgZm91bmQucHVzaChvcGVuKTtcbiAgICAgICAgfVxuICAgICAgICBmb3VuZC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICByZXR1cm4gYS5jaCAtIGIuY2g7XG4gICAgICAgIH0pO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZvdW5kLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHJhbmdlID0gZmluZFJhbmdlKGZvdW5kW2ldKTtcbiAgICAgICAgICBpZiAocmFuZ2UpXG4gICAgICAgICAgICByZXR1cm4gcmFuZ2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9O1xuICAgIH1cbiAgICBfX25hbWUoYnJhY2tldEZvbGRpbmcsIFwiYnJhY2tldEZvbGRpbmdcIik7XG4gICAgQ29kZU1pcnJvci5yZWdpc3RlckhlbHBlcihcImZvbGRcIiwgXCJicmFjZVwiLCBicmFja2V0Rm9sZGluZyhbW1wie1wiLCBcIn1cIl0sIFtcIltcIiwgXCJdXCJdXSkpO1xuICAgIENvZGVNaXJyb3IucmVnaXN0ZXJIZWxwZXIoXCJmb2xkXCIsIFwiYnJhY2UtcGFyZW5cIiwgYnJhY2tldEZvbGRpbmcoW1tcIntcIiwgXCJ9XCJdLCBbXCJbXCIsIFwiXVwiXSwgW1wiKFwiLCBcIilcIl1dKSk7XG4gICAgQ29kZU1pcnJvci5yZWdpc3RlckhlbHBlcihcImZvbGRcIiwgXCJpbXBvcnRcIiwgZnVuY3Rpb24oY20sIHN0YXJ0KSB7XG4gICAgICBmdW5jdGlvbiBoYXNJbXBvcnQobGluZSkge1xuICAgICAgICBpZiAobGluZSA8IGNtLmZpcnN0TGluZSgpIHx8IGxpbmUgPiBjbS5sYXN0TGluZSgpKVxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgc3RhcnQyID0gY20uZ2V0VG9rZW5BdChDb2RlTWlycm9yLlBvcyhsaW5lLCAxKSk7XG4gICAgICAgIGlmICghL1xcUy8udGVzdChzdGFydDIuc3RyaW5nKSlcbiAgICAgICAgICBzdGFydDIgPSBjbS5nZXRUb2tlbkF0KENvZGVNaXJyb3IuUG9zKGxpbmUsIHN0YXJ0Mi5lbmQgKyAxKSk7XG4gICAgICAgIGlmIChzdGFydDIudHlwZSAhPSBcImtleXdvcmRcIiB8fCBzdGFydDIuc3RyaW5nICE9IFwiaW1wb3J0XCIpXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGZvciAodmFyIGkgPSBsaW5lLCBlID0gTWF0aC5taW4oY20ubGFzdExpbmUoKSwgbGluZSArIDEwKTsgaSA8PSBlOyArK2kpIHtcbiAgICAgICAgICB2YXIgdGV4dCA9IGNtLmdldExpbmUoaSksIHNlbWkgPSB0ZXh0LmluZGV4T2YoXCI7XCIpO1xuICAgICAgICAgIGlmIChzZW1pICE9IC0xKVxuICAgICAgICAgICAgcmV0dXJuIHsgc3RhcnRDaDogc3RhcnQyLmVuZCwgZW5kOiBDb2RlTWlycm9yLlBvcyhpLCBzZW1pKSB9O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBfX25hbWUoaGFzSW1wb3J0LCBcImhhc0ltcG9ydFwiKTtcbiAgICAgIHZhciBzdGFydExpbmUgPSBzdGFydC5saW5lLCBoYXMgPSBoYXNJbXBvcnQoc3RhcnRMaW5lKSwgcHJldjtcbiAgICAgIGlmICghaGFzIHx8IGhhc0ltcG9ydChzdGFydExpbmUgLSAxKSB8fCAocHJldiA9IGhhc0ltcG9ydChzdGFydExpbmUgLSAyKSkgJiYgcHJldi5lbmQubGluZSA9PSBzdGFydExpbmUgLSAxKVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGZvciAodmFyIGVuZCA9IGhhcy5lbmQ7IDsgKSB7XG4gICAgICAgIHZhciBuZXh0ID0gaGFzSW1wb3J0KGVuZC5saW5lICsgMSk7XG4gICAgICAgIGlmIChuZXh0ID09IG51bGwpXG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGVuZCA9IG5leHQuZW5kO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsgZnJvbTogY20uY2xpcFBvcyhDb2RlTWlycm9yLlBvcyhzdGFydExpbmUsIGhhcy5zdGFydENoICsgMSkpLCB0bzogZW5kIH07XG4gICAgfSk7XG4gICAgQ29kZU1pcnJvci5yZWdpc3RlckhlbHBlcihcImZvbGRcIiwgXCJpbmNsdWRlXCIsIGZ1bmN0aW9uKGNtLCBzdGFydCkge1xuICAgICAgZnVuY3Rpb24gaGFzSW5jbHVkZShsaW5lKSB7XG4gICAgICAgIGlmIChsaW5lIDwgY20uZmlyc3RMaW5lKCkgfHwgbGluZSA+IGNtLmxhc3RMaW5lKCkpXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIHZhciBzdGFydDIgPSBjbS5nZXRUb2tlbkF0KENvZGVNaXJyb3IuUG9zKGxpbmUsIDEpKTtcbiAgICAgICAgaWYgKCEvXFxTLy50ZXN0KHN0YXJ0Mi5zdHJpbmcpKVxuICAgICAgICAgIHN0YXJ0MiA9IGNtLmdldFRva2VuQXQoQ29kZU1pcnJvci5Qb3MobGluZSwgc3RhcnQyLmVuZCArIDEpKTtcbiAgICAgICAgaWYgKHN0YXJ0Mi50eXBlID09IFwibWV0YVwiICYmIHN0YXJ0Mi5zdHJpbmcuc2xpY2UoMCwgOCkgPT0gXCIjaW5jbHVkZVwiKVxuICAgICAgICAgIHJldHVybiBzdGFydDIuc3RhcnQgKyA4O1xuICAgICAgfVxuICAgICAgX19uYW1lKGhhc0luY2x1ZGUsIFwiaGFzSW5jbHVkZVwiKTtcbiAgICAgIHZhciBzdGFydExpbmUgPSBzdGFydC5saW5lLCBoYXMgPSBoYXNJbmNsdWRlKHN0YXJ0TGluZSk7XG4gICAgICBpZiAoaGFzID09IG51bGwgfHwgaGFzSW5jbHVkZShzdGFydExpbmUgLSAxKSAhPSBudWxsKVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGZvciAodmFyIGVuZCA9IHN0YXJ0TGluZTsgOyApIHtcbiAgICAgICAgdmFyIG5leHQgPSBoYXNJbmNsdWRlKGVuZCArIDEpO1xuICAgICAgICBpZiAobmV4dCA9PSBudWxsKVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICArK2VuZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IENvZGVNaXJyb3IuUG9zKHN0YXJ0TGluZSwgaGFzICsgMSksXG4gICAgICAgIHRvOiBjbS5jbGlwUG9zKENvZGVNaXJyb3IuUG9zKGVuZCkpXG4gICAgICB9O1xuICAgIH0pO1xuICB9KTtcbn0pKCk7XG52YXIgYnJhY2VGb2xkID0gYnJhY2VGb2xkJDIuZXhwb3J0cztcbnZhciBicmFjZUZvbGQkMSA9IC8qIEBfX1BVUkVfXyAqLyBPYmplY3QuZnJlZXplKC8qIEBfX1BVUkVfXyAqLyBfbWVyZ2VOYW1lc3BhY2VzKHtcbiAgX19wcm90b19fOiBudWxsLFxuICBbU3ltYm9sLnRvU3RyaW5nVGFnXTogXCJNb2R1bGVcIixcbiAgXCJkZWZhdWx0XCI6IGJyYWNlRm9sZFxufSwgW2JyYWNlRm9sZCQyLmV4cG9ydHNdKSk7XG5leHBvcnQgeyBicmFjZUZvbGQkMSBhcyBiIH07XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///10768\n')}}]); -------------------------------------------------------------------------------- /cachiql-demo/dist/744.bundle.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkcachiql_demo=self.webpackChunkcachiql_demo||[]).push([[744],{19744:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "a": () => (/* binding */ dialog$2),\n/* harmony export */ "d": () => (/* binding */ dialog$1)\n/* harmony export */ });\n/* harmony import */ var _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(97480);\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, "name", { value, configurable: true });\n\nfunction _mergeNamespaces(n, m) {\n m.forEach(function(e) {\n e && typeof e !== "string" && !Array.isArray(e) && Object.keys(e).forEach(function(k) {\n if (k !== "default" && !(k in n)) {\n var d = Object.getOwnPropertyDescriptor(e, k);\n Object.defineProperty(n, k, d.get ? d : {\n enumerable: true,\n get: function() {\n return e[k];\n }\n });\n }\n });\n });\n return Object.freeze(n);\n}\n__name(_mergeNamespaces, "_mergeNamespaces");\nvar dialog$2 = { exports: {} };\n(function(module, exports) {\n (function(mod) {\n mod(_codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.a.exports);\n })(function(CodeMirror) {\n function dialogDiv(cm, template, bottom) {\n var wrap = cm.getWrapperElement();\n var dialog2;\n dialog2 = wrap.appendChild(document.createElement("div"));\n if (bottom)\n dialog2.className = "CodeMirror-dialog CodeMirror-dialog-bottom";\n else\n dialog2.className = "CodeMirror-dialog CodeMirror-dialog-top";\n if (typeof template == "string") {\n dialog2.innerHTML = template;\n } else {\n dialog2.appendChild(template);\n }\n CodeMirror.addClass(wrap, "dialog-opened");\n return dialog2;\n }\n __name(dialogDiv, "dialogDiv");\n function closeNotification(cm, newVal) {\n if (cm.state.currentNotificationClose)\n cm.state.currentNotificationClose();\n cm.state.currentNotificationClose = newVal;\n }\n __name(closeNotification, "closeNotification");\n CodeMirror.defineExtension("openDialog", function(template, callback, options) {\n if (!options)\n options = {};\n closeNotification(this, null);\n var dialog2 = dialogDiv(this, template, options.bottom);\n var closed = false, me = this;\n function close(newVal) {\n if (typeof newVal == "string") {\n inp.value = newVal;\n } else {\n if (closed)\n return;\n closed = true;\n CodeMirror.rmClass(dialog2.parentNode, "dialog-opened");\n dialog2.parentNode.removeChild(dialog2);\n me.focus();\n if (options.onClose)\n options.onClose(dialog2);\n }\n }\n __name(close, "close");\n var inp = dialog2.getElementsByTagName("input")[0], button;\n if (inp) {\n inp.focus();\n if (options.value) {\n inp.value = options.value;\n if (options.selectValueOnOpen !== false) {\n inp.select();\n }\n }\n if (options.onInput)\n CodeMirror.on(inp, "input", function(e) {\n options.onInput(e, inp.value, close);\n });\n if (options.onKeyUp)\n CodeMirror.on(inp, "keyup", function(e) {\n options.onKeyUp(e, inp.value, close);\n });\n CodeMirror.on(inp, "keydown", function(e) {\n if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) {\n return;\n }\n if (e.keyCode == 27 || options.closeOnEnter !== false && e.keyCode == 13) {\n inp.blur();\n CodeMirror.e_stop(e);\n close();\n }\n if (e.keyCode == 13)\n callback(inp.value, e);\n });\n if (options.closeOnBlur !== false)\n CodeMirror.on(dialog2, "focusout", function(evt) {\n if (evt.relatedTarget !== null)\n close();\n });\n } else if (button = dialog2.getElementsByTagName("button")[0]) {\n CodeMirror.on(button, "click", function() {\n close();\n me.focus();\n });\n if (options.closeOnBlur !== false)\n CodeMirror.on(button, "blur", close);\n button.focus();\n }\n return close;\n });\n CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {\n closeNotification(this, null);\n var dialog2 = dialogDiv(this, template, options && options.bottom);\n var buttons = dialog2.getElementsByTagName("button");\n var closed = false, me = this, blurring = 1;\n function close() {\n if (closed)\n return;\n closed = true;\n CodeMirror.rmClass(dialog2.parentNode, "dialog-opened");\n dialog2.parentNode.removeChild(dialog2);\n me.focus();\n }\n __name(close, "close");\n buttons[0].focus();\n for (var i = 0; i < buttons.length; ++i) {\n var b = buttons[i];\n (function(callback) {\n CodeMirror.on(b, "click", function(e) {\n CodeMirror.e_preventDefault(e);\n close();\n if (callback)\n callback(me);\n });\n })(callbacks[i]);\n CodeMirror.on(b, "blur", function() {\n --blurring;\n setTimeout(function() {\n if (blurring <= 0)\n close();\n }, 200);\n });\n CodeMirror.on(b, "focus", function() {\n ++blurring;\n });\n }\n });\n CodeMirror.defineExtension("openNotification", function(template, options) {\n closeNotification(this, close);\n var dialog2 = dialogDiv(this, template, options && options.bottom);\n var closed = false, doneTimer;\n var duration = options && typeof options.duration !== "undefined" ? options.duration : 5e3;\n function close() {\n if (closed)\n return;\n closed = true;\n clearTimeout(doneTimer);\n CodeMirror.rmClass(dialog2.parentNode, "dialog-opened");\n dialog2.parentNode.removeChild(dialog2);\n }\n __name(close, "close");\n CodeMirror.on(dialog2, "click", function(e) {\n CodeMirror.e_preventDefault(e);\n close();\n });\n if (duration)\n doneTimer = setTimeout(close, duration);\n return close;\n });\n });\n})();\nvar dialog = dialog$2.exports;\nvar dialog$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ _mergeNamespaces({\n __proto__: null,\n [Symbol.toStringTag]: "Module",\n "default": dialog\n}, [dialog$2.exports]));\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTk3NDQuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7QUFDQSw0REFBNEQsMkJBQTJCO0FBQ2xDO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLFFBQVEsd0RBQWtCO0FBQzFCLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG9CQUFvQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0gsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ3VDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vY2FjaGlxbC1kZW1vLy4vbm9kZV9tb2R1bGVzL0BncmFwaGlxbC9yZWFjdC9kaXN0L2RpYWxvZy5lcy5qcz84Yjk5Il0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2RlZlByb3AgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG52YXIgX19uYW1lID0gKHRhcmdldCwgdmFsdWUpID0+IF9fZGVmUHJvcCh0YXJnZXQsIFwibmFtZVwiLCB7IHZhbHVlLCBjb25maWd1cmFibGU6IHRydWUgfSk7XG5pbXBvcnQgeyBhIGFzIGNvZGVtaXJyb3IgfSBmcm9tIFwiLi9jb2RlbWlycm9yLmVzLmpzXCI7XG5mdW5jdGlvbiBfbWVyZ2VOYW1lc3BhY2VzKG4sIG0pIHtcbiAgbS5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICBlICYmIHR5cGVvZiBlICE9PSBcInN0cmluZ1wiICYmICFBcnJheS5pc0FycmF5KGUpICYmIE9iamVjdC5rZXlzKGUpLmZvckVhY2goZnVuY3Rpb24oaykge1xuICAgICAgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmICEoayBpbiBuKSkge1xuICAgICAgICB2YXIgZCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoZSwgayk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuLCBrLCBkLmdldCA/IGQgOiB7XG4gICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIGVba107XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG4pO1xufVxuX19uYW1lKF9tZXJnZU5hbWVzcGFjZXMsIFwiX21lcmdlTmFtZXNwYWNlc1wiKTtcbnZhciBkaWFsb2ckMiA9IHsgZXhwb3J0czoge30gfTtcbihmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcbiAgKGZ1bmN0aW9uKG1vZCkge1xuICAgIG1vZChjb2RlbWlycm9yLmV4cG9ydHMpO1xuICB9KShmdW5jdGlvbihDb2RlTWlycm9yKSB7XG4gICAgZnVuY3Rpb24gZGlhbG9nRGl2KGNtLCB0ZW1wbGF0ZSwgYm90dG9tKSB7XG4gICAgICB2YXIgd3JhcCA9IGNtLmdldFdyYXBwZXJFbGVtZW50KCk7XG4gICAgICB2YXIgZGlhbG9nMjtcbiAgICAgIGRpYWxvZzIgPSB3cmFwLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIikpO1xuICAgICAgaWYgKGJvdHRvbSlcbiAgICAgICAgZGlhbG9nMi5jbGFzc05hbWUgPSBcIkNvZGVNaXJyb3ItZGlhbG9nIENvZGVNaXJyb3ItZGlhbG9nLWJvdHRvbVwiO1xuICAgICAgZWxzZVxuICAgICAgICBkaWFsb2cyLmNsYXNzTmFtZSA9IFwiQ29kZU1pcnJvci1kaWFsb2cgQ29kZU1pcnJvci1kaWFsb2ctdG9wXCI7XG4gICAgICBpZiAodHlwZW9mIHRlbXBsYXRlID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgZGlhbG9nMi5pbm5lckhUTUwgPSB0ZW1wbGF0ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpYWxvZzIuYXBwZW5kQ2hpbGQodGVtcGxhdGUpO1xuICAgICAgfVxuICAgICAgQ29kZU1pcnJvci5hZGRDbGFzcyh3cmFwLCBcImRpYWxvZy1vcGVuZWRcIik7XG4gICAgICByZXR1cm4gZGlhbG9nMjtcbiAgICB9XG4gICAgX19uYW1lKGRpYWxvZ0RpdiwgXCJkaWFsb2dEaXZcIik7XG4gICAgZnVuY3Rpb24gY2xvc2VOb3RpZmljYXRpb24oY20sIG5ld1ZhbCkge1xuICAgICAgaWYgKGNtLnN0YXRlLmN1cnJlbnROb3RpZmljYXRpb25DbG9zZSlcbiAgICAgICAgY20uc3RhdGUuY3VycmVudE5vdGlmaWNhdGlvbkNsb3NlKCk7XG4gICAgICBjbS5zdGF0ZS5jdXJyZW50Tm90aWZpY2F0aW9uQ2xvc2UgPSBuZXdWYWw7XG4gICAgfVxuICAgIF9fbmFtZShjbG9zZU5vdGlmaWNhdGlvbiwgXCJjbG9zZU5vdGlmaWNhdGlvblwiKTtcbiAgICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcIm9wZW5EaWFsb2dcIiwgZnVuY3Rpb24odGVtcGxhdGUsIGNhbGxiYWNrLCBvcHRpb25zKSB7XG4gICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgIGNsb3NlTm90aWZpY2F0aW9uKHRoaXMsIG51bGwpO1xuICAgICAgdmFyIGRpYWxvZzIgPSBkaWFsb2dEaXYodGhpcywgdGVtcGxhdGUsIG9wdGlvbnMuYm90dG9tKTtcbiAgICAgIHZhciBjbG9zZWQgPSBmYWxzZSwgbWUgPSB0aGlzO1xuICAgICAgZnVuY3Rpb24gY2xvc2UobmV3VmFsKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbmV3VmFsID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICBpbnAudmFsdWUgPSBuZXdWYWw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGNsb3NlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICBjbG9zZWQgPSB0cnVlO1xuICAgICAgICAgIENvZGVNaXJyb3Iucm1DbGFzcyhkaWFsb2cyLnBhcmVudE5vZGUsIFwiZGlhbG9nLW9wZW5lZFwiKTtcbiAgICAgICAgICBkaWFsb2cyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGlhbG9nMik7XG4gICAgICAgICAgbWUuZm9jdXMoKTtcbiAgICAgICAgICBpZiAob3B0aW9ucy5vbkNsb3NlKVxuICAgICAgICAgICAgb3B0aW9ucy5vbkNsb3NlKGRpYWxvZzIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBfX25hbWUoY2xvc2UsIFwiY2xvc2VcIik7XG4gICAgICB2YXIgaW5wID0gZGlhbG9nMi5nZXRFbGVtZW50c0J5VGFnTmFtZShcImlucHV0XCIpWzBdLCBidXR0b247XG4gICAgICBpZiAoaW5wKSB7XG4gICAgICAgIGlucC5mb2N1cygpO1xuICAgICAgICBpZiAob3B0aW9ucy52YWx1ZSkge1xuICAgICAgICAgIGlucC52YWx1ZSA9IG9wdGlvbnMudmFsdWU7XG4gICAgICAgICAgaWYgKG9wdGlvbnMuc2VsZWN0VmFsdWVPbk9wZW4gIT09IGZhbHNlKSB7XG4gICAgICAgICAgICBpbnAuc2VsZWN0KCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLm9uSW5wdXQpXG4gICAgICAgICAgQ29kZU1pcnJvci5vbihpbnAsIFwiaW5wdXRcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgb3B0aW9ucy5vbklucHV0KGUsIGlucC52YWx1ZSwgY2xvc2UpO1xuICAgICAgICAgIH0pO1xuICAgICAgICBpZiAob3B0aW9ucy5vbktleVVwKVxuICAgICAgICAgIENvZGVNaXJyb3Iub24oaW5wLCBcImtleXVwXCIsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIG9wdGlvbnMub25LZXlVcChlLCBpbnAudmFsdWUsIGNsb3NlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgQ29kZU1pcnJvci5vbihpbnAsIFwia2V5ZG93blwiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5vbktleURvd24gJiYgb3B0aW9ucy5vbktleURvd24oZSwgaW5wLnZhbHVlLCBjbG9zZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGUua2V5Q29kZSA9PSAyNyB8fCBvcHRpb25zLmNsb3NlT25FbnRlciAhPT0gZmFsc2UgJiYgZS5rZXlDb2RlID09IDEzKSB7XG4gICAgICAgICAgICBpbnAuYmx1cigpO1xuICAgICAgICAgICAgQ29kZU1pcnJvci5lX3N0b3AoZSk7XG4gICAgICAgICAgICBjbG9zZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZS5rZXlDb2RlID09IDEzKVxuICAgICAgICAgICAgY2FsbGJhY2soaW5wLnZhbHVlLCBlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChvcHRpb25zLmNsb3NlT25CbHVyICE9PSBmYWxzZSlcbiAgICAgICAgICBDb2RlTWlycm9yLm9uKGRpYWxvZzIsIFwiZm9jdXNvdXRcIiwgZnVuY3Rpb24oZXZ0KSB7XG4gICAgICAgICAgICBpZiAoZXZ0LnJlbGF0ZWRUYXJnZXQgIT09IG51bGwpXG4gICAgICAgICAgICAgIGNsb3NlKCk7XG4gICAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKGJ1dHRvbiA9IGRpYWxvZzIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJidXR0b25cIilbMF0pIHtcbiAgICAgICAgQ29kZU1pcnJvci5vbihidXR0b24sIFwiY2xpY2tcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgY2xvc2UoKTtcbiAgICAgICAgICBtZS5mb2N1cygpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG9wdGlvbnMuY2xvc2VPbkJsdXIgIT09IGZhbHNlKVxuICAgICAgICAgIENvZGVNaXJyb3Iub24oYnV0dG9uLCBcImJsdXJcIiwgY2xvc2UpO1xuICAgICAgICBidXR0b24uZm9jdXMoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjbG9zZTtcbiAgICB9KTtcbiAgICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcIm9wZW5Db25maXJtXCIsIGZ1bmN0aW9uKHRlbXBsYXRlLCBjYWxsYmFja3MsIG9wdGlvbnMpIHtcbiAgICAgIGNsb3NlTm90aWZpY2F0aW9uKHRoaXMsIG51bGwpO1xuICAgICAgdmFyIGRpYWxvZzIgPSBkaWFsb2dEaXYodGhpcywgdGVtcGxhdGUsIG9wdGlvbnMgJiYgb3B0aW9ucy5ib3R0b20pO1xuICAgICAgdmFyIGJ1dHRvbnMgPSBkaWFsb2cyLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiYnV0dG9uXCIpO1xuICAgICAgdmFyIGNsb3NlZCA9IGZhbHNlLCBtZSA9IHRoaXMsIGJsdXJyaW5nID0gMTtcbiAgICAgIGZ1bmN0aW9uIGNsb3NlKCkge1xuICAgICAgICBpZiAoY2xvc2VkKVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgQ29kZU1pcnJvci5ybUNsYXNzKGRpYWxvZzIucGFyZW50Tm9kZSwgXCJkaWFsb2ctb3BlbmVkXCIpO1xuICAgICAgICBkaWFsb2cyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGlhbG9nMik7XG4gICAgICAgIG1lLmZvY3VzKCk7XG4gICAgICB9XG4gICAgICBfX25hbWUoY2xvc2UsIFwiY2xvc2VcIik7XG4gICAgICBidXR0b25zWzBdLmZvY3VzKCk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJ1dHRvbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGIgPSBidXR0b25zW2ldO1xuICAgICAgICAoZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgICBDb2RlTWlycm9yLm9uKGIsIFwiY2xpY2tcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgQ29kZU1pcnJvci5lX3ByZXZlbnREZWZhdWx0KGUpO1xuICAgICAgICAgICAgY2xvc2UoKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaylcbiAgICAgICAgICAgICAgY2FsbGJhY2sobWUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KShjYWxsYmFja3NbaV0pO1xuICAgICAgICBDb2RlTWlycm9yLm9uKGIsIFwiYmx1clwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAtLWJsdXJyaW5nO1xuICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAoYmx1cnJpbmcgPD0gMClcbiAgICAgICAgICAgICAgY2xvc2UoKTtcbiAgICAgICAgICB9LCAyMDApO1xuICAgICAgICB9KTtcbiAgICAgICAgQ29kZU1pcnJvci5vbihiLCBcImZvY3VzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICsrYmx1cnJpbmc7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwib3Blbk5vdGlmaWNhdGlvblwiLCBmdW5jdGlvbih0ZW1wbGF0ZSwgb3B0aW9ucykge1xuICAgICAgY2xvc2VOb3RpZmljYXRpb24odGhpcywgY2xvc2UpO1xuICAgICAgdmFyIGRpYWxvZzIgPSBkaWFsb2dEaXYodGhpcywgdGVtcGxhdGUsIG9wdGlvbnMgJiYgb3B0aW9ucy5ib3R0b20pO1xuICAgICAgdmFyIGNsb3NlZCA9IGZhbHNlLCBkb25lVGltZXI7XG4gICAgICB2YXIgZHVyYXRpb24gPSBvcHRpb25zICYmIHR5cGVvZiBvcHRpb25zLmR1cmF0aW9uICE9PSBcInVuZGVmaW5lZFwiID8gb3B0aW9ucy5kdXJhdGlvbiA6IDVlMztcbiAgICAgIGZ1bmN0aW9uIGNsb3NlKCkge1xuICAgICAgICBpZiAoY2xvc2VkKVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KGRvbmVUaW1lcik7XG4gICAgICAgIENvZGVNaXJyb3Iucm1DbGFzcyhkaWFsb2cyLnBhcmVudE5vZGUsIFwiZGlhbG9nLW9wZW5lZFwiKTtcbiAgICAgICAgZGlhbG9nMi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRpYWxvZzIpO1xuICAgICAgfVxuICAgICAgX19uYW1lKGNsb3NlLCBcImNsb3NlXCIpO1xuICAgICAgQ29kZU1pcnJvci5vbihkaWFsb2cyLCBcImNsaWNrXCIsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgQ29kZU1pcnJvci5lX3ByZXZlbnREZWZhdWx0KGUpO1xuICAgICAgICBjbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBpZiAoZHVyYXRpb24pXG4gICAgICAgIGRvbmVUaW1lciA9IHNldFRpbWVvdXQoY2xvc2UsIGR1cmF0aW9uKTtcbiAgICAgIHJldHVybiBjbG9zZTtcbiAgICB9KTtcbiAgfSk7XG59KSgpO1xudmFyIGRpYWxvZyA9IGRpYWxvZyQyLmV4cG9ydHM7XG52YXIgZGlhbG9nJDEgPSAvKiBAX19QVVJFX18gKi8gT2JqZWN0LmZyZWV6ZSgvKiBAX19QVVJFX18gKi8gX21lcmdlTmFtZXNwYWNlcyh7XG4gIF9fcHJvdG9fXzogbnVsbCxcbiAgW1N5bWJvbC50b1N0cmluZ1RhZ106IFwiTW9kdWxlXCIsXG4gIFwiZGVmYXVsdFwiOiBkaWFsb2dcbn0sIFtkaWFsb2ckMi5leHBvcnRzXSkpO1xuZXhwb3J0IHsgZGlhbG9nJDIgYXMgYSwgZGlhbG9nJDEgYXMgZCB9O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///19744\n')}}]); -------------------------------------------------------------------------------- /cachiql-demo/src/client/assets/white1024.svg: -------------------------------------------------------------------------------- 1 | 2 | cachiql (1)-svg (2)-svg 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /cachiql-demo/dist/980.bundle.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkcachiql_demo=self.webpackChunkcachiql_demo||[]).push([[980],{54980:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "a": () => (/* binding */ matchbrackets$2),\n/* harmony export */ "m": () => (/* binding */ matchbrackets$1)\n/* harmony export */ });\n/* harmony import */ var _codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(97480);\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, "name", { value, configurable: true });\n\nfunction _mergeNamespaces(n, m) {\n m.forEach(function(e) {\n e && typeof e !== "string" && !Array.isArray(e) && Object.keys(e).forEach(function(k) {\n if (k !== "default" && !(k in n)) {\n var d = Object.getOwnPropertyDescriptor(e, k);\n Object.defineProperty(n, k, d.get ? d : {\n enumerable: true,\n get: function() {\n return e[k];\n }\n });\n }\n });\n });\n return Object.freeze(n);\n}\n__name(_mergeNamespaces, "_mergeNamespaces");\nvar matchbrackets$2 = { exports: {} };\n(function(module, exports) {\n (function(mod) {\n mod(_codemirror_es_js__WEBPACK_IMPORTED_MODULE_0__.a.exports);\n })(function(CodeMirror) {\n var ie_lt8 = /MSIE \\d/.test(navigator.userAgent) && (document.documentMode == null || document.documentMode < 8);\n var Pos = CodeMirror.Pos;\n var matching = { "(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<" };\n function bracketRegex(config) {\n return config && config.bracketRegex || /[(){}[\\]]/;\n }\n __name(bracketRegex, "bracketRegex");\n function findMatchingBracket(cm, where, config) {\n var line = cm.getLineHandle(where.line), pos = where.ch - 1;\n var afterCursor = config && config.afterCursor;\n if (afterCursor == null)\n afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className);\n var re = bracketRegex(config);\n var match = !afterCursor && pos >= 0 && re.test(line.text.charAt(pos)) && matching[line.text.charAt(pos)] || re.test(line.text.charAt(pos + 1)) && matching[line.text.charAt(++pos)];\n if (!match)\n return null;\n var dir = match.charAt(1) == ">" ? 1 : -1;\n if (config && config.strict && dir > 0 != (pos == where.ch))\n return null;\n var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));\n var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style, config);\n if (found == null)\n return null;\n return {\n from: Pos(where.line, pos),\n to: found && found.pos,\n match: found && found.ch == match.charAt(0),\n forward: dir > 0\n };\n }\n __name(findMatchingBracket, "findMatchingBracket");\n function scanForBracket(cm, where, dir, style, config) {\n var maxScanLen = config && config.maxScanLineLength || 1e4;\n var maxScanLines = config && config.maxScanLines || 1e3;\n var stack = [];\n var re = bracketRegex(config);\n var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) : Math.max(cm.firstLine() - 1, where.line - maxScanLines);\n for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {\n var line = cm.getLine(lineNo);\n if (!line)\n continue;\n var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;\n if (line.length > maxScanLen)\n continue;\n if (lineNo == where.line)\n pos = where.ch - (dir < 0 ? 1 : 0);\n for (; pos != end; pos += dir) {\n var ch = line.charAt(pos);\n if (re.test(ch) && (style === void 0 || (cm.getTokenTypeAt(Pos(lineNo, pos + 1)) || "") == (style || ""))) {\n var match = matching[ch];\n if (match && match.charAt(1) == ">" == dir > 0)\n stack.push(ch);\n else if (!stack.length)\n return { pos: Pos(lineNo, pos), ch };\n else\n stack.pop();\n }\n }\n }\n return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;\n }\n __name(scanForBracket, "scanForBracket");\n function matchBrackets(cm, autoclear, config) {\n var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1e3, highlightNonMatching = config && config.highlightNonMatching;\n var marks = [], ranges = cm.listSelections();\n for (var i = 0; i < ranges.length; i++) {\n var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config);\n if (match && (match.match || highlightNonMatching !== false) && cm.getLine(match.from.line).length <= maxHighlightLen) {\n var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";\n marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), { className: style }));\n if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)\n marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), { className: style }));\n }\n }\n if (marks.length) {\n if (ie_lt8 && cm.state.focused)\n cm.focus();\n var clear = /* @__PURE__ */ __name(function() {\n cm.operation(function() {\n for (var i2 = 0; i2 < marks.length; i2++)\n marks[i2].clear();\n });\n }, "clear");\n if (autoclear)\n setTimeout(clear, 800);\n else\n return clear;\n }\n }\n __name(matchBrackets, "matchBrackets");\n function doMatchBrackets(cm) {\n cm.operation(function() {\n if (cm.state.matchBrackets.currentlyHighlighted) {\n cm.state.matchBrackets.currentlyHighlighted();\n cm.state.matchBrackets.currentlyHighlighted = null;\n }\n cm.state.matchBrackets.currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);\n });\n }\n __name(doMatchBrackets, "doMatchBrackets");\n function clearHighlighted(cm) {\n if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {\n cm.state.matchBrackets.currentlyHighlighted();\n cm.state.matchBrackets.currentlyHighlighted = null;\n }\n }\n __name(clearHighlighted, "clearHighlighted");\n CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {\n if (old && old != CodeMirror.Init) {\n cm.off("cursorActivity", doMatchBrackets);\n cm.off("focus", doMatchBrackets);\n cm.off("blur", clearHighlighted);\n clearHighlighted(cm);\n }\n if (val) {\n cm.state.matchBrackets = typeof val == "object" ? val : {};\n cm.on("cursorActivity", doMatchBrackets);\n cm.on("focus", doMatchBrackets);\n cm.on("blur", clearHighlighted);\n }\n });\n CodeMirror.defineExtension("matchBrackets", function() {\n matchBrackets(this, true);\n });\n CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig) {\n if (oldConfig || typeof config == "boolean") {\n if (!oldConfig) {\n config = config ? { strict: true } : null;\n } else {\n oldConfig.strict = config;\n config = oldConfig;\n }\n }\n return findMatchingBracket(this, pos, config);\n });\n CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config) {\n return scanForBracket(this, pos, dir, style, config);\n });\n });\n})();\nvar matchbrackets = matchbrackets$2.exports;\nvar matchbrackets$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ _mergeNamespaces({\n __proto__: null,\n [Symbol.toStringTag]: "Module",\n "default": matchbrackets\n}, [matchbrackets$2.exports]));\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNTQ5ODAuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7QUFDQSw0REFBNEQsMkJBQTJCO0FBQ2xDO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBLFFBQVEsd0RBQWtCO0FBQzFCLEdBQUc7QUFDSDtBQUNBO0FBQ0EscUJBQXFCLDhDQUE4QyxLQUFLLE1BQU0sS0FBSztBQUNuRjtBQUNBLG9EQUFvRDtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DLG1CQUFtQjtBQUN2RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxZQUFZO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7QUFDQSx3RkFBd0Ysa0JBQWtCO0FBQzFHO0FBQ0Esb0ZBQW9GLGtCQUFrQjtBQUN0RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QixtQkFBbUI7QUFDaEQ7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsZUFBZTtBQUM3QyxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDcUQiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9jYWNoaXFsLWRlbW8vLi9ub2RlX21vZHVsZXMvQGdyYXBoaXFsL3JlYWN0L2Rpc3QvbWF0Y2hicmFja2V0cy5lcy5qcz9lY2JlIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2RlZlByb3AgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG52YXIgX19uYW1lID0gKHRhcmdldCwgdmFsdWUpID0+IF9fZGVmUHJvcCh0YXJnZXQsIFwibmFtZVwiLCB7IHZhbHVlLCBjb25maWd1cmFibGU6IHRydWUgfSk7XG5pbXBvcnQgeyBhIGFzIGNvZGVtaXJyb3IgfSBmcm9tIFwiLi9jb2RlbWlycm9yLmVzLmpzXCI7XG5mdW5jdGlvbiBfbWVyZ2VOYW1lc3BhY2VzKG4sIG0pIHtcbiAgbS5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICBlICYmIHR5cGVvZiBlICE9PSBcInN0cmluZ1wiICYmICFBcnJheS5pc0FycmF5KGUpICYmIE9iamVjdC5rZXlzKGUpLmZvckVhY2goZnVuY3Rpb24oaykge1xuICAgICAgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmICEoayBpbiBuKSkge1xuICAgICAgICB2YXIgZCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoZSwgayk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuLCBrLCBkLmdldCA/IGQgOiB7XG4gICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIGVba107XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG4pO1xufVxuX19uYW1lKF9tZXJnZU5hbWVzcGFjZXMsIFwiX21lcmdlTmFtZXNwYWNlc1wiKTtcbnZhciBtYXRjaGJyYWNrZXRzJDIgPSB7IGV4cG9ydHM6IHt9IH07XG4oZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG4gIChmdW5jdGlvbihtb2QpIHtcbiAgICBtb2QoY29kZW1pcnJvci5leHBvcnRzKTtcbiAgfSkoZnVuY3Rpb24oQ29kZU1pcnJvcikge1xuICAgIHZhciBpZV9sdDggPSAvTVNJRSBcXGQvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgKGRvY3VtZW50LmRvY3VtZW50TW9kZSA9PSBudWxsIHx8IGRvY3VtZW50LmRvY3VtZW50TW9kZSA8IDgpO1xuICAgIHZhciBQb3MgPSBDb2RlTWlycm9yLlBvcztcbiAgICB2YXIgbWF0Y2hpbmcgPSB7IFwiKFwiOiBcIik+XCIsIFwiKVwiOiBcIig8XCIsIFwiW1wiOiBcIl0+XCIsIFwiXVwiOiBcIls8XCIsIFwie1wiOiBcIn0+XCIsIFwifVwiOiBcIns8XCIsIFwiPFwiOiBcIj4+XCIsIFwiPlwiOiBcIjw8XCIgfTtcbiAgICBmdW5jdGlvbiBicmFja2V0UmVnZXgoY29uZmlnKSB7XG4gICAgICByZXR1cm4gY29uZmlnICYmIGNvbmZpZy5icmFja2V0UmVnZXggfHwgL1soKXt9W1xcXV0vO1xuICAgIH1cbiAgICBfX25hbWUoYnJhY2tldFJlZ2V4LCBcImJyYWNrZXRSZWdleFwiKTtcbiAgICBmdW5jdGlvbiBmaW5kTWF0Y2hpbmdCcmFja2V0KGNtLCB3aGVyZSwgY29uZmlnKSB7XG4gICAgICB2YXIgbGluZSA9IGNtLmdldExpbmVIYW5kbGUod2hlcmUubGluZSksIHBvcyA9IHdoZXJlLmNoIC0gMTtcbiAgICAgIHZhciBhZnRlckN1cnNvciA9IGNvbmZpZyAmJiBjb25maWcuYWZ0ZXJDdXJzb3I7XG4gICAgICBpZiAoYWZ0ZXJDdXJzb3IgPT0gbnVsbClcbiAgICAgICAgYWZ0ZXJDdXJzb3IgPSAvKF58ICljbS1mYXQtY3Vyc29yKCR8ICkvLnRlc3QoY20uZ2V0V3JhcHBlckVsZW1lbnQoKS5jbGFzc05hbWUpO1xuICAgICAgdmFyIHJlID0gYnJhY2tldFJlZ2V4KGNvbmZpZyk7XG4gICAgICB2YXIgbWF0Y2ggPSAhYWZ0ZXJDdXJzb3IgJiYgcG9zID49IDAgJiYgcmUudGVzdChsaW5lLnRleHQuY2hhckF0KHBvcykpICYmIG1hdGNoaW5nW2xpbmUudGV4dC5jaGFyQXQocG9zKV0gfHwgcmUudGVzdChsaW5lLnRleHQuY2hhckF0KHBvcyArIDEpKSAmJiBtYXRjaGluZ1tsaW5lLnRleHQuY2hhckF0KCsrcG9zKV07XG4gICAgICBpZiAoIW1hdGNoKVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIHZhciBkaXIgPSBtYXRjaC5jaGFyQXQoMSkgPT0gXCI+XCIgPyAxIDogLTE7XG4gICAgICBpZiAoY29uZmlnICYmIGNvbmZpZy5zdHJpY3QgJiYgZGlyID4gMCAhPSAocG9zID09IHdoZXJlLmNoKSlcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB2YXIgc3R5bGUgPSBjbS5nZXRUb2tlblR5cGVBdChQb3Mod2hlcmUubGluZSwgcG9zICsgMSkpO1xuICAgICAgdmFyIGZvdW5kID0gc2NhbkZvckJyYWNrZXQoY20sIFBvcyh3aGVyZS5saW5lLCBwb3MgKyAoZGlyID4gMCA/IDEgOiAwKSksIGRpciwgc3R5bGUsIGNvbmZpZyk7XG4gICAgICBpZiAoZm91bmQgPT0gbnVsbClcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBmcm9tOiBQb3Mod2hlcmUubGluZSwgcG9zKSxcbiAgICAgICAgdG86IGZvdW5kICYmIGZvdW5kLnBvcyxcbiAgICAgICAgbWF0Y2g6IGZvdW5kICYmIGZvdW5kLmNoID09IG1hdGNoLmNoYXJBdCgwKSxcbiAgICAgICAgZm9yd2FyZDogZGlyID4gMFxuICAgICAgfTtcbiAgICB9XG4gICAgX19uYW1lKGZpbmRNYXRjaGluZ0JyYWNrZXQsIFwiZmluZE1hdGNoaW5nQnJhY2tldFwiKTtcbiAgICBmdW5jdGlvbiBzY2FuRm9yQnJhY2tldChjbSwgd2hlcmUsIGRpciwgc3R5bGUsIGNvbmZpZykge1xuICAgICAgdmFyIG1heFNjYW5MZW4gPSBjb25maWcgJiYgY29uZmlnLm1heFNjYW5MaW5lTGVuZ3RoIHx8IDFlNDtcbiAgICAgIHZhciBtYXhTY2FuTGluZXMgPSBjb25maWcgJiYgY29uZmlnLm1heFNjYW5MaW5lcyB8fCAxZTM7XG4gICAgICB2YXIgc3RhY2sgPSBbXTtcbiAgICAgIHZhciByZSA9IGJyYWNrZXRSZWdleChjb25maWcpO1xuICAgICAgdmFyIGxpbmVFbmQgPSBkaXIgPiAwID8gTWF0aC5taW4od2hlcmUubGluZSArIG1heFNjYW5MaW5lcywgY20ubGFzdExpbmUoKSArIDEpIDogTWF0aC5tYXgoY20uZmlyc3RMaW5lKCkgLSAxLCB3aGVyZS5saW5lIC0gbWF4U2NhbkxpbmVzKTtcbiAgICAgIGZvciAodmFyIGxpbmVObyA9IHdoZXJlLmxpbmU7IGxpbmVObyAhPSBsaW5lRW5kOyBsaW5lTm8gKz0gZGlyKSB7XG4gICAgICAgIHZhciBsaW5lID0gY20uZ2V0TGluZShsaW5lTm8pO1xuICAgICAgICBpZiAoIWxpbmUpXG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIHZhciBwb3MgPSBkaXIgPiAwID8gMCA6IGxpbmUubGVuZ3RoIC0gMSwgZW5kID0gZGlyID4gMCA/IGxpbmUubGVuZ3RoIDogLTE7XG4gICAgICAgIGlmIChsaW5lLmxlbmd0aCA+IG1heFNjYW5MZW4pXG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIGlmIChsaW5lTm8gPT0gd2hlcmUubGluZSlcbiAgICAgICAgICBwb3MgPSB3aGVyZS5jaCAtIChkaXIgPCAwID8gMSA6IDApO1xuICAgICAgICBmb3IgKDsgcG9zICE9IGVuZDsgcG9zICs9IGRpcikge1xuICAgICAgICAgIHZhciBjaCA9IGxpbmUuY2hhckF0KHBvcyk7XG4gICAgICAgICAgaWYgKHJlLnRlc3QoY2gpICYmIChzdHlsZSA9PT0gdm9pZCAwIHx8IChjbS5nZXRUb2tlblR5cGVBdChQb3MobGluZU5vLCBwb3MgKyAxKSkgfHwgXCJcIikgPT0gKHN0eWxlIHx8IFwiXCIpKSkge1xuICAgICAgICAgICAgdmFyIG1hdGNoID0gbWF0Y2hpbmdbY2hdO1xuICAgICAgICAgICAgaWYgKG1hdGNoICYmIG1hdGNoLmNoYXJBdCgxKSA9PSBcIj5cIiA9PSBkaXIgPiAwKVxuICAgICAgICAgICAgICBzdGFjay5wdXNoKGNoKTtcbiAgICAgICAgICAgIGVsc2UgaWYgKCFzdGFjay5sZW5ndGgpXG4gICAgICAgICAgICAgIHJldHVybiB7IHBvczogUG9zKGxpbmVObywgcG9zKSwgY2ggfTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgc3RhY2sucG9wKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbGluZU5vIC0gZGlyID09IChkaXIgPiAwID8gY20ubGFzdExpbmUoKSA6IGNtLmZpcnN0TGluZSgpKSA/IGZhbHNlIDogbnVsbDtcbiAgICB9XG4gICAgX19uYW1lKHNjYW5Gb3JCcmFja2V0LCBcInNjYW5Gb3JCcmFja2V0XCIpO1xuICAgIGZ1bmN0aW9uIG1hdGNoQnJhY2tldHMoY20sIGF1dG9jbGVhciwgY29uZmlnKSB7XG4gICAgICB2YXIgbWF4SGlnaGxpZ2h0TGVuID0gY20uc3RhdGUubWF0Y2hCcmFja2V0cy5tYXhIaWdobGlnaHRMaW5lTGVuZ3RoIHx8IDFlMywgaGlnaGxpZ2h0Tm9uTWF0Y2hpbmcgPSBjb25maWcgJiYgY29uZmlnLmhpZ2hsaWdodE5vbk1hdGNoaW5nO1xuICAgICAgdmFyIG1hcmtzID0gW10sIHJhbmdlcyA9IGNtLmxpc3RTZWxlY3Rpb25zKCk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbWF0Y2ggPSByYW5nZXNbaV0uZW1wdHkoKSAmJiBmaW5kTWF0Y2hpbmdCcmFja2V0KGNtLCByYW5nZXNbaV0uaGVhZCwgY29uZmlnKTtcbiAgICAgICAgaWYgKG1hdGNoICYmIChtYXRjaC5tYXRjaCB8fCBoaWdobGlnaHROb25NYXRjaGluZyAhPT0gZmFsc2UpICYmIGNtLmdldExpbmUobWF0Y2guZnJvbS5saW5lKS5sZW5ndGggPD0gbWF4SGlnaGxpZ2h0TGVuKSB7XG4gICAgICAgICAgdmFyIHN0eWxlID0gbWF0Y2gubWF0Y2ggPyBcIkNvZGVNaXJyb3ItbWF0Y2hpbmdicmFja2V0XCIgOiBcIkNvZGVNaXJyb3Itbm9ubWF0Y2hpbmdicmFja2V0XCI7XG4gICAgICAgICAgbWFya3MucHVzaChjbS5tYXJrVGV4dChtYXRjaC5mcm9tLCBQb3MobWF0Y2guZnJvbS5saW5lLCBtYXRjaC5mcm9tLmNoICsgMSksIHsgY2xhc3NOYW1lOiBzdHlsZSB9KSk7XG4gICAgICAgICAgaWYgKG1hdGNoLnRvICYmIGNtLmdldExpbmUobWF0Y2gudG8ubGluZSkubGVuZ3RoIDw9IG1heEhpZ2hsaWdodExlbilcbiAgICAgICAgICAgIG1hcmtzLnB1c2goY20ubWFya1RleHQobWF0Y2gudG8sIFBvcyhtYXRjaC50by5saW5lLCBtYXRjaC50by5jaCArIDEpLCB7IGNsYXNzTmFtZTogc3R5bGUgfSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobWFya3MubGVuZ3RoKSB7XG4gICAgICAgIGlmIChpZV9sdDggJiYgY20uc3RhdGUuZm9jdXNlZClcbiAgICAgICAgICBjbS5mb2N1cygpO1xuICAgICAgICB2YXIgY2xlYXIgPSAvKiBAX19QVVJFX18gKi8gX19uYW1lKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGNtLm9wZXJhdGlvbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkyID0gMDsgaTIgPCBtYXJrcy5sZW5ndGg7IGkyKyspXG4gICAgICAgICAgICAgIG1hcmtzW2kyXS5jbGVhcigpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9LCBcImNsZWFyXCIpO1xuICAgICAgICBpZiAoYXV0b2NsZWFyKVxuICAgICAgICAgIHNldFRpbWVvdXQoY2xlYXIsIDgwMCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICByZXR1cm4gY2xlYXI7XG4gICAgICB9XG4gICAgfVxuICAgIF9fbmFtZShtYXRjaEJyYWNrZXRzLCBcIm1hdGNoQnJhY2tldHNcIik7XG4gICAgZnVuY3Rpb24gZG9NYXRjaEJyYWNrZXRzKGNtKSB7XG4gICAgICBjbS5vcGVyYXRpb24oZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmIChjbS5zdGF0ZS5tYXRjaEJyYWNrZXRzLmN1cnJlbnRseUhpZ2hsaWdodGVkKSB7XG4gICAgICAgICAgY20uc3RhdGUubWF0Y2hCcmFja2V0cy5jdXJyZW50bHlIaWdobGlnaHRlZCgpO1xuICAgICAgICAgIGNtLnN0YXRlLm1hdGNoQnJhY2tldHMuY3VycmVudGx5SGlnaGxpZ2h0ZWQgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNtLnN0YXRlLm1hdGNoQnJhY2tldHMuY3VycmVudGx5SGlnaGxpZ2h0ZWQgPSBtYXRjaEJyYWNrZXRzKGNtLCBmYWxzZSwgY20uc3RhdGUubWF0Y2hCcmFja2V0cyk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgX19uYW1lKGRvTWF0Y2hCcmFja2V0cywgXCJkb01hdGNoQnJhY2tldHNcIik7XG4gICAgZnVuY3Rpb24gY2xlYXJIaWdobGlnaHRlZChjbSkge1xuICAgICAgaWYgKGNtLnN0YXRlLm1hdGNoQnJhY2tldHMgJiYgY20uc3RhdGUubWF0Y2hCcmFja2V0cy5jdXJyZW50bHlIaWdobGlnaHRlZCkge1xuICAgICAgICBjbS5zdGF0ZS5tYXRjaEJyYWNrZXRzLmN1cnJlbnRseUhpZ2hsaWdodGVkKCk7XG4gICAgICAgIGNtLnN0YXRlLm1hdGNoQnJhY2tldHMuY3VycmVudGx5SGlnaGxpZ2h0ZWQgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICBfX25hbWUoY2xlYXJIaWdobGlnaHRlZCwgXCJjbGVhckhpZ2hsaWdodGVkXCIpO1xuICAgIENvZGVNaXJyb3IuZGVmaW5lT3B0aW9uKFwibWF0Y2hCcmFja2V0c1wiLCBmYWxzZSwgZnVuY3Rpb24oY20sIHZhbCwgb2xkKSB7XG4gICAgICBpZiAob2xkICYmIG9sZCAhPSBDb2RlTWlycm9yLkluaXQpIHtcbiAgICAgICAgY20ub2ZmKFwiY3Vyc29yQWN0aXZpdHlcIiwgZG9NYXRjaEJyYWNrZXRzKTtcbiAgICAgICAgY20ub2ZmKFwiZm9jdXNcIiwgZG9NYXRjaEJyYWNrZXRzKTtcbiAgICAgICAgY20ub2ZmKFwiYmx1clwiLCBjbGVhckhpZ2hsaWdodGVkKTtcbiAgICAgICAgY2xlYXJIaWdobGlnaHRlZChjbSk7XG4gICAgICB9XG4gICAgICBpZiAodmFsKSB7XG4gICAgICAgIGNtLnN0YXRlLm1hdGNoQnJhY2tldHMgPSB0eXBlb2YgdmFsID09IFwib2JqZWN0XCIgPyB2YWwgOiB7fTtcbiAgICAgICAgY20ub24oXCJjdXJzb3JBY3Rpdml0eVwiLCBkb01hdGNoQnJhY2tldHMpO1xuICAgICAgICBjbS5vbihcImZvY3VzXCIsIGRvTWF0Y2hCcmFja2V0cyk7XG4gICAgICAgIGNtLm9uKFwiYmx1clwiLCBjbGVhckhpZ2hsaWdodGVkKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBDb2RlTWlycm9yLmRlZmluZUV4dGVuc2lvbihcIm1hdGNoQnJhY2tldHNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICBtYXRjaEJyYWNrZXRzKHRoaXMsIHRydWUpO1xuICAgIH0pO1xuICAgIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwiZmluZE1hdGNoaW5nQnJhY2tldFwiLCBmdW5jdGlvbihwb3MsIGNvbmZpZywgb2xkQ29uZmlnKSB7XG4gICAgICBpZiAob2xkQ29uZmlnIHx8IHR5cGVvZiBjb25maWcgPT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgaWYgKCFvbGRDb25maWcpIHtcbiAgICAgICAgICBjb25maWcgPSBjb25maWcgPyB7IHN0cmljdDogdHJ1ZSB9IDogbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRDb25maWcuc3RyaWN0ID0gY29uZmlnO1xuICAgICAgICAgIGNvbmZpZyA9IG9sZENvbmZpZztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZpbmRNYXRjaGluZ0JyYWNrZXQodGhpcywgcG9zLCBjb25maWcpO1xuICAgIH0pO1xuICAgIENvZGVNaXJyb3IuZGVmaW5lRXh0ZW5zaW9uKFwic2NhbkZvckJyYWNrZXRcIiwgZnVuY3Rpb24ocG9zLCBkaXIsIHN0eWxlLCBjb25maWcpIHtcbiAgICAgIHJldHVybiBzY2FuRm9yQnJhY2tldCh0aGlzLCBwb3MsIGRpciwgc3R5bGUsIGNvbmZpZyk7XG4gICAgfSk7XG4gIH0pO1xufSkoKTtcbnZhciBtYXRjaGJyYWNrZXRzID0gbWF0Y2hicmFja2V0cyQyLmV4cG9ydHM7XG52YXIgbWF0Y2hicmFja2V0cyQxID0gLyogQF9fUFVSRV9fICovIE9iamVjdC5mcmVlemUoLyogQF9fUFVSRV9fICovIF9tZXJnZU5hbWVzcGFjZXMoe1xuICBfX3Byb3RvX186IG51bGwsXG4gIFtTeW1ib2wudG9TdHJpbmdUYWddOiBcIk1vZHVsZVwiLFxuICBcImRlZmF1bHRcIjogbWF0Y2hicmFja2V0c1xufSwgW21hdGNoYnJhY2tldHMkMi5leHBvcnRzXSkpO1xuZXhwb3J0IHsgbWF0Y2hicmFja2V0cyQyIGFzIGEsIG1hdGNoYnJhY2tldHMkMSBhcyBtIH07XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///54980\n')}}]); --------------------------------------------------------------------------------